(linenum→info "unix/slp.c:2238")

ruby/1.9.0/missing/strtoul.c

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