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.

262 lines
7.0 KiB

  1. /*****************************************************************************
  2. *
  3. * at.c
  4. *
  5. * Arithmetic types.
  6. *
  7. *****************************************************************************/
  8. #include "m4.h"
  9. F STDCALL fWhiteTch(TCH tch);
  10. /*****************************************************************************
  11. *
  12. * AddExpAt
  13. *
  14. * Add the (unsigned) arithmetic value to the Exp hold.
  15. *
  16. * Since the value is never very large, we may as well be recursive.
  17. *
  18. *****************************************************************************/
  19. void STDCALL
  20. AddExpAt(AT at)
  21. {
  22. if (at > 9) {
  23. AddExpAt(at / 10);
  24. }
  25. AddExpTch((TCH)(TEXT('0') + at % 10));
  26. }
  27. /*****************************************************************************
  28. *
  29. * PushAtRadixCtch
  30. *
  31. * Push onto the input stream the specified arithmetic value, in the
  32. * requested radix, padded with zeros to the requested width.
  33. *
  34. * The type is always considered signed.
  35. *
  36. * If a negative value needs to be padded, the zeros are inserted after
  37. * the leading minus sign.
  38. *
  39. * QUIRK! Under AT&T, the leading minus sign does *not* contribute
  40. * to the count! I emulate this quirk...
  41. *
  42. * FEATURE! If the radix is invalid, force it to 10. AT&T doesn't
  43. * check the radix, but I will.
  44. *
  45. * QUIRK! Under AT&T, a negative width is treated as zero.
  46. * I emulate this quirk...
  47. *
  48. * INTERESTING HACK! Since characters are pushed LIFO, we can generate
  49. * the entire output string without needing to use a hold or anything
  50. * else gross like that.
  51. *
  52. *****************************************************************************/
  53. void STDCALL
  54. PushAtRadixCtch(AT atConvert, unsigned radix, CTCH ctch)
  55. {
  56. AT at;
  57. if ((int)ctch < 0) {
  58. #ifdef WARN_COMPAT
  59. Warn("Negative eval width %d silently converted to zero");
  60. #endif
  61. ctch = 0;
  62. }
  63. if (radix < 2 || radix > 36) {
  64. #ifdef WARN_COMPAT
  65. Warn("Invalid radix %d silently converted to 10");
  66. #endif
  67. radix = 10;
  68. }
  69. at = atConvert < 0 ? -atConvert : atConvert;
  70. do {
  71. TCH tch = (TCH)((unsigned long)at % radix);
  72. at = (unsigned long)at / radix;
  73. if (tch < 10) {
  74. PushTch((TCH)(tch + '0'));
  75. } else {
  76. PushTch((TCH)(tch + 'A' - 10));
  77. }
  78. ctch--;
  79. } while (at);
  80. while ((int)ctch > 0) {
  81. PushTch('0');
  82. --ctch;
  83. }
  84. if (atConvert < 0) {
  85. PushTch('-');
  86. }
  87. }
  88. /*****************************************************************************
  89. *
  90. * PushAt
  91. *
  92. * Common case where we want to display the value in base 10
  93. * with no padding.
  94. *
  95. *****************************************************************************/
  96. void STDCALL
  97. PushAt(AT at)
  98. {
  99. PushAtRadixCtch(at, 10, 0);
  100. }
  101. /*****************************************************************************
  102. *
  103. * SkipWhitePtok
  104. *
  105. * Skip leading whitespace in a token, *MODIFYING* the token in place.
  106. *
  107. *****************************************************************************/
  108. void STDCALL
  109. SkipWhitePtok(PTOK ptok)
  110. {
  111. AssertSPtok(ptok);
  112. Assert(fScratchPtok(ptok));
  113. while (!fNullPtok(ptok) && fWhiteTch(*ptchPtok(ptok))) {
  114. EatHeadPtokCtch(ptok, 1);
  115. }
  116. }
  117. /*****************************************************************************
  118. *
  119. * atRadixPtok
  120. *
  121. * Parse a number out of a token, given the radix. Leading whitespace
  122. * must already have been streipped.
  123. *
  124. * The token is *MODIFIED* to point to the first unconsumed character.
  125. * If no valid digits are found, then zero is returned and the token
  126. * is unchanged.
  127. *
  128. *****************************************************************************/
  129. AT STDCALL
  130. atRadixPtok(unsigned radix, PTOK ptok)
  131. {
  132. AT at = 0;
  133. while (!fNullPtok(ptok)) {
  134. AT atDigit = (TBYTE)*ptchPtok(ptok) - '0';
  135. if ((unsigned)atDigit > 9) {
  136. atDigit = ((TBYTE)*ptchPtok(ptok) | 0x20) - 'a';
  137. if ((unsigned)atDigit > 5) {
  138. break;
  139. }
  140. atDigit += 10;
  141. }
  142. if ((unsigned)atDigit > radix) {
  143. break;
  144. }
  145. at = at * radix + atDigit;
  146. EatHeadPtokCtch(ptok, 1);
  147. }
  148. return at;
  149. }
  150. /*****************************************************************************
  151. *
  152. * fEvalPtokPat
  153. *
  154. * Parse a number out of a token. Leading whitespace must already have
  155. * been stripped. A leading minus sign is not permitted. (`eval'
  156. * would have already parsed it out as a unary operator.) A leading
  157. * zero forces the value to be parsed as octal; a leading `0x' as hex.
  158. *
  159. * The token is *MODIFIED* to point to the first unconsumed character.
  160. * If no valid number is found, then zero is returned. Otherwise,
  161. * nonzero is returned and pat is filled with the parsed value.
  162. *
  163. *****************************************************************************/
  164. F STDCALL
  165. fEvalPtokPat(PTOK ptok, PAT pat)
  166. {
  167. AT at;
  168. AssertSPtok(ptok);
  169. Assert(fScratchPtok(ptok));
  170. if (!fNullPtok(ptok)) {
  171. PTCH ptchStart;
  172. unsigned radix;
  173. /*
  174. * Get the radix...
  175. */
  176. if (*ptchPtok(ptok) == '0') {
  177. if (ctchSPtok(ptok) > 2 &&
  178. (ptchPtok(ptok)[1] | 0x20) == 'x') {
  179. EatHeadPtokCtch(ptok, 2);
  180. radix = 16;
  181. } else {
  182. radix = 8;
  183. }
  184. } else {
  185. radix = 10;
  186. }
  187. ptchStart = ptchPtok(ptok); /* Remember the start */
  188. at = atRadixPtok(radix, ptok);
  189. if (ptchStart == ptchPtok(ptok)) {
  190. if (radix == 16) {
  191. EatHeadPtokCtch(ptok, (CTCH)-2); /* Restore the `0x' */
  192. }
  193. return 0;
  194. } else {
  195. *pat = at;
  196. return 1;
  197. }
  198. }
  199. return 0; /* No number found */
  200. }
  201. /*****************************************************************************
  202. *
  203. * atTraditionalPtok
  204. *
  205. * Parse a number out of a token. Leading whitespace is ignored.
  206. * A leading minus sign is permitted. Octal and hex notation is
  207. * not permitted. No space is permitted between the optional
  208. * minus sign and the digit string. An invalid input is parsed as zero.
  209. *
  210. *****************************************************************************/
  211. AT STDCALL PURE
  212. atTraditionalPtok(PCTOK ptok)
  213. {
  214. TOK tok;
  215. AssertSPtok(ptok);
  216. DupStaticPtokPtok(&tok, ptok);
  217. D(tok.tsfl |= tsflScratch);
  218. SkipWhitePtok(&tok);
  219. if (!fNullPtok(&tok)) {
  220. AT at;
  221. BOOL fSign;
  222. if (*ptchPtok(&tok) == '-') {
  223. fSign = 1;
  224. EatHeadPtokCtch(&tok, 1);
  225. } else {
  226. fSign = 0;
  227. }
  228. at = atRadixPtok(10, &tok);
  229. if (fSign) {
  230. at = -at;
  231. }
  232. return at;
  233. } else {
  234. return 0;
  235. }
  236. }