strtoll.c 1.2 KB

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