strtoull.c 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include <lib9.h>
  2. #define UVLONG_MAX (1LL<<63)
  3. uvlong
  4. strtoull(char *nptr, char **endptr, int base)
  5. {
  6. char *p;
  7. uvlong n, nn, m;
  8. int c, ovfl, v, neg, ndig;
  9. p = nptr;
  10. neg = 0;
  11. n = 0;
  12. ndig = 0;
  13. ovfl = 0;
  14. /*
  15. * White space
  16. */
  17. for(;; p++) {
  18. switch(*p) {
  19. case ' ':
  20. case '\t':
  21. case '\n':
  22. case '\f':
  23. case '\r':
  24. case '\v':
  25. continue;
  26. }
  27. break;
  28. }
  29. /*
  30. * Sign
  31. */
  32. if(*p == '-' || *p == '+')
  33. if(*p++ == '-')
  34. neg = 1;
  35. /*
  36. * Base
  37. */
  38. if(base == 0) {
  39. base = 10;
  40. if(*p == '0') {
  41. base = 8;
  42. if(p[1] == 'x' || p[1] == 'X'){
  43. p += 2;
  44. base = 16;
  45. }
  46. }
  47. } else
  48. if(base == 16 && *p == '0') {
  49. if(p[1] == 'x' || p[1] == 'X')
  50. p += 2;
  51. } else
  52. if(base < 0 || 36 < base)
  53. goto Return;
  54. /*
  55. * Non-empty sequence of digits
  56. */
  57. m = UVLONG_MAX/base;
  58. for(;; p++,ndig++) {
  59. c = *p;
  60. v = base;
  61. if('0' <= c && c <= '9')
  62. v = c - '0';
  63. else
  64. if('a' <= c && c <= 'z')
  65. v = c - 'a' + 10;
  66. else
  67. if('A' <= c && c <= 'Z')
  68. v = c - 'A' + 10;
  69. if(v >= base)
  70. break;
  71. if(n > m)
  72. ovfl = 1;
  73. nn = n*base + v;
  74. if(nn < n)
  75. ovfl = 1;
  76. n = nn;
  77. }
  78. Return:
  79. if(ndig == 0)
  80. p = nptr;
  81. if(endptr)
  82. *endptr = p;
  83. if(ovfl)
  84. return UVLONG_MAX;
  85. if(neg)
  86. return -n;
  87. return n;
  88. }