Source code of Windows XP (NT5)
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.

1146 lines
35 KiB

  1. /***************************************************************************/
  2. /* BCD.C */
  3. /* Copyright (C) 1996 SYWARE Inc., All rights reserved */
  4. /***************************************************************************/
  5. // Commenting #define out - causing compiler error - not sure if needed, compiles
  6. // okay without it.
  7. //#define WINVER 0x0400
  8. #include "precomp.h"
  9. #include "wbemidl.h"
  10. #include <comdef.h>
  11. //smart pointer
  12. _COM_SMARTPTR_TYPEDEF(IWbemServices, IID_IWbemServices);
  13. _COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, IID_IEnumWbemClassObject);
  14. //_COM_SMARTPTR_TYPEDEF(IWbemContext, IID_IWbemContext );
  15. _COM_SMARTPTR_TYPEDEF(IWbemLocator, IID_IWbemLocator);
  16. #include "drdbdr.h"
  17. /***************************************************************************/
  18. void INTFUNC BCDMultiplyByTen(LPUSTR lpszValue)
  19. /* Multiply a value by ten */
  20. {
  21. SWORD decimal;
  22. /* Look for the decimal point */
  23. for (decimal = 0; decimal < s_lstrlen(lpszValue); decimal++) {
  24. if (lpszValue[decimal] == '.') {
  25. /* Found it. Move the next digit to the left */
  26. lpszValue[decimal] = lpszValue[decimal+1];
  27. /* Was the decimal point at the end of the value? */
  28. if (lpszValue[decimal] != '\0') {
  29. /* No. Set the next character to the decimal point */
  30. lpszValue[decimal+1] = '.';
  31. /* If no digits to the right of decimal point, remove it */
  32. if (lpszValue[decimal+2] == '\0')
  33. lpszValue[decimal+1] = '\0';
  34. }
  35. else {
  36. /* Yes. Add in another zero */
  37. lpszValue[decimal] = '0';
  38. }
  39. /* If we just moved a zero to the left of the decimal point */
  40. /* for a number with only a fractional part, remove the */
  41. /* leading zero */
  42. if (*lpszValue == '0')
  43. s_lstrcpy(lpszValue, lpszValue + 1);
  44. return;
  45. }
  46. }
  47. /* Didn't find a decimal point. Just add a zero to the end */
  48. if (s_lstrlen(lpszValue) != 0)
  49. s_lstrcat(lpszValue, "0");
  50. return;
  51. }
  52. /***************************************************************************/
  53. void INTFUNC BCDDivideByTen(LPUSTR lpszValue)
  54. /* Divide a value by ten */
  55. {
  56. SWORD decimal;
  57. /* Look for the decimal point */
  58. for (decimal = 0; decimal < s_lstrlen(lpszValue); decimal++) {
  59. if (lpszValue[decimal] == '.') {
  60. /* Found it. Is this the first character? */
  61. if (decimal != 0) {
  62. /* No. Move the previous digit into this spot */
  63. lpszValue[decimal] = lpszValue[decimal-1];
  64. /* Put in the new decimal point */
  65. lpszValue[decimal-1] = '.';
  66. }
  67. else {
  68. /* Yes. move the number to the right */
  69. _fmemmove(lpszValue+1, lpszValue, s_lstrlen(lpszValue)+1);
  70. /* Add in another zero */
  71. lpszValue[1] = '0';
  72. }
  73. return;
  74. }
  75. }
  76. /* Didn't find a decimal point. Move right most digit over and */
  77. /* add one in */
  78. if (decimal > 0) {
  79. lpszValue[decimal+1] = '\0';
  80. lpszValue[decimal] = lpszValue[decimal-1];
  81. lpszValue[decimal-1] = '.';
  82. }
  83. return;
  84. }
  85. /***************************************************************************/
  86. SWORD INTFUNC BCDCompareValues(LPUSTR lpszLeft,
  87. LPUSTR lpszRight)
  88. /* Compares the two BCD values. The values are assumed to be positive */
  89. /* If 'lpszLeft' is greater than 'lpszRight', a positive value is retuned. */
  90. /* If 'lpszLeft' is less than 'lpszRight', a negative value is retuned. */
  91. /* If 'lpszLeft' is equal to 'lpszRight', 0 is retuned. */
  92. {
  93. SWORD idxDecimalLeft;
  94. SWORD idxDecimalRight;
  95. UCHAR cLeft;
  96. UCHAR cRight;
  97. LPUSTR ptrLeft;
  98. LPUSTR ptrRight;
  99. int fComp;
  100. /* Find decimal point (if any) */
  101. for (idxDecimalLeft = 0;
  102. idxDecimalLeft < s_lstrlen(lpszLeft);
  103. idxDecimalLeft++) {
  104. if (lpszLeft[idxDecimalLeft] == '.')
  105. break;
  106. }
  107. for (idxDecimalRight = 0;
  108. idxDecimalRight < s_lstrlen(lpszRight);
  109. idxDecimalRight++) {
  110. if (lpszRight[idxDecimalRight] == '.')
  111. break;
  112. }
  113. /* If unequal number of integer digits, return answer */
  114. if (idxDecimalLeft > idxDecimalRight)
  115. return 1;
  116. else if (idxDecimalLeft < idxDecimalRight)
  117. return -1;
  118. /* Compare integer part of the values and if they are not equal, */
  119. /* return answer */
  120. cLeft = lpszLeft[idxDecimalLeft];
  121. cRight = lpszRight[idxDecimalRight];
  122. lpszLeft[idxDecimalLeft] = '\0';
  123. if (lpszRight[idxDecimalRight] != '\0')
  124. lpszRight[idxDecimalRight] = '\0';
  125. fComp = s_lstrcmp(lpszLeft, lpszRight);
  126. lpszLeft[idxDecimalLeft] = cLeft;
  127. if (lpszRight[idxDecimalRight] != cRight)
  128. lpszRight[idxDecimalRight] = cRight;
  129. if (fComp > 0)
  130. return 1;
  131. else if (fComp < 0)
  132. return -1;
  133. /* The integer parts are equal. Compare the fractional parts */
  134. ptrLeft = lpszLeft + idxDecimalLeft;
  135. if (*ptrLeft == '.')
  136. ptrLeft++;
  137. ptrRight = lpszRight + idxDecimalRight;
  138. if (*ptrRight == '.')
  139. ptrRight++;
  140. while (TRUE) {
  141. if (*ptrLeft == '\0') {
  142. while (*ptrRight == '0')
  143. ptrRight++;
  144. if (*ptrRight == '\0')
  145. break;
  146. return -1;
  147. }
  148. if (*ptrRight == '\0') {
  149. while (*ptrLeft == '0')
  150. ptrLeft++;
  151. if (*ptrLeft == '\0')
  152. break;
  153. return 1;
  154. }
  155. if (*ptrLeft > *ptrRight)
  156. return 1;
  157. else if (*ptrLeft < *ptrRight)
  158. return -1;
  159. ptrLeft++;
  160. ptrRight++;
  161. }
  162. return 0;
  163. }
  164. /***************************************************************************/
  165. void INTFUNC BCDAdd(LPUSTR lpszResult,
  166. LPUSTR lpszLeft,
  167. LPUSTR lpszRight)
  168. {
  169. LPUSTR lpszCurrent;
  170. LPUSTR lpszCurrentLeft;
  171. LPUSTR lpszCurrentRight;
  172. SWORD idxDecimalLeft;
  173. SWORD idxDecimalRight;
  174. UCHAR digit;
  175. LPUSTR lpszCarryDigit;
  176. /* Point at values */
  177. lpszCurrent = lpszResult;
  178. lpszCurrentLeft = lpszLeft;
  179. lpszCurrentRight = lpszRight;
  180. /* Put leading zero in */
  181. *lpszCurrent = '0';
  182. lpszCurrent++;
  183. /* Find decimal point (if any) */
  184. for (idxDecimalLeft = 0;
  185. idxDecimalLeft < s_lstrlen(lpszLeft);
  186. idxDecimalLeft++) {
  187. if (lpszLeft[idxDecimalLeft] == '.')
  188. break;
  189. }
  190. for (idxDecimalRight = 0;
  191. idxDecimalRight < s_lstrlen(lpszRight);
  192. idxDecimalRight++) {
  193. if (lpszRight[idxDecimalRight] == '.')
  194. break;
  195. }
  196. /* Put in excess characters */
  197. while (idxDecimalLeft > idxDecimalRight) {
  198. *lpszCurrent = *lpszCurrentLeft;
  199. lpszCurrent++;
  200. lpszCurrentLeft++;
  201. idxDecimalLeft--;
  202. }
  203. while (idxDecimalRight > idxDecimalLeft) {
  204. *lpszCurrent = *lpszCurrentRight;
  205. lpszCurrent++;
  206. lpszCurrentRight++;
  207. idxDecimalRight--;
  208. }
  209. /* Add integer part */
  210. while (idxDecimalLeft > 0) {
  211. /* Get left digit */
  212. digit = (*lpszCurrentLeft) & 0x0F;
  213. lpszCurrentLeft++;
  214. idxDecimalLeft--;
  215. /* Add right digit to it */
  216. digit += ((*lpszCurrentRight) & 0x0F);
  217. lpszCurrentRight++;
  218. idxDecimalRight--;
  219. /* Is there a carry? */
  220. if (digit >= 10) {
  221. /* Yes. Propagate it to the higher digits */
  222. lpszCarryDigit = lpszCurrent - 1;
  223. while (TRUE) {
  224. if (*lpszCarryDigit != '9') {
  225. *lpszCarryDigit = *lpszCarryDigit + 1;
  226. break;
  227. }
  228. *lpszCarryDigit = '0';
  229. lpszCarryDigit--;
  230. }
  231. /* Adjust digit */
  232. digit -= (10);
  233. }
  234. /* Save digit */
  235. *lpszCurrent = '0' + digit;
  236. lpszCurrent++;
  237. }
  238. /* Is there a fractional part? */
  239. if ((*lpszCurrentLeft != '\0') || (*lpszCurrentRight != '\0')) {
  240. /* Yes. Put in a decimal point */
  241. *lpszCurrent = '.';
  242. lpszCurrent++;
  243. /* Skip over the decimal points */
  244. if (*lpszCurrentRight == '.')
  245. lpszCurrentRight++;
  246. if (*lpszCurrentLeft == '.')
  247. lpszCurrentLeft++;
  248. /* Add the values */
  249. while ((*lpszCurrentLeft != '\0') || (*lpszCurrentRight != '\0')) {
  250. /* Get left digit */
  251. if (*lpszCurrentLeft != '\0') {
  252. digit = (*lpszCurrentLeft) & 0x0F;
  253. lpszCurrentLeft++;
  254. }
  255. else
  256. digit = 0;
  257. /* Add right digit to it */
  258. if (*lpszCurrentRight != '\0') {
  259. digit += ((*lpszCurrentRight) & 0x0F);
  260. lpszCurrentRight++;
  261. }
  262. /* Is there a carry? */
  263. if (digit >= 10) {
  264. /* Yes. Propagate it to the higher digits */
  265. lpszCarryDigit = lpszCurrent - 1;
  266. while (TRUE) {
  267. if (*lpszCarryDigit == '.')
  268. lpszCarryDigit--;
  269. if (*lpszCarryDigit != '9') {
  270. *lpszCarryDigit = *lpszCarryDigit + 1;
  271. break;
  272. }
  273. *lpszCarryDigit = '0';
  274. lpszCarryDigit--;
  275. }
  276. /* Adjust digit */
  277. digit -= (10);
  278. }
  279. /* Save digit */
  280. *lpszCurrent = '0' + digit;
  281. lpszCurrent++;
  282. }
  283. }
  284. /* Put in terminating null */
  285. *lpszCurrent = '\0';
  286. /* Did anything carry into the first digit? */
  287. if (*lpszResult == '0') {
  288. /* No. Shift value to the left */
  289. s_lstrcpy(lpszResult, lpszResult+1);
  290. }
  291. }
  292. /***************************************************************************/
  293. void INTFUNC BCDSubtract(LPUSTR lpszResult,
  294. LPUSTR lpszLeft,
  295. LPUSTR lpszRight)
  296. {
  297. LPUSTR lpszCurrent;
  298. LPUSTR lpszCurrentLeft;
  299. LPUSTR lpszCurrentRight;
  300. SWORD idxDecimalLeft;
  301. SWORD idxDecimalRight;
  302. UCHAR digit;
  303. LPUSTR lpszBorrowDigit;
  304. /* If the result is negative, subtract the other way */
  305. if (BCDCompareValues(lpszLeft, lpszRight) < 0) {
  306. *lpszResult = '-';
  307. BCDSubtract(lpszResult+1, lpszRight, lpszLeft);
  308. return;
  309. }
  310. /* Point at values */
  311. lpszCurrent = lpszResult;
  312. lpszCurrentLeft = lpszLeft;
  313. lpszCurrentRight = lpszRight;
  314. /* Find decimal point (if any) */
  315. for (idxDecimalLeft = 0;
  316. idxDecimalLeft < s_lstrlen(lpszLeft);
  317. idxDecimalLeft++) {
  318. if (lpszLeft[idxDecimalLeft] == '.')
  319. break;
  320. }
  321. for (idxDecimalRight = 0;
  322. idxDecimalRight < s_lstrlen(lpszRight);
  323. idxDecimalRight++) {
  324. if (lpszRight[idxDecimalRight] == '.')
  325. break;
  326. }
  327. /* Put in excess characters */
  328. while (idxDecimalLeft > idxDecimalRight) {
  329. *lpszCurrent = *lpszCurrentLeft;
  330. lpszCurrent++;
  331. lpszCurrentLeft++;
  332. idxDecimalLeft--;
  333. }
  334. /* Subtract integer part */
  335. while (idxDecimalLeft > 0) {
  336. /* Get left digit */
  337. digit = (*lpszCurrentLeft) & 0x0F;
  338. lpszCurrentLeft++;
  339. idxDecimalLeft--;
  340. /* Add ten to it (to keep it positive) */
  341. digit += (10);
  342. /* Subtract right digit from it */
  343. digit -= ((*lpszCurrentRight) & 0x0F);
  344. lpszCurrentRight++;
  345. idxDecimalRight--;
  346. /* Is there a borrow? */
  347. if (digit < 10) {
  348. /* Yes. Propagate it to the higher digits */
  349. lpszBorrowDigit = lpszCurrent - 1;
  350. while (TRUE) {
  351. if (*lpszBorrowDigit != '0') {
  352. *lpszBorrowDigit = *lpszBorrowDigit - 1;
  353. break;
  354. }
  355. *lpszBorrowDigit = '9';
  356. lpszBorrowDigit--;
  357. }
  358. }
  359. else {
  360. /* No. Adjust digit */
  361. digit -= (10);
  362. }
  363. /* Save digit */
  364. *lpszCurrent = '0' + digit;
  365. lpszCurrent++;
  366. }
  367. /* Is there a fractional part? */
  368. if ((*lpszCurrentLeft != '\0') || (*lpszCurrentRight != '\0')) {
  369. /* Yes. Put in a decimal point */
  370. *lpszCurrent = '.';
  371. lpszCurrent++;
  372. /* Skip over the decimal points */
  373. if (*lpszCurrentRight == '.')
  374. lpszCurrentRight++;
  375. if (*lpszCurrentLeft == '.')
  376. lpszCurrentLeft++;
  377. /* Subtract the values */
  378. while ((*lpszCurrentLeft != '\0') || (*lpszCurrentRight != '\0')) {
  379. /* Get left digit */
  380. if (*lpszCurrentLeft != '\0') {
  381. digit = (*lpszCurrentLeft) & 0x0F;
  382. lpszCurrentLeft++;
  383. }
  384. else
  385. digit = 0;
  386. /* Add ten to it (to keep it positive) */
  387. digit += (10);
  388. /* Subtract right digit from it */
  389. if (*lpszCurrentRight != '\0') {
  390. digit -= ((*lpszCurrentRight) & 0x0F);
  391. lpszCurrentRight++;
  392. }
  393. /* Is there a borrow? */
  394. if (digit < 10) {
  395. /* Yes. Propagate it to the higher digits */
  396. lpszBorrowDigit = lpszCurrent - 1;
  397. while (TRUE) {
  398. if (*lpszBorrowDigit == '.')
  399. lpszBorrowDigit--;
  400. if (*lpszBorrowDigit != '0') {
  401. *lpszBorrowDigit = *lpszBorrowDigit - 1;
  402. break;
  403. }
  404. *lpszBorrowDigit = '9';
  405. lpszBorrowDigit--;
  406. }
  407. }
  408. else {
  409. /* No. Adjust digit */
  410. digit -= (10);
  411. }
  412. /* Save digit */
  413. *lpszCurrent = '0' + digit;
  414. lpszCurrent++;
  415. }
  416. }
  417. /* Put in terminating null */
  418. *lpszCurrent = '\0';
  419. /* Remove leading zeros */
  420. while (*lpszResult == '0')
  421. s_lstrcpy(lpszResult, lpszResult+1);
  422. }
  423. /***************************************************************************/
  424. void INTFUNC BCDTimes(LPUSTR lpszResult,
  425. LPUSTR lpszLeft,
  426. LPUSTR lpszRight,
  427. LPUSTR lpWorkBuffer)
  428. {
  429. SWORD idxDecimalLeft;
  430. SWORD idxDecimalRight;
  431. SWORD cDecimalDigits;
  432. LPUSTR lpszCurrent;
  433. UCHAR digit;
  434. UCHAR idx;
  435. /* Find decimal point (if any) */
  436. for (idxDecimalLeft = 0;
  437. idxDecimalLeft < s_lstrlen(lpszLeft);
  438. idxDecimalLeft++) {
  439. if (lpszLeft[idxDecimalLeft] == '.')
  440. break;
  441. }
  442. for (idxDecimalRight = 0;
  443. idxDecimalRight < s_lstrlen(lpszRight);
  444. idxDecimalRight++) {
  445. if (lpszRight[idxDecimalRight] == '.')
  446. break;
  447. }
  448. /* Remove decimal points from the values and figure out how many */
  449. /* decimal digits in the result */
  450. if (*(lpszLeft + idxDecimalLeft) == '.') {
  451. _fmemmove(lpszLeft + idxDecimalLeft, lpszLeft + idxDecimalLeft + 1,
  452. s_lstrlen(lpszLeft + idxDecimalLeft));
  453. cDecimalDigits = s_lstrlen(lpszLeft) - idxDecimalLeft;
  454. }
  455. else {
  456. cDecimalDigits = 0;
  457. idxDecimalLeft = -1;
  458. }
  459. if (*(lpszRight + idxDecimalRight) == '.') {
  460. _fmemmove(lpszRight + idxDecimalRight, lpszRight + idxDecimalRight + 1,
  461. s_lstrlen(lpszRight + idxDecimalRight));
  462. cDecimalDigits += (s_lstrlen(lpszRight) - idxDecimalRight);
  463. }
  464. else
  465. idxDecimalRight = -1;
  466. /* Put a zero in the workbuffer */
  467. s_lstrcpy(lpWorkBuffer, lpszRight);
  468. for (lpszCurrent = lpWorkBuffer; *lpszCurrent; lpszCurrent++)
  469. *lpszCurrent = '0';
  470. /* For each left digit... */
  471. lpszCurrent = lpszLeft;
  472. while (*lpszCurrent != '\0') {
  473. /* Add the right value into the result that many times */
  474. digit = *lpszCurrent & 0x0F;
  475. for (idx = 0; idx < digit; idx++) {
  476. BCDAdd(lpszResult, lpszRight, lpWorkBuffer);
  477. s_lstrcpy(lpWorkBuffer, lpszResult);
  478. }
  479. /* Look at next digit */
  480. lpszCurrent++;
  481. if (*lpszCurrent == '\0')
  482. break;
  483. /* Multiply the result by ten */
  484. s_lstrcat(lpWorkBuffer, "0");
  485. }
  486. s_lstrcpy(lpszResult, lpWorkBuffer);
  487. /* Put the decimal point back into the values */
  488. if (idxDecimalLeft != -1) {
  489. _fmemmove(lpszLeft + idxDecimalLeft + 1, lpszLeft + idxDecimalLeft,
  490. s_lstrlen(lpszLeft + idxDecimalLeft) + 1);
  491. lpszLeft[idxDecimalLeft] = '.';
  492. }
  493. if (idxDecimalRight != -1) {
  494. _fmemmove(lpszRight + idxDecimalRight + 1, lpszRight + idxDecimalRight,
  495. s_lstrlen(lpszRight + idxDecimalRight) + 1);
  496. lpszRight[idxDecimalRight] = '.';
  497. }
  498. if (cDecimalDigits != 0) {
  499. while (s_lstrlen(lpszResult) < cDecimalDigits) {
  500. _fmemmove(lpszResult + 1, lpszResult, s_lstrlen(lpszResult)+1);
  501. lpszResult[0] = '0';
  502. }
  503. _fmemmove(lpszResult + s_lstrlen(lpszResult) - cDecimalDigits + 1,
  504. lpszResult + s_lstrlen(lpszResult) - cDecimalDigits,
  505. s_lstrlen(lpszResult + s_lstrlen(lpszResult) - cDecimalDigits)+1);
  506. lpszResult[s_lstrlen(lpszResult) - cDecimalDigits - 1] = '.';
  507. }
  508. return;
  509. }
  510. /***************************************************************************/
  511. SWORD INTFUNC BCDDivide(LPUSTR lpszResult,
  512. SWORD scale,
  513. LPUSTR lpszLeft,
  514. LPUSTR lpszRight,
  515. LPUSTR lpWorkBuffer1,
  516. LPUSTR lpWorkBuffer2,
  517. LPUSTR lpWorkBuffer3)
  518. {
  519. SWORD decimalPosition;
  520. LPUSTR lpszCurrent;
  521. SWORD i;
  522. /* If right side is zero, return an error */
  523. for (lpszCurrent = lpszRight; *lpszCurrent; lpszCurrent++){
  524. if ((*lpszCurrent != '0') && (*lpszCurrent != '.'))
  525. break;
  526. }
  527. if (*lpszCurrent == '\0')
  528. return ERR_ZERODIVIDE;
  529. /* Copy the dividend */
  530. if (BCDCompareValues(lpszLeft, (LPUSTR)"") != 0)
  531. s_lstrcpy(lpWorkBuffer1, lpszLeft);
  532. else
  533. s_lstrcpy(lpWorkBuffer1, "");
  534. /* 'decimalPosition' specifies how places the decimal point has to be */
  535. /* moved. Positive values mean move to the right, negative values */
  536. /* mean move to the left */
  537. decimalPosition = 0;
  538. /* While the dividend is greater than the divisor, divide it by ten. */
  539. while (BCDCompareValues(lpWorkBuffer1, lpszRight) > 0) {
  540. BCDDivideByTen(lpWorkBuffer1);
  541. decimalPosition++;
  542. }
  543. /* While the dividend is less than the divisor, multiply it by ten. */
  544. if (s_lstrlen(lpWorkBuffer1) > 0) {
  545. while (BCDCompareValues(lpWorkBuffer1, lpszRight) < 0) {
  546. BCDMultiplyByTen(lpWorkBuffer1);
  547. decimalPosition--;
  548. }
  549. }
  550. /* Point at place to put result */
  551. lpszCurrent = lpszResult;
  552. /* If the scale is greater than zero, put in the decimal point */
  553. if (scale > 0) {
  554. *lpszCurrent = '.';
  555. lpszCurrent++;
  556. }
  557. decimalPosition++;
  558. /* For as many digits as are needed... */
  559. s_lstrcpy(lpWorkBuffer2, lpszRight);
  560. for (i = 0; i < scale + decimalPosition; i++) {
  561. /* Intialize the digit to zero */
  562. *lpszCurrent = '0';
  563. /* Count how many times divisor can be subtracted from dividend */
  564. while (BCDCompareValues(lpWorkBuffer1, lpWorkBuffer2) >= 0) {
  565. s_lstrcpy(lpWorkBuffer3, lpWorkBuffer1);
  566. BCDSubtract(lpWorkBuffer1, lpWorkBuffer3, lpWorkBuffer2);
  567. (*lpszCurrent)++;
  568. }
  569. /* Calculate the next digit of the result */
  570. lpszCurrent++;
  571. BCDDivideByTen(lpWorkBuffer2);
  572. }
  573. *lpszCurrent = '\0';
  574. /* If there is a positive scale, move the decimal point as need be */
  575. if (scale > 0) {
  576. while (decimalPosition > 0) {
  577. BCDMultiplyByTen(lpszResult);
  578. decimalPosition--;
  579. }
  580. while (decimalPosition < 0) {
  581. BCDDivideByTen(lpszResult);
  582. decimalPosition++;
  583. }
  584. }
  585. /* Remove leading zeros */
  586. while (*lpszResult == '0')
  587. s_lstrcpy(lpszResult, lpszResult+1);
  588. return ERR_SUCCESS;
  589. }
  590. /***************************************************************************/
  591. void INTFUNC BCDFixNegZero(LPUSTR szValue,
  592. SDWORD cbValueMax)
  593. /* Change "-0.000" to "0.000" if need be */
  594. {
  595. LPUSTR toPtr;
  596. SWORD idx;
  597. BOOL fZero;
  598. /* Is this a negative number? */
  599. if ((cbValueMax > 0) && (*szValue == '-')) {
  600. /* Yes. Figure out if it is zero */
  601. fZero = TRUE;
  602. toPtr = szValue + 1;
  603. for (idx = 0; idx < cbValueMax-1; idx++) {
  604. if (*toPtr == '\0')
  605. break;
  606. if ((*toPtr != '.') && (*toPtr != '0')) {
  607. fZero = FALSE;
  608. break;
  609. }
  610. toPtr++;
  611. }
  612. /* If it is zero, remove leading minus sign */
  613. if (fZero) {
  614. toPtr = szValue;
  615. for (idx = 1; idx < cbValueMax-1; idx++) {
  616. *toPtr = *(toPtr + 1);
  617. if (*toPtr == '\0')
  618. break;
  619. toPtr++;
  620. }
  621. *toPtr = '\0';
  622. }
  623. }
  624. }
  625. /***************************************************************************/
  626. /***************************************************************************/
  627. SWORD INTFUNC BCDNormalize(LPUSTR szValueFrom,
  628. SDWORD cbValueFrom,
  629. LPUSTR szValueTo,
  630. SDWORD cbValueToMax,
  631. SDWORD precision,
  632. SWORD scale)
  633. {
  634. LPUSTR toPtr;
  635. SDWORD toSize;
  636. SDWORD idxDecimalPoint;
  637. SWORD idx;
  638. BOOL fNegative;
  639. BOOL fTruncated;
  640. SDWORD right;
  641. SDWORD left;
  642. /* Point to destination */
  643. toPtr = szValueTo;
  644. toSize = cbValueToMax;
  645. /* Trim off leading spaces */
  646. while ((cbValueFrom > 0) && (*szValueFrom == ' ')) {
  647. szValueFrom++;
  648. cbValueFrom--;
  649. }
  650. /* See if value is positive or negative */
  651. if (*szValueFrom != '-')
  652. fNegative = FALSE;
  653. else {
  654. fNegative = TRUE;
  655. szValueFrom++;
  656. cbValueFrom--;
  657. }
  658. /* Trim off leading zeros */
  659. while ((cbValueFrom > 0) && (*szValueFrom == '0')) {
  660. szValueFrom++;
  661. cbValueFrom--;
  662. }
  663. /* Trim off trailing spaces */
  664. while ((cbValueFrom > 0) && (szValueFrom[cbValueFrom - 1] == ' '))
  665. cbValueFrom--;
  666. /* Is there a decimal point? */
  667. for (idx = 0; idx < cbValueFrom; idx++) {
  668. if (szValueFrom[idx] == '.') {
  669. /* Yes. Trim off trailing zeros */
  670. while ((cbValueFrom > 0) && (szValueFrom[cbValueFrom - 1] == '0'))
  671. cbValueFrom--;
  672. break;
  673. }
  674. }
  675. /* Find location of decimal point (if any) */
  676. idxDecimalPoint = -1;
  677. for (idx = 0; idx < cbValueFrom; idx++) {
  678. if (szValueFrom[idx] == '.') {
  679. idxDecimalPoint = idx;
  680. break;
  681. }
  682. }
  683. /* If scale is zero, remove decimal point and digits */
  684. fTruncated = FALSE;
  685. if ((idxDecimalPoint != -1) && (scale == 0)) {
  686. if (idxDecimalPoint < (cbValueFrom - 1))
  687. fTruncated = TRUE;
  688. cbValueFrom = idxDecimalPoint;
  689. idxDecimalPoint = -1;
  690. }
  691. /* Figure out how many digits to the right of the decimal point */
  692. if (idxDecimalPoint == -1)
  693. right = 0;
  694. else
  695. right = cbValueFrom - idxDecimalPoint - 1;
  696. /* If too many digits to the right of the decimal point, remove them */
  697. while (right > scale) {
  698. cbValueFrom--;
  699. right--;
  700. fTruncated = TRUE;
  701. }
  702. /* Figure out how many digits to the left of the decimal point */
  703. if (idxDecimalPoint == -1)
  704. left = cbValueFrom;
  705. else
  706. left = cbValueFrom - right - 1;
  707. /* If too many digits to the left of the decimal point, error */
  708. if (left > (precision - scale))
  709. return ERR_OUTOFRANGE;
  710. /* Copy the value to the output buffer. If negative put in the sign */
  711. if (fNegative) {
  712. if (toSize > 0) {
  713. *toPtr = '-';
  714. toPtr++;
  715. toSize--;
  716. }
  717. else
  718. return ERR_OUTOFRANGE;
  719. }
  720. /* Put the digits to the left of the decimal in */
  721. while (left > 0) {
  722. if (toSize > 0) {
  723. *toPtr = *szValueFrom;
  724. szValueFrom++;
  725. toPtr++;
  726. toSize--;
  727. }
  728. else
  729. return ERR_OUTOFRANGE;
  730. left--;
  731. }
  732. /* Decimal part needed? */
  733. if (scale > 0) {
  734. /* Put in the decimal point */
  735. if (toSize > 0) {
  736. *toPtr = '.';
  737. toPtr++;
  738. toSize--;
  739. }
  740. else
  741. fTruncated = TRUE;
  742. /* Put in the decimal digits */
  743. if (idxDecimalPoint != -1)
  744. szValueFrom++;
  745. while (scale > 0) {
  746. if (toSize > 0) {
  747. if (right > 0) {
  748. *toPtr = *szValueFrom;
  749. szValueFrom++;
  750. right--;
  751. }
  752. else {
  753. *toPtr = '0';
  754. }
  755. toPtr++;
  756. toSize--;
  757. }
  758. else
  759. fTruncated = TRUE;
  760. scale--;
  761. }
  762. }
  763. /* Put in null terminator */
  764. if (toSize > 0) {
  765. *toPtr = '\0';
  766. toPtr++;
  767. toSize--;
  768. }
  769. else
  770. fTruncated = TRUE;
  771. BCDFixNegZero(szValueTo, cbValueToMax);
  772. if (fTruncated)
  773. return ERR_DATATRUNCATED;
  774. return ERR_SUCCESS;
  775. }
  776. /***************************************************************************/
  777. RETCODE INTFUNC BCDCompare(LPSQLNODE lpSqlNode, LPSQLNODE lpSqlNodeLeft,
  778. UWORD Operator, LPSQLNODE lpSqlNodeRight)
  779. /* Compares two BCD values as follows: */
  780. /* lpSqlNode->value.Double = lpSqlNodeLeft Operator lpSqlNodeRight */
  781. {
  782. SWORD fComp;
  783. /* Check parameters */
  784. if ((lpSqlNode->sqlDataType != TYPE_INTEGER) ||
  785. (lpSqlNodeLeft->sqlDataType != TYPE_NUMERIC) ||
  786. ((Operator != OP_NEG)&&(lpSqlNodeRight->sqlDataType != TYPE_NUMERIC)))
  787. return ERR_INTERNAL;
  788. /* Compare the values */
  789. if ((lpSqlNodeLeft->value.String[0] != '-') &&
  790. (lpSqlNodeRight->value.String[0] != '-')) {
  791. fComp = BCDCompareValues(lpSqlNodeLeft->value.String,
  792. lpSqlNodeRight->value.String);
  793. }
  794. else if ((lpSqlNodeLeft->value.String[0] != '-') &&
  795. (lpSqlNodeRight->value.String[0] == '-'))
  796. fComp = 1;
  797. else if ((lpSqlNodeLeft->value.String[0] == '-') &&
  798. (lpSqlNodeRight->value.String[0] != '-'))
  799. fComp = -1;
  800. else {
  801. fComp = BCDCompareValues(lpSqlNodeRight->value.String+1,
  802. lpSqlNodeLeft->value.String+1);
  803. }
  804. /* Figure out the answer */
  805. switch (Operator) {
  806. case OP_EQ:
  807. if (fComp == 0)
  808. lpSqlNode->value.Double = TRUE;
  809. else
  810. lpSqlNode->value.Double = FALSE;
  811. break;
  812. case OP_NE:
  813. if (fComp != 0)
  814. lpSqlNode->value.Double = TRUE;
  815. else
  816. lpSqlNode->value.Double = FALSE;
  817. break;
  818. case OP_LE:
  819. if (fComp <= 0)
  820. lpSqlNode->value.Double = TRUE;
  821. else
  822. lpSqlNode->value.Double = FALSE;
  823. break;
  824. case OP_LT:
  825. if (fComp < 0)
  826. lpSqlNode->value.Double = TRUE;
  827. else
  828. lpSqlNode->value.Double = FALSE;
  829. break;
  830. case OP_GE:
  831. if (fComp >= 0)
  832. lpSqlNode->value.Double = TRUE;
  833. else
  834. lpSqlNode->value.Double = FALSE;
  835. break;
  836. case OP_GT:
  837. if (fComp > 0)
  838. lpSqlNode->value.Double = TRUE;
  839. else
  840. lpSqlNode->value.Double = FALSE;
  841. break;
  842. case OP_LIKE:
  843. case OP_NOTLIKE:
  844. default:
  845. return ERR_INTERNAL;
  846. }
  847. return ERR_SUCCESS;
  848. }
  849. /***************************************************************************/
  850. RETCODE INTFUNC BCDAlgebra(LPSQLNODE lpSqlNode, LPSQLNODE lpSqlNodeLeft,
  851. UWORD Operator, LPSQLNODE lpSqlNodeRight,
  852. LPUSTR lpWorkBuffer1, LPUSTR lpWorkBuffer2,
  853. LPUSTR lpWorkBuffer3)
  854. /* Perfoms algebraic operation in two numerical values as follows: */
  855. /* lpSqlNode lpSqlNodeLeft Operator lpSqlNodeRight */
  856. {
  857. RETCODE err;
  858. /* Check parameters */
  859. if ((Operator != OP_NEG) && (lpSqlNodeRight == NULL))
  860. return ERR_INTERNAL;
  861. if ((lpSqlNode->sqlDataType != TYPE_NUMERIC) ||
  862. (lpSqlNodeLeft->sqlDataType != TYPE_NUMERIC) ||
  863. ((Operator != OP_NEG)&&(lpSqlNodeRight->sqlDataType != TYPE_NUMERIC)))
  864. return ERR_INTERNAL;
  865. /* Do the operation */
  866. switch (Operator) {
  867. case OP_NEG:
  868. if (lpSqlNodeLeft->value.String[0] == '-')
  869. s_lstrcpy(lpSqlNode->value.String, lpSqlNodeLeft->value.String+1);
  870. else {
  871. lpSqlNode->value.String[0] = '-';
  872. s_lstrcpy(lpSqlNode->value.String+1, lpSqlNodeLeft->value.String);
  873. }
  874. break;
  875. case OP_PLUS:
  876. if ((lpSqlNodeLeft->value.String[0] != '-') &&
  877. (lpSqlNodeRight->value.String[0] != '-')) {
  878. BCDAdd(lpSqlNode->value.String,
  879. lpSqlNodeLeft->value.String,
  880. lpSqlNodeRight->value.String);
  881. }
  882. else if ((lpSqlNodeLeft->value.String[0] != '-') &&
  883. (lpSqlNodeRight->value.String[0] == '-')) {
  884. BCDSubtract(lpSqlNode->value.String,
  885. lpSqlNodeLeft->value.String,
  886. lpSqlNodeRight->value.String+1);
  887. }
  888. else if ((lpSqlNodeLeft->value.String[0] == '-') &&
  889. (lpSqlNodeRight->value.String[0] != '-')) {
  890. BCDSubtract(lpSqlNode->value.String,
  891. lpSqlNodeRight->value.String,
  892. lpSqlNodeLeft->value.String+1);
  893. }
  894. else {
  895. lpSqlNode->value.String[0] = '-';
  896. BCDAdd(lpSqlNode->value.String+1,
  897. lpSqlNodeLeft->value.String+1,
  898. lpSqlNodeRight->value.String+1);
  899. }
  900. break;
  901. case OP_MINUS:
  902. if ((lpSqlNodeLeft->value.String[0] != '-') &&
  903. (lpSqlNodeRight->value.String[0] != '-')) {
  904. BCDSubtract(lpSqlNode->value.String,
  905. lpSqlNodeLeft->value.String,
  906. lpSqlNodeRight->value.String);
  907. }
  908. else if ((lpSqlNodeLeft->value.String[0] != '-') &&
  909. (lpSqlNodeRight->value.String[0] == '-')) {
  910. BCDAdd(lpSqlNode->value.String,
  911. lpSqlNodeLeft->value.String,
  912. lpSqlNodeRight->value.String+1);
  913. }
  914. else if ((lpSqlNodeLeft->value.String[0] == '-') &&
  915. (lpSqlNodeRight->value.String[0] != '-')) {
  916. lpSqlNode->value.String[0] = '-';
  917. BCDAdd(lpSqlNode->value.String+1,
  918. lpSqlNodeLeft->value.String+1,
  919. lpSqlNodeRight->value.String);
  920. }
  921. else {
  922. BCDSubtract(lpSqlNode->value.String,
  923. lpSqlNodeRight->value.String+1,
  924. lpSqlNodeLeft->value.String+1);
  925. }
  926. break;
  927. case OP_TIMES:
  928. if ((lpSqlNodeLeft->value.String[0] != '-') &&
  929. (lpSqlNodeRight->value.String[0] != '-')) {
  930. BCDTimes(lpSqlNode->value.String,
  931. lpSqlNodeLeft->value.String,
  932. lpSqlNodeRight->value.String,
  933. lpWorkBuffer1);
  934. }
  935. else if ((lpSqlNodeLeft->value.String[0] != '-') &&
  936. (lpSqlNodeRight->value.String[0] == '-')) {
  937. lpSqlNode->value.String[0] = '-';
  938. BCDTimes(lpSqlNode->value.String+1,
  939. lpSqlNodeLeft->value.String,
  940. lpSqlNodeRight->value.String+1,
  941. lpWorkBuffer1);
  942. }
  943. else if ((lpSqlNodeLeft->value.String[0] == '-') &&
  944. (lpSqlNodeRight->value.String[0] != '-')) {
  945. lpSqlNode->value.String[0] = '-';
  946. BCDTimes(lpSqlNode->value.String+1,
  947. lpSqlNodeLeft->value.String+1,
  948. lpSqlNodeRight->value.String,
  949. lpWorkBuffer1);
  950. }
  951. else {
  952. BCDTimes(lpSqlNode->value.String,
  953. lpSqlNodeLeft->value.String+1,
  954. lpSqlNodeRight->value.String+1,
  955. lpWorkBuffer1);
  956. }
  957. break;
  958. case OP_DIVIDEDBY:
  959. if ((lpSqlNodeLeft->value.String[0] != '-') &&
  960. (lpSqlNodeRight->value.String[0] != '-')) {
  961. err = BCDDivide(lpSqlNode->value.String,
  962. lpSqlNode->sqlScale,
  963. lpSqlNodeLeft->value.String,
  964. lpSqlNodeRight->value.String,
  965. lpWorkBuffer1, lpWorkBuffer2, lpWorkBuffer3);
  966. }
  967. else if ((lpSqlNodeLeft->value.String[0] != '-') &&
  968. (lpSqlNodeRight->value.String[0] == '-')) {
  969. lpSqlNode->value.String[0] = '-';
  970. err = BCDDivide(lpSqlNode->value.String+1,
  971. lpSqlNode->sqlScale,
  972. lpSqlNodeLeft->value.String,
  973. lpSqlNodeRight->value.String+1,
  974. lpWorkBuffer1, lpWorkBuffer2, lpWorkBuffer3);
  975. }
  976. else if ((lpSqlNodeLeft->value.String[0] == '-') &&
  977. (lpSqlNodeRight->value.String[0] != '-')) {
  978. lpSqlNode->value.String[0] = '-';
  979. err = BCDDivide(lpSqlNode->value.String+1,
  980. lpSqlNode->sqlScale,
  981. lpSqlNodeLeft->value.String+1,
  982. lpSqlNodeRight->value.String,
  983. lpWorkBuffer1, lpWorkBuffer2, lpWorkBuffer3);
  984. }
  985. else {
  986. err = BCDDivide(lpSqlNode->value.String,
  987. lpSqlNode->sqlScale,
  988. lpSqlNodeLeft->value.String+1,
  989. lpSqlNodeRight->value.String+1,
  990. lpWorkBuffer1, lpWorkBuffer2, lpWorkBuffer3);
  991. }
  992. if (err != ERR_SUCCESS)
  993. return err;
  994. break;
  995. default:
  996. return ERR_INTERNAL;
  997. }
  998. BCDFixNegZero(lpSqlNode->value.String,s_lstrlen(lpSqlNode->value.String)+1);
  999. return ERR_SUCCESS;
  1000. }
  1001. /***************************************************************************/