Annotation of micropolis/src/tcl/compat/strtoul.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.