|
|
1.1 root 1: /*
2: * strtoul.c --
3: *
4: * Source code for the "strtoul" library procedure.
5: *
6: * Copyright 1988 Regents of the University of California
7: * Permission to use, copy, modify, and distribute this
8: * software and its documentation for any purpose and without
9: * fee is hereby granted, provided that the above copyright
10: * notice appear in all copies. The University of California
11: * makes no representations about the suitability of this
12: * software for any purpose. It is provided "as is" without
13: * express or implied warranty.
14: */
15:
16: #ifndef lint
17: static char rcsid[] = "$Header: /sprite/src/lib/c/stdlib/RCS/strtoul.c,v 1.2 89/03/22 00:47:33 rab Exp $ SPRITE (Berkeley)";
18: #endif /* not lint */
19:
20: #include <sprite.h>
21: #include <stdlib.h>
22: #include <ctype.h>
23:
24: /*
25: * The table below is used to convert from ASCII digits to a
26: * numerical equivalent. It maps from '0' through 'z' to integers
27: * (100 for non-digit characters).
28: */
29:
30: static char cvtIn[] = {
31: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */
32: 100, 100, 100, 100, 100, 100, 100, /* punctuation */
33: 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'A' - 'Z' */
34: 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
35: 30, 31, 32, 33, 34, 35,
36: 100, 100, 100, 100, 100, 100, /* punctuation */
37: 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'a' - 'z' */
38: 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
39: 30, 31, 32, 33, 34, 35};
40:
41: /*
42: *----------------------------------------------------------------------
43: *
44: * strtoul --
45: *
46: * Convert an ASCII string into an integer.
47: *
48: * Results:
49: * The return value is the integer equivalent of string. If endPtr
50: * is non-NULL, then *endPtr is filled in with the character
51: * after the last one that was part of the integer. If string
52: * doesn't contain a valid integer value, then zero is returned
53: * and *endPtr is set to string.
54: *
55: * Side effects:
56: * None.
57: *
58: *----------------------------------------------------------------------
59: */
60:
61: unsigned long int
62: strtoul(string, endPtr, base)
63: char *string; /* String of ASCII digits, possibly
64: * preceded by white space. For bases
65: * greater than 10, either lower- or
66: * upper-case digits may be used.
67: */
68: char **endPtr; /* Where to store address of terminating
69: * character, or NULL. */
70: int base; /* Base for conversion. Must be less
71: * than 37. If 0, then the base is chosen
72: * from the leading characters of string:
73: * "0x" means hex, "0" means octal, anything
74: * else means decimal.
75: */
76: {
77: register char *p;
78: register unsigned long int result = 0;
79: register unsigned digit;
80: int anyDigits = FALSE;
81:
82: /*
83: * Skip any leading blanks.
84: */
85:
86: p = string;
87: while (isspace(*p)) {
88: p += 1;
89: }
90:
91: /*
92: * If no base was provided, pick one from the leading characters
93: * of the string.
94: */
95:
96: if (base == 0)
97: {
98: if (*p == '0') {
99: p += 1;
100: if (*p == 'x') {
101: p += 1;
102: base = 16;
103: } else {
104:
105: /*
106: * Must set anyDigits here, otherwise "0" produces a
107: * "no digits" error.
108: */
109:
110: anyDigits = TRUE;
111: base = 8;
112: }
113: }
114: else base = 10;
115: } else if (base == 16) {
116:
117: /*
118: * Skip a leading "0x" from hex numbers.
119: */
120:
121: if ((p[0] == '0') && (p[1] == 'x')) {
122: p += 2;
123: }
124: }
125:
126: /*
127: * Sorry this code is so messy, but speed seems important. Do
128: * different things for base 8, 10, 16, and other.
129: */
130:
131: if (base == 8) {
132: for ( ; ; p += 1) {
133: digit = *p - '0';
134: if (digit > 7) {
135: break;
136: }
137: result = (result << 3) + digit;
138: anyDigits = TRUE;
139: }
140: } else if (base == 10) {
141: for ( ; ; p += 1) {
142: digit = *p - '0';
143: if (digit > 9) {
144: break;
145: }
146: result = (10*result) + digit;
147: anyDigits = TRUE;
148: }
149: } else if (base == 16) {
150: for ( ; ; p += 1) {
151: digit = *p - '0';
152: if (digit > ('z' - '0')) {
153: break;
154: }
155: digit = cvtIn[digit];
156: if (digit > 15) {
157: break;
158: }
159: result = (result << 4) + digit;
160: anyDigits = TRUE;
161: }
162: } else {
163: for ( ; ; p += 1) {
164: digit = *p - '0';
165: if (digit > ('z' - '0')) {
166: break;
167: }
168: digit = cvtIn[digit];
169: if (digit >= base) {
170: break;
171: }
172: result = result*base + digit;
173: anyDigits = TRUE;
174: }
175: }
176:
177: /*
178: * See if there were any digits at all.
179: */
180:
181: if (!anyDigits) {
182: p = string;
183: }
184:
185: if (endPtr != NULL) {
186: *endPtr = p;
187: }
188:
189: return result;
190: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.