home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / libc / ansi / stdlib / strtoll.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-24  |  1.6 KB  |  80 lines

  1. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
  3. #include <limits.h>
  4. #include <ctype.h>
  5. #include <errno.h>
  6. #include <stdlib.h>
  7. #include <libc/unconst.h>
  8.  
  9. long long
  10. strtoll(const char *nptr, char **endptr, int base)
  11. {
  12.   const char *s = nptr;
  13.   unsigned long long acc;
  14.   int c;
  15.   unsigned long long cutoff;
  16.   int neg = 0, any, cutlim;
  17.  
  18.   /*
  19.    * See strtol for comments as to the logic used.
  20.    */
  21.   do {
  22.     c = *s++;
  23.   } while (isspace(c));
  24.   if (c == '-')
  25.   {
  26.     neg = 1;
  27.     c = *s++;
  28.   }
  29.   else if (c == '+')
  30.     c = *s++;
  31.   if ((base == 0 || base == 16) &&
  32.       c == '0' && (*s == 'x' || *s == 'X'))
  33.   {
  34.     c = s[1];
  35.     s += 2;
  36.     base = 16;
  37.   }
  38.   if (base == 0)
  39.     base = c == '0' ? 8 : 10;
  40.  
  41. /* to prevent overflow, we take max-1 and add 1 after division */
  42.   cutoff = neg ? -(LLONG_MIN+1) : LLONG_MAX-1;
  43.   cutlim = cutoff % base;
  44.   cutoff /= base;
  45.   if (++cutlim == base)
  46.   {
  47.     cutlim = 0;
  48.     cutoff++;
  49.   }
  50.   for (acc = 0, any = 0;; c = *s++)
  51.   {
  52.     if (isdigit(c))
  53.       c -= '0';
  54.     else if (isalpha(c))
  55.       c -= isupper(c) ? 'A' - 10 : 'a' - 10;
  56.     else
  57.       break;
  58.     if (c >= base)
  59.       break;
  60.     if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
  61.       any = -1;
  62.     else
  63.     {
  64.       any = 1;
  65.       acc *= base;
  66.       acc += c;
  67.     }
  68.   }
  69.   if (any < 0)
  70.   {
  71.     acc = neg ? LLONG_MIN : LLONG_MAX;
  72.     errno = ERANGE;
  73.   }
  74.   else if (neg)
  75.     acc = -acc;
  76.   if (endptr != 0)
  77.     *endptr = any ? unconst(s, char *) - 1 : unconst(nptr, char *);
  78.   return acc;
  79. }
  80.