missing/strtoul.c


DEFINITIONS

This source file includes following functions.
  1. strtoul


   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 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  
  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(string, endPtr, base)
  57      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 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 = p;
 181      }
 182  
 183      return result;
 184  }