|
|
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.