strtol.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. /* $Id$ */
  6. #include <ctype.h>
  7. #include <errno.h>
  8. #include <limits.h>
  9. #include <stdlib.h>
  10. static unsigned long
  11. string2long(register const char *nptr, char **endptr,
  12. int base, int is_signed);
  13. long int
  14. strtol(register const char *nptr, char **endptr, int base)
  15. {
  16. return (signed long)string2long(nptr, endptr, base, 1);
  17. }
  18. unsigned long int
  19. strtoul(register const char *nptr, char **endptr, int base)
  20. {
  21. return (unsigned long)string2long(nptr, endptr, base, 0);
  22. }
  23. static unsigned long
  24. string2long(register const char *nptr, char ** const endptr,
  25. int base, int is_signed)
  26. {
  27. register unsigned int v;
  28. register unsigned long val = 0;
  29. register int c;
  30. int ovfl = 0, sign = 1;
  31. const char *startnptr = nptr, *nrstart;
  32. if (endptr) *endptr = (char *)nptr;
  33. while (isspace(*nptr)) nptr++;
  34. c = *nptr;
  35. if (c == '-' || c == '+') {
  36. if (c == '-') sign = -1;
  37. nptr++;
  38. }
  39. nrstart = nptr; /* start of the number */
  40. /* When base is 0, the syntax determines the actual base */
  41. if (base == 0)
  42. if (*nptr == '0')
  43. if (*++nptr == 'x' || *nptr == 'X') {
  44. base = 16;
  45. nptr++;
  46. }
  47. else base = 8;
  48. else base = 10;
  49. else if (base==16 && *nptr=='0' && (*++nptr =='x' || *nptr =='X'))
  50. nptr++;
  51. while (isdigit(c = *nptr) || isalpha(c)) {
  52. if (!ovfl) {
  53. if (isalpha(c))
  54. v = 10 + (isupper(c) ? c - 'A' : c - 'a');
  55. else
  56. v = c - '0';
  57. if (v >= base) break;
  58. if (val > (ULONG_MAX - v) / base) ++ovfl;
  59. else val = (val * base) + v;
  60. }
  61. nptr++;
  62. }
  63. if (endptr) {
  64. if (nrstart == nptr) *endptr = (char *)startnptr;
  65. else *endptr = (char *)nptr;
  66. }
  67. if (!ovfl) {
  68. /* Overflow is only possible when converting a signed long.
  69. * The "-(LONG_MIN+1)+(unsigned long) 1" construction is there
  70. * to prevent overflow warnings on -LONG_MIN.
  71. */
  72. if (is_signed
  73. && ( (sign < 0 && val > -(LONG_MIN+1)+(unsigned long) 1)
  74. || (sign > 0 && val > LONG_MAX)))
  75. ovfl++;
  76. }
  77. if (ovfl) {
  78. errno = ERANGE;
  79. if (is_signed)
  80. if (sign < 0) return LONG_MIN;
  81. else return LONG_MAX;
  82. else return ULONG_MAX;
  83. }
  84. return (sign * val);
  85. }