/contrib/cvs/lib/strtoul.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 100 lines · 82 code · 10 blank · 8 comment · 37 complexity · 22f302311850eef58afe67796d99cb40 MD5 · raw file

  1. /*
  2. * strtol : convert a string to long.
  3. *
  4. * Andy Wilson, 2-Oct-89.
  5. */
  6. #include <errno.h>
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #ifdef HAVE_CONFIG_H
  10. #include "config.h"
  11. #endif
  12. #ifndef ULONG_MAX
  13. #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
  14. #endif
  15. extern int errno;
  16. unsigned long
  17. strtoul(s, ptr, base)
  18. const char *s; char **ptr; int base;
  19. {
  20. unsigned long total = 0;
  21. unsigned digit;
  22. const char *start=s;
  23. int did_conversion=0;
  24. int overflow = 0;
  25. int negate = 0;
  26. unsigned long maxdiv, maxrem;
  27. if (s==NULL)
  28. {
  29. errno = ERANGE;
  30. if (!ptr)
  31. *ptr = (char *)start;
  32. return 0L;
  33. }
  34. while (isspace(*s))
  35. s++;
  36. if (*s == '+')
  37. s++;
  38. else if (*s == '-')
  39. s++, negate = 1;
  40. if (base==0 || base==16) /* the 'base==16' is for handling 0x */
  41. {
  42. int tmp;
  43. /*
  44. * try to infer base from the string
  45. */
  46. if (*s != '0')
  47. tmp = 10; /* doesn't start with 0 - assume decimal */
  48. else if (s[1] == 'X' || s[1] == 'x')
  49. tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */
  50. else
  51. tmp = 8; /* starts with 0 - hence octal */
  52. if (base==0)
  53. base = (int)tmp;
  54. }
  55. maxdiv = ULONG_MAX / base;
  56. maxrem = ULONG_MAX % base;
  57. while ((digit = *s) != '\0')
  58. {
  59. if (digit >= '0' && digit < ('0'+base))
  60. digit -= '0';
  61. else
  62. if (base > 10)
  63. {
  64. if (digit >= 'a' && digit < ('a'+(base-10)))
  65. digit = digit - 'a' + 10;
  66. else if (digit >= 'A' && digit < ('A'+(base-10)))
  67. digit = digit - 'A' + 10;
  68. else
  69. break;
  70. }
  71. else
  72. break;
  73. did_conversion = 1;
  74. if (total > maxdiv
  75. || (total == maxdiv && digit > maxrem))
  76. overflow = 1;
  77. total = (total * base) + digit;
  78. s++;
  79. }
  80. if (overflow)
  81. {
  82. errno = ERANGE;
  83. if (ptr != NULL)
  84. *ptr = (char *)s;
  85. return (ULONG_MAX);
  86. }
  87. if (ptr != NULL)
  88. *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start);
  89. return negate ? -total : total;
  90. }