Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
6.5 KiB

  1. #include <windows.h>
  2. #include <sdsutils.h>
  3. #define LONG_MAX 2147483647
  4. #define LONG_MIN -2147483647-1
  5. #define ULONG_MAX 0xFFFFFFFF
  6. static unsigned long StrToXL (const char *nptr, const char **endptr, int ibase, int flags);
  7. /***
  8. *strtol, strtoul(nptr,endptr,ibase) - Convert ascii string to long un/signed
  9. * int.
  10. *
  11. *Purpose:
  12. * Convert an ascii string to a long 32-bit value. The base
  13. * used for the caculations is supplied by the caller. The base
  14. * must be in the range 0, 2-36. If a base of 0 is supplied, the
  15. * ascii string must be examined to determine the base of the
  16. * number:
  17. * (a) First char = '0', second char = 'x' or 'X',
  18. * use base 16.
  19. * (b) First char = '0', use base 8
  20. * (c) First char in range '1' - '9', use base 10.
  21. *
  22. * If the 'endptr' value is non-NULL, then strtol/strtoul places
  23. * a pointer to the terminating character in this value.
  24. * See ANSI standard for details
  25. *
  26. *Entry:
  27. * nptr == NEAR/FAR pointer to the start of string.
  28. * endptr == NEAR/FAR pointer to the end of the string.
  29. * ibase == integer base to use for the calculations.
  30. *
  31. * string format: [whitespace] [sign] [0] [x] [digits/letters]
  32. *
  33. *Exit:
  34. * Good return:
  35. * result
  36. *
  37. * Overflow return:
  38. * strtol -- LONG_MAX or LONG_MIN
  39. * strtoul -- ULONG_MAX
  40. * strtol/strtoul -- errno == ERANGE
  41. *
  42. * No digits or bad base return:
  43. * 0
  44. * endptr = nptr*
  45. *
  46. *Exceptions:
  47. * None.
  48. *******************************************************************************/
  49. /* flag values */
  50. #define FL_UNSIGNED 1 /* strtoul called */
  51. #define FL_NEG 2 /* negative sign found */
  52. #define FL_OVERFLOW 4 /* overflow occured */
  53. #define FL_READDIGIT 8 /* we've read at least one correct digit */
  54. static unsigned long StrToXL (const char *nptr, const char **endptr, int ibase, int flags)
  55. {
  56. const char *p;
  57. char c;
  58. unsigned long number;
  59. unsigned digval;
  60. unsigned long maxval;
  61. p = nptr; /* p is our scanning pointer */
  62. number = 0; /* start with zero */
  63. c = *p++; /* read char */
  64. while ( IsSpace((int)(unsigned char)c) )
  65. c = *p++; /* skip whitespace */
  66. if (c == '-') {
  67. flags |= FL_NEG; /* remember minus sign */
  68. c = *p++;
  69. }
  70. else if (c == '+')
  71. c = *p++; /* skip sign */
  72. if (ibase < 0 || ibase == 1 || ibase > 36) {
  73. /* bad base! */
  74. if (endptr)
  75. /* store beginning of string in endptr */
  76. *endptr = nptr;
  77. return 0L; /* return 0 */
  78. }
  79. else if (ibase == 0) {
  80. /* determine base free-lance, based on first two chars of
  81. string */
  82. if (c != '0')
  83. ibase = 10;
  84. else if (*p == 'x' || *p == 'X')
  85. ibase = 16;
  86. else
  87. ibase = 8;
  88. }
  89. if (ibase == 16) {
  90. /* we might have 0x in front of number; remove if there */
  91. if (c == '0' && (*p == 'x' || *p == 'X')) {
  92. ++p;
  93. c = *p++; /* advance past prefix */
  94. }
  95. }
  96. /* if our number exceeds this, we will overflow on multiply */
  97. maxval = ULONG_MAX / ibase;
  98. for (;;) { /* exit in middle of loop */
  99. /* convert c to value */
  100. if ( IsDigit((int)(unsigned char)c) )
  101. digval = c - '0';
  102. else if ( IsAlpha((int)(unsigned char)c) )
  103. digval = (char)CharUpper((LPSTR)c) - 'A' + 10;
  104. else
  105. break;
  106. if (digval >= (unsigned)ibase)
  107. break; /* exit loop if bad digit found */
  108. /* record the fact we have read one digit */
  109. flags |= FL_READDIGIT;
  110. /* we now need to compute number = number * base + digval,
  111. but we need to know if overflow occured. This requires
  112. a tricky pre-check. */
  113. if (number < maxval || (number == maxval &&
  114. (unsigned long)digval <= ULONG_MAX % ibase)) {
  115. /* we won't overflow, go ahead and multiply */
  116. number = number * ibase + digval;
  117. }
  118. else {
  119. /* we would have overflowed -- set the overflow flag */
  120. flags |= FL_OVERFLOW;
  121. }
  122. c = *p++; /* read next digit */
  123. }
  124. --p; /* point to place that stopped scan */
  125. if (!(flags & FL_READDIGIT)) {
  126. /* no number there; return 0 and point to beginning of
  127. string */
  128. if (endptr)
  129. /* store beginning of string in endptr later on */
  130. p = nptr;
  131. number = 0L; /* return 0 */
  132. }
  133. else if ( (flags & FL_OVERFLOW) ||
  134. ( !(flags & FL_UNSIGNED) &&
  135. ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
  136. ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
  137. {
  138. /* overflow or signed overflow occurred */
  139. if ( flags & FL_UNSIGNED )
  140. number = ULONG_MAX;
  141. else if ( flags & FL_NEG )
  142. number = (unsigned long)(-LONG_MIN);
  143. else
  144. number = LONG_MAX;
  145. }
  146. if (endptr != NULL)
  147. /* store pointer to char that stopped the scan */
  148. *endptr = p;
  149. if (flags & FL_NEG)
  150. /* negate result if there was a neg sign */
  151. number = (unsigned long)(-(long)number);
  152. return number; /* done. */
  153. }
  154. unsigned long StrToUL (const char *nptr, char **endptr,int ibase)
  155. {
  156. return StrToXL(nptr, (const char**)endptr, ibase, FL_UNSIGNED);
  157. }