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