strtoul.c 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #include <stdlib.h>
  2. #include <errno.h>
  3. #include <limits.h>
  4. unsigned long
  5. strtoul(const char *nptr, char **endptr, int base)
  6. {
  7. const char *p;
  8. unsigned long n, nn;
  9. int c, ovfl, neg, v, ndig;
  10. p = (char*)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. p += 2;
  46. base = 16;
  47. }
  48. }
  49. }else if(base==16 && *p=='0'){
  50. if(p[1]=='x' || p[1]=='X')
  51. p += 2;
  52. }else if(base<0 || 36<base)
  53. goto Return;
  54. /*
  55. * Non-empty sequence of digits
  56. */
  57. for(;; p++,ndig++){
  58. c = *p;
  59. v = base;
  60. if('0'<=c && c<='9')
  61. v = c - '0';
  62. else if('a'<=c && c<='z')
  63. v = c - 'a' + 10;
  64. else if('A'<=c && c<='Z')
  65. v = c - 'A' + 10;
  66. if(v >= base)
  67. break;
  68. nn = n*base + v;
  69. if(nn < n)
  70. ovfl = 1;
  71. n = nn;
  72. }
  73. Return:
  74. if(ndig == 0)
  75. p = nptr;
  76. if(endptr)
  77. *endptr = (char *)p;
  78. if(ovfl){
  79. errno = ERANGE;
  80. return ULONG_MAX;
  81. }
  82. if(neg)
  83. return -n;
  84. return n;
  85. }