Windows NT 4.0 source code leak
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.

215 lines
5.2 KiB

4 years ago
  1. /***
  2. *wcstol.c - Contains C runtimes wcstol and wcstoul
  3. *
  4. * Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * wcstol - convert wchar_t string to long signed integer
  8. * wcstoul - convert wchar_t string to long unsigned integer
  9. *
  10. *Revision History:
  11. * 06-15-92 KRS Module created, based on strtol.c
  12. * 04-21-93 GJF Removed assumption that LONG_MIN == -LONG_MAX.
  13. * 05-10-93 GJF Fixed error check.
  14. * 05-20-93 GJF Nothing like taking ugly code and making prettier...
  15. * and wrong. Fixed bug introduced on 5-10.
  16. *
  17. *******************************************************************************/
  18. #include <cruntime.h>
  19. #include <stdlib.h>
  20. #include <limits.h>
  21. #include <errno.h>
  22. #include <ctype.h>
  23. /***
  24. *wcstol, wcstoul(nptr,endptr,ibase) - Convert ascii string to long un/signed
  25. * int.
  26. *
  27. *Purpose:
  28. * Convert an ascii string to a long 32-bit value. The base
  29. * used for the caculations is supplied by the caller. The base
  30. * must be in the range 0, 2-36. If a base of 0 is supplied, the
  31. * ascii string must be examined to determine the base of the
  32. * number:
  33. * (a) First char = '0', second char = 'x' or 'X',
  34. * use base 16.
  35. * (b) First char = '0', use base 8
  36. * (c) First char in range '1' - '9', use base 10.
  37. *
  38. * If the 'endptr' value is non-NULL, then wcstol/wcstoul places
  39. * a pointer to the terminating character in this value.
  40. * See ANSI standard for details
  41. *
  42. *Entry:
  43. * nptr == NEAR/FAR pointer to the start of string.
  44. * endptr == NEAR/FAR pointer to the end of the string.
  45. * ibase == integer base to use for the calculations.
  46. *
  47. * string format: [whitespace] [sign] [0] [x] [digits/letters]
  48. *
  49. *Exit:
  50. * Good return:
  51. * result
  52. *
  53. * Overflow return:
  54. * wcstol -- LONG_MAX or LONG_MIN
  55. * wcstoul -- ULONG_MAX
  56. * wcstol/wcstoul -- errno == ERANGE
  57. *
  58. * No digits or bad base return:
  59. * 0
  60. * endptr = nptr*
  61. *
  62. *Exceptions:
  63. * None.
  64. *******************************************************************************/
  65. /* flag values */
  66. #define FL_UNSIGNED 1 /* wcstoul called */
  67. #define FL_NEG 2 /* negative sign found */
  68. #define FL_OVERFLOW 4 /* overflow occured */
  69. #define FL_READDIGIT 8 /* we've read at least one correct digit */
  70. static unsigned long _CRTAPI3 wcstoxl (
  71. const wchar_t *nptr,
  72. const wchar_t **endptr,
  73. int ibase,
  74. int flags
  75. )
  76. {
  77. const wchar_t *p;
  78. wchar_t c;
  79. unsigned long number;
  80. unsigned digval;
  81. unsigned long maxval;
  82. p = nptr; /* p is our scanning pointer */
  83. number = 0; /* start with zero */
  84. c = *p++; /* read char */
  85. while (iswspace(c))
  86. c = *p++; /* skip whitespace */
  87. if (c == '-') {
  88. flags |= FL_NEG; /* remember minus sign */
  89. c = *p++;
  90. }
  91. else if (c == '+')
  92. c = *p++; /* skip sign */
  93. if (ibase < 0 || ibase == 1 || ibase > 36) {
  94. /* bad base! */
  95. if (endptr)
  96. /* store beginning of string in endptr */
  97. *endptr = nptr;
  98. return 0L; /* return 0 */
  99. }
  100. else if (ibase == 0) {
  101. /* determine base free-lance, based on first two chars of
  102. string */
  103. if (c != L'0')
  104. ibase = 10;
  105. else if (*p == L'x' || *p == L'X')
  106. ibase = 16;
  107. else
  108. ibase = 8;
  109. }
  110. if (ibase == 16) {
  111. /* we might have 0x in front of number; remove if there */
  112. if (c == L'0' && (*p == L'x' || *p == L'X')) {
  113. ++p;
  114. c = *p++; /* advance past prefix */
  115. }
  116. }
  117. /* if our number exceeds this, we will overflow on multiply */
  118. maxval = ULONG_MAX / ibase;
  119. for (;;) { /* exit in middle of loop */
  120. /* convert c to value */
  121. if (iswdigit(c))
  122. digval = c - L'0';
  123. else if (iswalpha(c))
  124. digval = towupper(c) - L'A' + 10;
  125. else
  126. break;
  127. if (digval >= (unsigned)ibase)
  128. break; /* exit loop if bad digit found */
  129. /* record the fact we have read one digit */
  130. flags |= FL_READDIGIT;
  131. /* we now need to compute number = number * base + digval,
  132. but we need to know if overflow occured. This requires
  133. a tricky pre-check. */
  134. if (number < maxval || (number == maxval &&
  135. (unsigned long)digval <= ULONG_MAX % ibase)) {
  136. /* we won't overflow, go ahead and multiply */
  137. number = number * ibase + digval;
  138. }
  139. else {
  140. /* we would have overflowed -- set the overflow flag */
  141. flags |= FL_OVERFLOW;
  142. }
  143. c = *p++; /* read next digit */
  144. }
  145. --p; /* point to place that stopped scan */
  146. if (!(flags & FL_READDIGIT)) {
  147. /* no number there; return 0 and point to beginning of
  148. string */
  149. if (endptr)
  150. /* store beginning of string in endptr later on */
  151. p = nptr;
  152. number = 0L; /* return 0 */
  153. }
  154. else if ( (flags & FL_OVERFLOW) ||
  155. ( !(flags & FL_UNSIGNED) &&
  156. ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
  157. ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
  158. {
  159. /* overflow or signed overflow occurred */
  160. errno = ERANGE;
  161. if ( flags & FL_UNSIGNED )
  162. number = ULONG_MAX;
  163. else if ( flags & FL_NEG )
  164. number = (unsigned long)(-LONG_MIN);
  165. else
  166. number = LONG_MAX;
  167. }
  168. if (endptr != NULL)
  169. /* store pointer to char that stopped the scan */
  170. *endptr = p;
  171. if (flags & FL_NEG)
  172. /* negate result if there was a neg sign */
  173. number = (unsigned long)(-(long)number);
  174. return number; /* done. */
  175. }
  176. long _CRTAPI1 wcstol (
  177. const wchar_t *nptr,
  178. wchar_t **endptr,
  179. int ibase
  180. )
  181. {
  182. return (long) wcstoxl(nptr, endptr, ibase, 0);
  183. }
  184. unsigned long _CRTAPI1 wcstoul (
  185. const wchar_t *nptr,
  186. wchar_t **endptr,
  187. int ibase
  188. )
  189. {
  190. return wcstoxl(nptr, endptr, ibase, FL_UNSIGNED);
  191. }