strtoul.c 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include <u.h>
  2. #include <libc.h>
  3. #define ULONG_MAX 4294967295UL
  4. ulong
  5. strtoul(char *nptr, char **endptr, int base)
  6. {
  7. char *p;
  8. ulong n, nn, m;
  9. int c, ovfl, neg, v, ndig;
  10. p = nptr;
  11. neg = 0;
  12. n = 0;
  13. ndig = 0;
  14. ovfl = 0;
  15. /*
  16. * White space
  17. */
  18. for(;;p++){
  19. switch(*p){
  20. case ' ':
  21. case '\t':
  22. case '\n':
  23. case '\f':
  24. case '\r':
  25. case '\v':
  26. continue;
  27. }
  28. break;
  29. }
  30. /*
  31. * Sign
  32. */
  33. if(*p=='-' || *p=='+')
  34. if(*p++ == '-')
  35. neg = 1;
  36. /*
  37. * Base
  38. */
  39. if(base==0){
  40. if(*p != '0')
  41. base = 10;
  42. else{
  43. base = 8;
  44. if(p[1]=='x' || p[1]=='X')
  45. base = 16;
  46. }
  47. }
  48. if(base<2 || 36<base)
  49. goto Return;
  50. if(base==16 && *p=='0'){
  51. if(p[1]=='x' || p[1]=='X')
  52. if(('0' <= p[2] && p[2] <= '9')
  53. ||('a' <= p[2] && p[2] <= 'f')
  54. ||('A' <= p[2] && p[2] <= 'F'))
  55. p += 2;
  56. }
  57. /*
  58. * Non-empty sequence of digits
  59. */
  60. n = 0;
  61. m = ULONG_MAX/base;
  62. for(;; p++,ndig++){
  63. c = *p;
  64. v = base;
  65. if('0'<=c && c<='9')
  66. v = c - '0';
  67. else if('a'<=c && c<='z')
  68. v = c - 'a' + 10;
  69. else 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. return ULONG_MAX;
  87. if(neg)
  88. return -n;
  89. return n;
  90. }