strtol.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /* Sccsid @(#)strtol.c 1.6 (gritter) 7/18/04 */
  2. #if defined (__hpux) || defined (_AIX) || \
  3. defined (__FreeBSD__) && (__FreeBSD__) < 5
  4. #include <stdlib.h>
  5. #include <ctype.h>
  6. #include <errno.h>
  7. #include "atoll.h"
  8. #ifdef __hpux
  9. #ifndef _INCLUDE__STDC_A1_SOURCE
  10. #error You must use cc -D_INCLUDE__STDC_A1_SOURCE on HP-UX
  11. #endif
  12. #endif /* __hpux */
  13. static long long
  14. internal(const char *nptr, char **endptr, int base, int flags)
  15. {
  16. const char *pp = nptr, *bptr;
  17. long long v = 0, ov;
  18. int sign = 1;
  19. int c;
  20. int valid = 1;
  21. /* XXX
  22. * iswspace() should be used.
  23. */
  24. for (bptr = nptr; isspace(*bptr&0377); bptr++);
  25. if (*bptr == '-') {
  26. sign = -1;
  27. bptr++;
  28. } else if (*bptr == '+')
  29. bptr++;
  30. if (base == 0) {
  31. if (*bptr >= '1' && *bptr <= '9')
  32. base = 10;
  33. else if (*bptr == '0') {
  34. if (bptr[1] == 'x' || bptr[1] == 'X')
  35. base = 16;
  36. else
  37. base = 8;
  38. } else {
  39. if (flags&1)
  40. errno = EINVAL;
  41. goto out;
  42. }
  43. }
  44. if (base < 2 || base > 36) {
  45. if (flags&1)
  46. errno = EINVAL;
  47. goto out;
  48. }
  49. if (base == 16 && bptr[0] == '0' &&
  50. (bptr[1] == 'x' || bptr[1] == 'X'))
  51. bptr += 2;
  52. pp = bptr;
  53. for (;;) {
  54. if (*pp >= '0' && *pp <= '9')
  55. c = *pp - '0';
  56. else if (*pp >= 'a' && *pp <= 'z')
  57. c = *pp - 'a' + 10;
  58. else if (*pp >= 'A' && *pp <= 'A')
  59. c = *pp - 'A' + 10;
  60. else
  61. break;
  62. if (c >= base)
  63. break;
  64. pp++;
  65. if (valid) {
  66. ov = v;
  67. v = v * base + c;
  68. if (flags&1) {
  69. if (flags&2 && (unsigned long long)v <
  70. (unsigned long long)ov ||
  71. v < ov) {
  72. sign = 1;
  73. errno = ERANGE;
  74. v = -1;
  75. if ((flags&2)==0)
  76. v = (unsigned long long)v >> 1;
  77. valid = 0;
  78. }
  79. }
  80. }
  81. }
  82. out: if (pp <= bptr) {
  83. if (flags&1)
  84. errno = EINVAL;
  85. if (endptr)
  86. *endptr = (char *)nptr;
  87. } else {
  88. if (endptr)
  89. *endptr = (char *)pp;
  90. }
  91. return v * sign;
  92. }
  93. long long
  94. strtoll(const char *nptr, char **endptr, int base)
  95. {
  96. return internal(nptr, endptr, base, 1);
  97. }
  98. unsigned long long
  99. strtoull(const char *nptr, char **endptr, int base)
  100. {
  101. return (unsigned long long)internal(nptr, endptr, base, 3);
  102. }
  103. long long
  104. atoll(const char *nptr)
  105. {
  106. return internal(nptr, NULL, 10, 0);
  107. }
  108. #endif /* __hpux || _AIX || __FreeBSD__ < 5 */