ChipMaster's bwBASIC This also includes history going back to v2.10. *WARN* some binary files might have been corrupted by CRLF.
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.
 
 
 
 
 
 

1911 lines
44 KiB

  1. /****************************************************************
  2. bwb_ops.c Expression Parsing Operations
  3. for Bywater BASIC Interpreter
  4. Copyright (c) 1993, Ted A. Campbell
  5. Bywater Software
  6. email: tcamp@delphi.com
  7. Copyright and Permissions Information:
  8. All U.S. and international rights are claimed by the author,
  9. Ted A. Campbell.
  10. This software is released under the terms of the GNU General
  11. Public License (GPL), which is distributed with this software
  12. in the file "COPYING". The GPL specifies the terms under
  13. which users may copy and use the software in this distribution.
  14. A separate license is available for commercial distribution,
  15. for information on which you should contact the author.
  16. ***************************************************************/
  17. /*---------------------------------------------------------------*/
  18. /* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
  19. /* 11/1995 (eidetics@cerf.net). */
  20. /* */
  21. /* Those additionally marked with "DD" were at the suggestion of */
  22. /* Dale DePriest (daled@cadence.com). */
  23. /* */
  24. /* Version 3.00 by Howard Wulf, AF5NE */
  25. /* */
  26. /*---------------------------------------------------------------*/
  27. #include "bwbasic.h"
  28. /* declarations for functions visible in this file only */
  29. static int
  30. op_oplevel(int level);
  31. static int
  32. op_add(int level, int precision);
  33. static int
  34. op_subtract(int level, int precision);
  35. static int
  36. op_multiply(int level, int precision);
  37. static int
  38. op_divide(int level, int precision);
  39. static int
  40. op_assign(int level, int precision);
  41. static int
  42. op_equals(int level, int precision);
  43. static int
  44. op_lessthan(int level, int precision);
  45. static int
  46. op_greaterthan(int level, int precision);
  47. static int
  48. op_lteq(int level, int precision);
  49. static int
  50. op_gteq(int level, int precision);
  51. static int
  52. op_notequal(int level, int precision);
  53. static int
  54. op_modulus(int level, int precision);
  55. static int
  56. op_exponent(int level, int precision);
  57. static int
  58. op_intdiv(int level, int precision);
  59. static int
  60. op_or(int level, int precision);
  61. static int
  62. op_and(int level, int precision);
  63. static int
  64. op_not(int level, int precision);
  65. static int
  66. op_xor(int level, int precision);
  67. static int
  68. op_imp(int level, int precision);
  69. static int
  70. op_eqv(int level, int precision);
  71. static int
  72. op_negation(int level, int precision); /* JBV */
  73. static int
  74. op_posation(int level, int precision);
  75. static int
  76. op_islevelstr(int level);
  77. static int
  78. op_getprecision(int level);
  79. static int
  80. op_isoperator(int operation);
  81. static int
  82. op_pulldown(int how_far);
  83. static int op_level;
  84. /***************************************************************
  85. FUNCTION: exp_operation()
  86. DESCRIPTION: This function performs whatever operations
  87. are necessary at the end of function bwb_exp()
  88. (i.e., the end of the parsing of an expression;
  89. see file bwb_exp.c).
  90. ***************************************************************/
  91. int
  92. exp_operation(int entry_level)
  93. {
  94. register int precedence;
  95. int operator;
  96. bwx_DEBUG(__FUNCTION__);
  97. /* cycle through all levels of precedence and perform required
  98. * operations */
  99. for (precedence = 0; precedence <= MAX_PRECEDENCE; ++precedence)
  100. {
  101. /* Operation loop: cycle through every level above entry
  102. * level and perform required operations as needed */
  103. op_level = entry_level + 1;
  104. while ((op_level < CURTASK expsc)
  105. && (op_isoperator(CURTASK exps[op_level].operation) == FALSE))
  106. {
  107. ++op_level;
  108. }
  109. while ((op_level > entry_level) && (op_level < CURTASK expsc))
  110. {
  111. /* see if the operation at this level is an operator
  112. * with the appropriate precedence level by running
  113. * through the table of operators */
  114. for (operator = 0; operator < NUM_OPERATORS; ++operator)
  115. {
  116. if (exp_ops[operator].operation == CURTASK exps[op_level].operation)
  117. {
  118. /* check for appropriate level of
  119. * precedence */
  120. if (exp_ops[operator].precedence == precedence)
  121. {
  122. op_oplevel(op_level); /* perform the operation */
  123. }
  124. }
  125. }
  126. /* advance level if appropriate; one must check,
  127. * however, since the op_oplevel() function may have
  128. * decremented CURTASK expsc */
  129. if (op_level < CURTASK expsc)
  130. {
  131. ++op_level;
  132. while ((op_isoperator(CURTASK exps[op_level].operation) == FALSE)
  133. && (op_level < CURTASK expsc))
  134. {
  135. ++op_level;
  136. }
  137. } /* end of increment of op_level */
  138. } /* end of for loop for stack levels */
  139. } /* end of for loop for precedence levels */
  140. return TRUE;
  141. } /* end of function exp_operation() */
  142. /***************************************************************
  143. FUNCTION: op_oplevel()
  144. DESCRIPTION: This function performs a specific operation
  145. at a specific level as the expression parser
  146. resolves its arguments.
  147. ***************************************************************/
  148. static int
  149. op_oplevel(int level)
  150. {
  151. int precision;
  152. bwx_DEBUG(__FUNCTION__);
  153. /* set the precision */
  154. if ((precision = op_getprecision(level)) == OP_ERROR)
  155. {
  156. op_pulldown(2);
  157. sprintf(bwb_ebuf, "exp_operation(): failed to set precision.");
  158. bwb_error(bwb_ebuf);
  159. return FALSE;
  160. }
  161. /* precision is set correctly */
  162. else
  163. {
  164. switch (CURTASK exps[level].operation)
  165. {
  166. case OP_ADD:
  167. op_add(level, precision);
  168. break;
  169. case OP_SUBTRACT:
  170. op_subtract(level, precision);
  171. break;
  172. case OP_MULTIPLY:
  173. op_multiply(level, precision);
  174. break;
  175. case OP_DIVIDE:
  176. op_divide(level, precision);
  177. break;
  178. case OP_ASSIGN:
  179. op_assign(level, precision);
  180. break;
  181. case OP_EQUALS:
  182. op_equals(level, precision);
  183. break;
  184. case OP_LESSTHAN:
  185. op_lessthan(level, precision);
  186. break;
  187. case OP_GREATERTHAN:
  188. op_greaterthan(level, precision);
  189. break;
  190. case OP_LTEQ:
  191. op_lteq(level, precision);
  192. break;
  193. case OP_GTEQ:
  194. op_gteq(level, precision);
  195. break;
  196. case OP_NOTEQUAL:
  197. op_notequal(level, precision);
  198. break;
  199. case OP_MODULUS:
  200. op_modulus(level, precision);
  201. break;
  202. case OP_INTDIVISION:
  203. op_intdiv(level, precision);
  204. break;
  205. case OP_OR:
  206. op_or(level, precision);
  207. break;
  208. case OP_AND:
  209. op_and(level, precision);
  210. break;
  211. case OP_NOT:
  212. op_not(level, precision);
  213. break;
  214. case OP_XOR:
  215. op_xor(level, precision);
  216. break;
  217. case OP_IMPLIES:
  218. op_imp(level, precision);
  219. break;
  220. case OP_EQUIV:
  221. op_eqv(level, precision);
  222. break;
  223. case OP_EXPONENT:
  224. op_exponent(level, precision);
  225. break;
  226. case OP_NEGATION: /* JBV */
  227. op_negation(level, precision);
  228. break;
  229. case OP_POSATION:
  230. op_posation(level, precision);
  231. break;
  232. default:
  233. sprintf(bwb_ebuf, "PROGRAMMING ERROR: operator <%d> not (yet) supported.", CURTASK exps[level].operation);
  234. op_pulldown(2);
  235. bwb_error(bwb_ebuf);
  236. return FALSE;
  237. break;
  238. } /* end of case statement for operators */
  239. } /* end of else statement, precision set */
  240. return TRUE;
  241. } /* end of function op_oplevel() */
  242. /***************************************************************
  243. FUNCTION: op_isoperator()
  244. DESCRIPTION: This function detects whether its argument
  245. is an operator.
  246. ***************************************************************/
  247. static int
  248. op_isoperator(int operation)
  249. {
  250. register int c;
  251. bwx_DEBUG(__FUNCTION__);
  252. for (c = 0; c < NUM_OPERATORS; ++c)
  253. {
  254. if (operation == exp_ops[c].operation)
  255. {
  256. return TRUE;
  257. }
  258. }
  259. /* test failed; return FALSE */
  260. return FALSE;
  261. }
  262. /***************************************************************
  263. FUNCTION: op_add()
  264. DESCRIPTION: This function adds two numbers or
  265. concatenates two strings.
  266. ***************************************************************/
  267. static int
  268. op_add(int level, int precision)
  269. {
  270. bwx_DEBUG(__FUNCTION__);
  271. switch (precision)
  272. {
  273. case STRING:
  274. /* both sides of the operation should be strings for string
  275. * addition; if not, report an error */
  276. if ((op_islevelstr(level - 1) != TRUE)
  277. || (op_islevelstr(level + 1) != TRUE))
  278. {
  279. sprintf(bwb_ebuf, "in op_add(): Type mismatch in string addition.");
  280. bwb_error(bwb_ebuf);
  281. return FALSE;
  282. }
  283. /* concatenate the two strings */
  284. {
  285. static bstring b; /* JBV */
  286. b.rab = FALSE; /* JBV */
  287. str_btob(&b, exp_getsval(&(CURTASK exps[level - 1])));
  288. str_cat(&b, exp_getsval(&(CURTASK exps[level + 1])));
  289. str_btob(&(CURTASK exps[level - 1].sval), &b);
  290. CURTASK exps[level - 1].operation = CONST_STRING;
  291. }
  292. break;
  293. case NUMBER:
  294. CURTASK exps[level - 1].nval
  295. = exp_getnval(&(CURTASK exps[level - 1]))
  296. + exp_getnval(&(CURTASK exps[level + 1]));
  297. CURTASK exps[level - 1].operation = NUMBER;
  298. break;
  299. }
  300. /* set variable to requested precision */
  301. CURTASK exps[level - 1].type = (char) precision;
  302. /* decrement the stack twice */
  303. op_pulldown(2);
  304. return TRUE;
  305. }
  306. /***************************************************************
  307. FUNCTION: op_subtract()
  308. DESCRIPTION: This function subtracts the number on
  309. the left from the number on the right.
  310. ***************************************************************/
  311. static int
  312. op_subtract(int level, int precision)
  313. {
  314. bwx_DEBUG(__FUNCTION__);
  315. switch (precision)
  316. {
  317. case STRING:
  318. /* both sides of the operation should be numbers for string
  319. * addition; if not, report an error */
  320. sprintf(bwb_ebuf, "Strings cannot be subtracted.");
  321. bwb_error(bwb_ebuf);
  322. return FALSE;
  323. break;
  324. case NUMBER:
  325. CURTASK exps[level - 1].nval
  326. = exp_getnval(&(CURTASK exps[level - 1]))
  327. - exp_getnval(&(CURTASK exps[level + 1]));
  328. break;
  329. }
  330. /* set variable to requested precision */
  331. CURTASK exps[level - 1].type = (char) precision;
  332. CURTASK exps[level - 1].operation = NUMBER;
  333. /* decrement the stack twice */
  334. op_pulldown(2);
  335. return TRUE;
  336. }
  337. /***************************************************************
  338. FUNCTION: op_multiply()
  339. DESCRIPTION: This function multiplies the number on
  340. the left by the number on the right.
  341. ***************************************************************/
  342. static int
  343. op_multiply(int level, int precision)
  344. {
  345. bwx_DEBUG(__FUNCTION__);
  346. switch (precision)
  347. {
  348. case STRING:
  349. /* both sides of the operation should be numbers for string
  350. * addition; if not, report an error */
  351. sprintf(bwb_ebuf, "Strings cannot be multiplied.");
  352. bwb_error(bwb_ebuf);
  353. return FALSE;
  354. break;
  355. case NUMBER:
  356. CURTASK exps[level - 1].nval
  357. = exp_getnval(&(CURTASK exps[level - 1]))
  358. * exp_getnval(&(CURTASK exps[level + 1]));
  359. break;
  360. }
  361. /* set variable to requested precision */
  362. CURTASK exps[level - 1].type = (char) precision;
  363. CURTASK exps[level - 1].operation = NUMBER;
  364. /* decrement the stack twice */
  365. op_pulldown(2);
  366. return TRUE;
  367. }
  368. /***************************************************************
  369. FUNCTION: op_divide()
  370. DESCRIPTION: This function divides the number on
  371. the left by the number on the right.
  372. ***************************************************************/
  373. static int
  374. op_divide(int level, int precision)
  375. {
  376. bwx_DEBUG(__FUNCTION__);
  377. switch (precision)
  378. {
  379. case STRING:
  380. /* both sides of the operation should be numbers for
  381. * division; if not, report an error */
  382. sprintf(bwb_ebuf, "Strings cannot be divided.");
  383. bwb_error(bwb_ebuf);
  384. return FALSE;
  385. break;
  386. case NUMBER:
  387. if (exp_getnval(&(CURTASK exps[level + 1]))
  388. == 0)
  389. {
  390. /* - Evaluation of an expression results in division
  391. * by zero (nonfatal, the recommended recovery
  392. * procedure is to supply machine infinity with the
  393. * sign of the numerator and continue) */
  394. if (exp_getnval(&(CURTASK exps[level - 1])) < 0)
  395. {
  396. /* NEGATIVE */
  397. CURTASK exps[level - 1].nval = -(DBL_MAX); /* NEGATIVE INFINITY */
  398. }
  399. else
  400. {
  401. /* POSITIVE */
  402. CURTASK exps[level - 1].nval = (DBL_MAX); /* POSITIVE INFINITY */
  403. }
  404. bwb_Warning_Overflow("*** WARNING: Divide by 0 ***");
  405. }
  406. else
  407. {
  408. CURTASK exps[level - 1].nval
  409. = exp_getnval(&(CURTASK exps[level - 1]))
  410. / exp_getnval(&(CURTASK exps[level + 1]));
  411. }
  412. break;
  413. }
  414. /* set variable to requested precision */
  415. CURTASK exps[level - 1].type = (char) precision;
  416. CURTASK exps[level - 1].operation = NUMBER;
  417. /* decrement the stack twice */
  418. op_pulldown(2);
  419. return TRUE;
  420. }
  421. BasicNumberType
  422. VerifyNumeric(BasicNumberType Value)
  423. {
  424. bwx_DEBUG(__FUNCTION__);
  425. /* check Value */
  426. if (isnan(Value))
  427. {
  428. /*** FATAL - INTERNAL ERROR - SHOULD NEVER HAPPEN ***/
  429. bwb_error("NOT A NUMBER");
  430. return 0;
  431. }
  432. else
  433. if (isinf(Value))
  434. {
  435. /* - Evaluation of an expression results in an overflow
  436. * (nonfatal, the recommended recovery procedure is to supply
  437. * machine in- finity with the algebraically correct sign and
  438. * continue). */
  439. if (Value < 0)
  440. {
  441. Value = -DBL_MAX;
  442. }
  443. else
  444. {
  445. Value = DBL_MAX;
  446. }
  447. bwb_Warning_Overflow("*** Arithmetic Overflow ***");
  448. }
  449. return Value;
  450. }
  451. /***************************************************************
  452. FUNCTION: op_assign()
  453. DESCRIPTION: This function assigns the value in the
  454. right hand side to the variable in the
  455. left hand side.
  456. ***************************************************************/
  457. static int
  458. op_assign(int level, int precision)
  459. {
  460. bwx_DEBUG(__FUNCTION__);
  461. /* Make sure the position one level below is a variable */
  462. if (CURTASK exps[level - 1].operation != VARIABLE)
  463. {
  464. op_pulldown(2);
  465. sprintf(bwb_ebuf, "in op_assign(): Assignment must be to variable: level -1 <%d> op <%d>",
  466. level - 1, CURTASK exps[level - 1].operation);
  467. bwb_error(bwb_ebuf);
  468. return FALSE;
  469. }
  470. if (CURTASK exps[level - 1].type != CURTASK exps[level + 1].type)
  471. {
  472. bwb_error("Type Mismatch");
  473. return FALSE;
  474. }
  475. /* if the assignment is numerical, then the precision should be set
  476. * to that of the variable on the left-hand side of the assignment */
  477. if (precision != STRING)
  478. {
  479. precision = (int) CURTASK exps[level - 1].type;
  480. }
  481. switch (precision)
  482. {
  483. case STRING:
  484. str_btob(exp_getsval(&(CURTASK exps[level - 1])),
  485. exp_getsval(&(CURTASK exps[level + 1])));
  486. break;
  487. case NUMBER:
  488. if (TRUE)
  489. {
  490. double Value;
  491. Value = exp_getnval(&(CURTASK exps[level + 1]));
  492. Value = VerifyNumeric(Value);
  493. /* assign Value */
  494. *var_findnval(CURTASK exps[level - 1].xvar,
  495. CURTASK exps[level - 1].array_pos) =
  496. CURTASK exps[level - 1].nval =
  497. Value;
  498. }
  499. break;
  500. default:
  501. sprintf(bwb_ebuf, "in op_assign(): Variable before assignment operator has unidentified type.");
  502. bwb_error(bwb_ebuf);
  503. return FALSE;
  504. }
  505. /* set variable to requested precision */
  506. CURTASK exps[level - 1].type = (char) precision;
  507. /* decrement the stack twice */
  508. op_pulldown(2);
  509. return TRUE;
  510. }
  511. /***************************************************************
  512. FUNCTION: op_equals()
  513. DESCRIPTION: This function compares two values and
  514. returns an integer value: TRUE if they are
  515. the same and FALSE if they are not.
  516. ***************************************************************/
  517. static int
  518. op_equals(int level, int precision)
  519. {
  520. bwx_DEBUG(__FUNCTION__);
  521. switch (precision)
  522. {
  523. case STRING:
  524. /* both sides of the operation should be strings for string
  525. * addition; if not, report an error */
  526. if ((op_islevelstr(level - 1) != TRUE)
  527. || (op_islevelstr(level + 1) != TRUE))
  528. {
  529. sprintf(bwb_ebuf, "in op_equals(): Type mismatch in string comparison.");
  530. bwb_error(bwb_ebuf);
  531. return FALSE;
  532. }
  533. /* compare the two strings */
  534. if (str_cmp(exp_getsval(&(CURTASK exps[level - 1])),
  535. exp_getsval(&(CURTASK exps[level + 1]))) == 0)
  536. {
  537. CURTASK exps[level - 1].nval = TRUE;
  538. }
  539. else
  540. {
  541. CURTASK exps[level - 1].nval = FALSE;
  542. }
  543. break;
  544. case NUMBER:
  545. if (exp_getnval(&(CURTASK exps[level - 1]))
  546. == exp_getnval(&(CURTASK exps[level + 1])))
  547. {
  548. CURTASK exps[level - 1].nval = TRUE;
  549. }
  550. else
  551. {
  552. CURTASK exps[level - 1].nval = FALSE;
  553. }
  554. break;
  555. }
  556. /* set variable to integer and operation to NUMBER: this must be done
  557. * at the end, since at the beginning it might cause op_islevelstr()
  558. * to return a false error */
  559. CURTASK exps[level - 1].type = NUMBER;
  560. CURTASK exps[level - 1].operation = NUMBER;
  561. /* decrement the stack */
  562. op_pulldown(2);
  563. return TRUE;
  564. }
  565. /***************************************************************
  566. FUNCTION: op_lessthan()
  567. DESCRIPTION: This function compares two values and
  568. returns an integer value: TRUE if the
  569. left hand value is less than the right,
  570. and FALSE if it is not.
  571. ***************************************************************/
  572. static int
  573. op_lessthan(int level, int precision)
  574. {
  575. bwx_DEBUG(__FUNCTION__);
  576. switch (precision)
  577. {
  578. case STRING:
  579. /* both sides of the operation should be numbers for string
  580. * addition; if not, report an error */
  581. if ((op_islevelstr(level - 1) != TRUE)
  582. || (op_islevelstr(level + 1) != TRUE))
  583. {
  584. sprintf(bwb_ebuf, "Type mismatch in string comparison.");
  585. bwb_error(bwb_ebuf);
  586. return FALSE;
  587. }
  588. /* compare the two strings */
  589. if (str_cmp(exp_getsval(&(CURTASK exps[level - 1])),
  590. exp_getsval(&(CURTASK exps[level + 1]))) < 0)
  591. {
  592. CURTASK exps[level - 1].nval = TRUE;
  593. }
  594. else
  595. {
  596. CURTASK exps[level - 1].nval = FALSE;
  597. }
  598. break;
  599. case NUMBER:
  600. if (exp_getnval(&(CURTASK exps[level - 1]))
  601. < exp_getnval(&(CURTASK exps[level + 1])))
  602. {
  603. CURTASK exps[level - 1].nval = TRUE;
  604. }
  605. else
  606. {
  607. CURTASK exps[level - 1].nval = FALSE;
  608. }
  609. break;
  610. }
  611. /* set variable to integer and operation to NUMBER: this must be done
  612. * at the end, since at the beginning it might cause op_islevelstr()
  613. * to return a false error */
  614. CURTASK exps[level - 1].type = NUMBER;
  615. CURTASK exps[level - 1].operation = NUMBER;
  616. /* decrement the stack */
  617. op_pulldown(2);
  618. return TRUE;
  619. }
  620. /***************************************************************
  621. FUNCTION: op_greaterthan()
  622. DESCRIPTION: This function compares two values and
  623. returns an integer value: TRUE if the
  624. left hand value is greater than the right,
  625. and FALSE if it is not.
  626. ***************************************************************/
  627. static int
  628. op_greaterthan(int level, int precision)
  629. {
  630. bwx_DEBUG(__FUNCTION__);
  631. switch (precision)
  632. {
  633. case STRING:
  634. /* both sides of the operation should be numbers for string
  635. * addition; if not, report an error */
  636. if ((op_islevelstr(level - 1) != TRUE)
  637. || (op_islevelstr(level + 1) != TRUE))
  638. {
  639. sprintf(bwb_ebuf, "Type mismatch in string comparison.");
  640. bwb_error(bwb_ebuf);
  641. return FALSE;
  642. }
  643. /* compare the two strings */
  644. if (str_cmp(exp_getsval(&(CURTASK exps[level - 1])),
  645. exp_getsval(&(CURTASK exps[level + 1]))) > 0)
  646. {
  647. CURTASK exps[level - 1].nval = TRUE;
  648. }
  649. else
  650. {
  651. CURTASK exps[level - 1].nval = FALSE;
  652. }
  653. break;
  654. case NUMBER:
  655. if (exp_getnval(&(CURTASK exps[level - 1]))
  656. > exp_getnval(&(CURTASK exps[level + 1])))
  657. {
  658. CURTASK exps[level - 1].nval = TRUE;
  659. }
  660. else
  661. {
  662. CURTASK exps[level - 1].nval = FALSE;
  663. }
  664. break;
  665. }
  666. /* set variable to integer and operation to NUMBER: this must be done
  667. * at the end, since at the beginning it might cause op_islevelstr()
  668. * to return a false error */
  669. CURTASK exps[level - 1].type = NUMBER;
  670. CURTASK exps[level - 1].operation = NUMBER;
  671. /* decrement the stack */
  672. op_pulldown(2);
  673. return TRUE;
  674. }
  675. /***************************************************************
  676. FUNCTION: op_lteq()
  677. DESCRIPTION: This function compares two values and
  678. returns an integer value: TRUE if the
  679. left hand value is less than or equal
  680. to the right, and FALSE if it is not.
  681. ***************************************************************/
  682. static int
  683. op_lteq(int level, int precision)
  684. {
  685. bwx_DEBUG(__FUNCTION__);
  686. switch (precision)
  687. {
  688. case STRING:
  689. /* both sides of the operation should be numbers for string
  690. * addition; if not, report an error */
  691. if ((op_islevelstr(level - 1) != TRUE)
  692. || (op_islevelstr(level + 1) != TRUE))
  693. {
  694. sprintf(bwb_ebuf, "Type mismatch in string comparison.");
  695. bwb_error(bwb_ebuf);
  696. return FALSE;
  697. }
  698. /* compare the two strings */
  699. if (str_cmp(exp_getsval(&(CURTASK exps[level - 1])),
  700. exp_getsval(&(CURTASK exps[level + 1]))) <= 0)
  701. {
  702. CURTASK exps[level - 1].nval = TRUE;
  703. }
  704. else
  705. {
  706. CURTASK exps[level - 1].nval = FALSE;
  707. }
  708. break;
  709. case NUMBER:
  710. if (exp_getnval(&(CURTASK exps[level - 1]))
  711. <= exp_getnval(&(CURTASK exps[level + 1])))
  712. {
  713. CURTASK exps[level - 1].nval = TRUE;
  714. }
  715. else
  716. {
  717. CURTASK exps[level - 1].nval = FALSE;
  718. }
  719. break;
  720. }
  721. /* set variable to integer and operation to NUMBER: this must be done
  722. * at the end, since at the beginning it might cause op_islevelstr()
  723. * to return a false error */
  724. CURTASK exps[level - 1].type = NUMBER;
  725. CURTASK exps[level - 1].operation = NUMBER;
  726. /* decrement the stack */
  727. op_pulldown(2);
  728. return TRUE;
  729. }
  730. /***************************************************************
  731. FUNCTION: op_gteq()
  732. DESCRIPTION: This function compares two values and
  733. returns an integer value: TRUE if the
  734. left hand value is greater than or equal
  735. to the right, and FALSE if it is not.
  736. ***************************************************************/
  737. static int
  738. op_gteq(int level, int precision)
  739. {
  740. bwx_DEBUG(__FUNCTION__);
  741. switch (precision)
  742. {
  743. case STRING:
  744. /* both sides of the operation should be numbers for string
  745. * addition; if not, report an error */
  746. if ((op_islevelstr(level - 1) != TRUE)
  747. || (op_islevelstr(level + 1) != TRUE))
  748. {
  749. sprintf(bwb_ebuf, "Type mismatch in string comparison.");
  750. bwb_error(bwb_ebuf);
  751. return FALSE;
  752. }
  753. /* compare the two strings */
  754. if (str_cmp(exp_getsval(&(CURTASK exps[level - 1])),
  755. exp_getsval(&(CURTASK exps[level + 1]))) >= 0)
  756. {
  757. CURTASK exps[level - 1].nval = TRUE;
  758. }
  759. else
  760. {
  761. CURTASK exps[level - 1].nval = FALSE;
  762. }
  763. break;
  764. case NUMBER:
  765. if (exp_getnval(&(CURTASK exps[level - 1]))
  766. >= exp_getnval(&(CURTASK exps[level + 1])))
  767. {
  768. CURTASK exps[level - 1].nval = TRUE;
  769. }
  770. else
  771. {
  772. CURTASK exps[level - 1].nval = FALSE;
  773. }
  774. break;
  775. }
  776. /* set variable to integer and operation to NUMBER: this must be done
  777. * at the end, since at the beginning it might cause op_islevelstr()
  778. * to return a false error */
  779. CURTASK exps[level - 1].type = NUMBER;
  780. CURTASK exps[level - 1].operation = NUMBER;
  781. /* decrement the stack */
  782. op_pulldown(2);
  783. return TRUE;
  784. }
  785. /***************************************************************
  786. FUNCTION: op_notequal()
  787. DESCRIPTION: This function compares two values and
  788. returns an integer value: TRUE if they
  789. are not the same and FALSE if they are.
  790. ***************************************************************/
  791. static int
  792. op_notequal(int level, int precision)
  793. {
  794. bwx_DEBUG(__FUNCTION__);
  795. switch (precision)
  796. {
  797. case STRING:
  798. /* both sides of the operation should be numbers for string
  799. * addition; if not, report an error */
  800. if ((op_islevelstr(level - 1) != TRUE)
  801. || (op_islevelstr(level + 1) != TRUE))
  802. {
  803. sprintf(bwb_ebuf, "Type mismatch in string comparison.");
  804. bwb_error(bwb_ebuf);
  805. return FALSE;
  806. }
  807. /* compare the two strings */
  808. if (str_cmp(exp_getsval(&(CURTASK exps[level - 1])),
  809. exp_getsval(&(CURTASK exps[level + 1]))) != 0)
  810. {
  811. CURTASK exps[level - 1].nval = TRUE;
  812. }
  813. else
  814. {
  815. CURTASK exps[level - 1].nval = FALSE;
  816. }
  817. break;
  818. case NUMBER:
  819. if (exp_getnval(&(CURTASK exps[level - 1]))
  820. != exp_getnval(&(CURTASK exps[level + 1])))
  821. {
  822. CURTASK exps[level - 1].nval = TRUE;
  823. }
  824. else
  825. {
  826. CURTASK exps[level - 1].nval = FALSE;
  827. }
  828. break;
  829. }
  830. /* set variable to integer and operation to NUMBER: this must be done
  831. * at the end, since at the beginning it might cause op_islevelstr()
  832. * to return a false error */
  833. CURTASK exps[level - 1].type = NUMBER;
  834. CURTASK exps[level - 1].operation = NUMBER;
  835. /* decrement the stack */
  836. op_pulldown(2);
  837. return TRUE;
  838. }
  839. /***************************************************************
  840. FUNCTION: op_modulus()
  841. DESCRIPTION: This function divides the number on
  842. the left by the number on the right
  843. and returns the remainder.
  844. ***************************************************************/
  845. static int
  846. op_modulus(int level, int precision)
  847. {
  848. static double iportion;
  849. bwx_DEBUG(__FUNCTION__);
  850. switch (precision)
  851. {
  852. case STRING:
  853. /* both sides of the operation should be numbers for string
  854. * addition; if not, report an error */
  855. sprintf(bwb_ebuf, "Strings cannot be divided.");
  856. bwb_error(bwb_ebuf);
  857. return FALSE;
  858. break;
  859. case NUMBER:
  860. {
  861. /* N = X MOD Y */
  862. if (exp_getnval(&(CURTASK exps[level + 1]))
  863. == 0)
  864. {
  865. CURTASK exps[level - 1].nval = -1;
  866. op_pulldown(2);
  867. sprintf(bwb_ebuf, "Modulus by 0.");
  868. bwb_error(bwb_ebuf);
  869. return FALSE;
  870. }
  871. CURTASK exps[level].nval
  872. = exp_getnval(&(CURTASK exps[level - 1]))
  873. / exp_getnval(&(CURTASK exps[level + 1]));
  874. modf((double) CURTASK exps[level].nval, &iportion);
  875. CURTASK exps[level - 1].nval
  876. = exp_getnval(&(CURTASK exps[level - 1]))
  877. - (exp_getnval(&(CURTASK exps[level + 1]))
  878. * iportion);
  879. }
  880. break;
  881. }
  882. /* set variable to requested precision */
  883. CURTASK exps[level - 1].type = (char) precision;
  884. CURTASK exps[level - 1].operation = NUMBER;
  885. /* decrement the stack twice */
  886. op_pulldown(2);
  887. return TRUE;
  888. }
  889. /***************************************************************
  890. FUNCTION: op_exponent()
  891. DESCRIPTION: This function finds the exponential value
  892. of a number (on the left) to the power
  893. indicated on the right-hand side.
  894. ***************************************************************/
  895. static int
  896. op_exponent(int level, int precision)
  897. {
  898. bwx_DEBUG(__FUNCTION__);
  899. switch (precision)
  900. {
  901. case STRING:
  902. /* both sides of the operation should be numbers for string
  903. * addition; if not, report an error */
  904. sprintf(bwb_ebuf, "Strings cannot be taken as exponents.");
  905. bwb_error(bwb_ebuf);
  906. return FALSE;
  907. break;
  908. case NUMBER:
  909. if (TRUE)
  910. {
  911. /* N = X ^ Y */
  912. BasicNumberType X;
  913. BasicNumberType Y;
  914. BasicNumberType N;
  915. X = exp_getnval(&(CURTASK exps[level - 1]));
  916. Y = exp_getnval(&(CURTASK exps[level + 1]));
  917. if (X < 0 && Y != (int) Y)
  918. {
  919. /*** FATAL ***/
  920. /* - Evaluation of the operation of
  921. * involution results in a nega- tive number
  922. * being raised to a non-integral power
  923. * (fatal). */
  924. N = 0;
  925. bwb_error("NEGATIVE QUANTITY RAISED TO A NON-INTEGRAL POWER");
  926. return FALSE;
  927. }
  928. else
  929. if (X == 0 && Y < 0)
  930. {
  931. /* - Evaluation of the operation of
  932. * involution results in a zero be- ing
  933. * raised to a negative value (nonfatal, the
  934. * recommended re- covery procedure is to
  935. * supply positive machine infinity and
  936. * continue). */
  937. N = (DBL_MAX);
  938. bwb_Warning_Overflow("*** Arithmetic Overflow ***");
  939. }
  940. else
  941. {
  942. N = pow(X, Y);
  943. }
  944. CURTASK exps[level - 1].nval = N;
  945. }
  946. break;
  947. }
  948. /* set variable to requested precision */
  949. CURTASK exps[level - 1].type = (char) precision;
  950. CURTASK exps[level - 1].operation = NUMBER;
  951. /* decrement the stack twice */
  952. op_pulldown(2);
  953. return TRUE;
  954. }
  955. /***************************************************************
  956. FUNCTION: op_intdiv()
  957. DESCRIPTION: This function divides the number on
  958. the left by the number on the right,
  959. returning the result as an integer.
  960. ***************************************************************/
  961. static int
  962. op_intdiv(int level, int precision)
  963. {
  964. bwx_DEBUG(__FUNCTION__);
  965. switch (precision)
  966. {
  967. case STRING:
  968. /* both sides of the operation should be numbers for string
  969. * addition; if not, report an error */
  970. sprintf(bwb_ebuf, "Strings cannot be divided.");
  971. bwb_error(bwb_ebuf);
  972. return FALSE;
  973. break;
  974. default:
  975. {
  976. /* N = X \ Y */
  977. long X;
  978. long Y;
  979. long N;
  980. X = exp_getival(&(CURTASK exps[level - 1]));
  981. Y = exp_getival(&(CURTASK exps[level + 1]));
  982. if (Y == 0)
  983. {
  984. sprintf(bwb_ebuf, "Integer Divide by 0.");
  985. bwb_error(bwb_ebuf);
  986. return FALSE;
  987. }
  988. N = X / Y;
  989. CURTASK exps[level - 1].nval = N;
  990. }
  991. break;
  992. }
  993. /* set variable to requested precision */
  994. CURTASK exps[level - 1].type = NUMBER;
  995. CURTASK exps[level - 1].operation = NUMBER;
  996. /* decrement the stack twice */
  997. op_pulldown(2);
  998. return TRUE;
  999. }
  1000. /***************************************************************
  1001. FUNCTION: op_or()
  1002. DESCRIPTION: This function compares two integers and
  1003. performs a logical OR on them.
  1004. ***************************************************************/
  1005. static int
  1006. op_or(int level, int precision)
  1007. {
  1008. bwx_DEBUG(__FUNCTION__);
  1009. switch (precision)
  1010. {
  1011. case STRING:
  1012. /* both sides of the operation should be numbers for logical
  1013. * comparison; if not, report an error */
  1014. sprintf(bwb_ebuf, "Strings cannot be compared logically.");
  1015. bwb_error(bwb_ebuf);
  1016. return FALSE;
  1017. break;
  1018. case NUMBER:
  1019. {
  1020. /* N = X OR Y */
  1021. long X;
  1022. long Y;
  1023. long N;
  1024. X = exp_getival(&(CURTASK exps[level - 1]));
  1025. Y = exp_getival(&(CURTASK exps[level + 1]));
  1026. N = X | Y;
  1027. CURTASK exps[level - 1].nval = N;
  1028. }
  1029. break;
  1030. }
  1031. /* set variable type to integer */
  1032. CURTASK exps[level - 1].type = NUMBER;
  1033. CURTASK exps[level - 1].operation = NUMBER;
  1034. /* decrement the stack twice */
  1035. op_pulldown(2);
  1036. return TRUE;
  1037. }
  1038. /***************************************************************
  1039. FUNCTION: op_and()
  1040. DESCRIPTION: This function compares two integers and
  1041. performs a logical AND on them.
  1042. ***************************************************************/
  1043. static int
  1044. op_and(int level, int precision)
  1045. {
  1046. bwx_DEBUG(__FUNCTION__);
  1047. switch (precision)
  1048. {
  1049. case STRING:
  1050. /* both sides of the operation should be numbers for logical
  1051. * comparison; if not, report an error */
  1052. sprintf(bwb_ebuf, "Strings cannot be compared logically.");
  1053. bwb_error(bwb_ebuf);
  1054. return FALSE;
  1055. break;
  1056. case NUMBER:
  1057. {
  1058. /* N = X AND Y */
  1059. long X;
  1060. long Y;
  1061. long N;
  1062. X = exp_getival(&(CURTASK exps[level - 1]));
  1063. Y = exp_getival(&(CURTASK exps[level + 1]));
  1064. N = X & Y;
  1065. CURTASK exps[level - 1].nval = N;
  1066. }
  1067. break;
  1068. }
  1069. /* set variable type to integer */
  1070. CURTASK exps[level - 1].type = NUMBER;
  1071. CURTASK exps[level - 1].operation = NUMBER;
  1072. /* decrement the stack twice */
  1073. op_pulldown(2);
  1074. return TRUE;
  1075. }
  1076. /***************************************************************
  1077. FUNCTION: op_not()
  1078. DESCRIPTION: This function performs a logical NOT on
  1079. the integer to the right.
  1080. ***************************************************************/
  1081. static int
  1082. op_not(int level, int precision)
  1083. {
  1084. bwx_DEBUG(__FUNCTION__);
  1085. switch (precision)
  1086. {
  1087. case STRING:
  1088. /* both sides of the operation should be numbers for logical
  1089. * comparison; if not, report an error */
  1090. sprintf(bwb_ebuf, "Strings cannot be compared logically.");
  1091. bwb_error(bwb_ebuf);
  1092. return FALSE;
  1093. break;
  1094. default:
  1095. {
  1096. /* N = NOT X */
  1097. long X;
  1098. long N;
  1099. X = exp_getival(&(CURTASK exps[level + 1]));
  1100. N = ~X;
  1101. CURTASK exps[level /*- 1*/ ].nval = N;
  1102. }
  1103. break;
  1104. }
  1105. /* set variable type to integer */
  1106. CURTASK exps[level].type = NUMBER;
  1107. CURTASK exps[level].operation = NUMBER;
  1108. /* decrement the stack once */
  1109. op_pulldown(1);
  1110. return TRUE;
  1111. }
  1112. /***************************************************************
  1113. FUNCTION: op_xor()
  1114. DESCRIPTION: This function compares two integers and
  1115. performs a logical XOR on them.
  1116. ***************************************************************/
  1117. static int
  1118. op_xor(int level, int precision)
  1119. {
  1120. bwx_DEBUG(__FUNCTION__);
  1121. switch (precision)
  1122. {
  1123. case STRING:
  1124. /* both sides of the operation should be numbers for logical
  1125. * comparison; if not, report an error */
  1126. sprintf(bwb_ebuf, "Strings cannot be compared logically.");
  1127. bwb_error(bwb_ebuf);
  1128. return FALSE;
  1129. break;
  1130. case NUMBER:
  1131. {
  1132. /* N = X XOR Y */
  1133. long X;
  1134. long Y;
  1135. long N;
  1136. X = exp_getival(&(CURTASK exps[level - 1]));
  1137. Y = exp_getival(&(CURTASK exps[level + 1]));
  1138. N = X ^ Y;
  1139. CURTASK exps[level - 1].nval = N;
  1140. }
  1141. break;
  1142. }
  1143. /* set variable type to integer */
  1144. CURTASK exps[level - 1].type = NUMBER;
  1145. CURTASK exps[level - 1].operation = NUMBER;
  1146. /* decrement the stack twice */
  1147. op_pulldown(2);
  1148. return TRUE;
  1149. }
  1150. /***************************************************************
  1151. FUNCTION: op_eqv()
  1152. DESCRIPTION: This function compares two integers and
  1153. performs a logical EQV on them.
  1154. ***************************************************************/
  1155. static int
  1156. op_eqv(int level, int precision)
  1157. {
  1158. bwx_DEBUG(__FUNCTION__);
  1159. switch (precision)
  1160. {
  1161. case STRING:
  1162. /* both sides of the operation should be numbers for logical
  1163. * comparison; if not, report an error */
  1164. sprintf(bwb_ebuf, "Strings cannot be compared logically.");
  1165. bwb_error(bwb_ebuf);
  1166. return FALSE;
  1167. break;
  1168. case NUMBER:
  1169. {
  1170. /* N = X EQV Y = NOT ( X XOR Y ) */
  1171. long X;
  1172. long Y;
  1173. long N;
  1174. X = exp_getival(&(CURTASK exps[level - 1]));
  1175. Y = exp_getival(&(CURTASK exps[level + 1]));
  1176. N = ~(X ^ Y);
  1177. CURTASK exps[level - 1].nval = N;
  1178. }
  1179. break;
  1180. }
  1181. /* set variable type to integer */
  1182. CURTASK exps[level - 1].type = NUMBER;
  1183. CURTASK exps[level - 1].operation = NUMBER;
  1184. /* decrement the stack twice */
  1185. op_pulldown(2);
  1186. return TRUE;
  1187. }
  1188. /***************************************************************
  1189. FUNCTION: op_imp()
  1190. DESCRIPTION: This function compares two integers and
  1191. performs a logical IMP on them.
  1192. ***************************************************************/
  1193. static int
  1194. op_imp(int level, int precision)
  1195. {
  1196. bwx_DEBUG(__FUNCTION__);
  1197. switch (precision)
  1198. {
  1199. case STRING:
  1200. /* both sides of the operation should be numbers for logical
  1201. * comparison; if not, report an error */
  1202. sprintf(bwb_ebuf, "Strings cannot be compared logically.");
  1203. bwb_error(bwb_ebuf);
  1204. return FALSE;
  1205. break;
  1206. case NUMBER:
  1207. {
  1208. /* N = X IMP Y = (X AND Y) OR (NOT X) */
  1209. long X;
  1210. long Y;
  1211. long N;
  1212. X = exp_getival(&(CURTASK exps[level - 1]));
  1213. Y = exp_getival(&(CURTASK exps[level + 1]));
  1214. N = (X & Y) | (~X);
  1215. CURTASK exps[level - 1].nval = N;
  1216. }
  1217. break;
  1218. }
  1219. /* set variable type to integer */
  1220. CURTASK exps[level - 1].type = NUMBER;
  1221. CURTASK exps[level - 1].operation = NUMBER;
  1222. /* decrement the stack twice */
  1223. op_pulldown(2);
  1224. return TRUE;
  1225. }
  1226. /***************************************************************
  1227. FUNCTION: op_negation()
  1228. DESCRIPTION: This function performs a negation on the
  1229. element to the right.
  1230. Added by JBV 10/95
  1231. ***************************************************************/
  1232. static int
  1233. op_negation(int level, int precision)
  1234. {
  1235. bwx_DEBUG(__FUNCTION__);
  1236. switch (precision)
  1237. {
  1238. case STRING:
  1239. /* both sides of the operation should be numbers for logical
  1240. * comparison; if not, report an error */
  1241. sprintf(bwb_ebuf, "Strings cannot be compared logically.");
  1242. bwb_error(bwb_ebuf);
  1243. return FALSE;
  1244. break;
  1245. default:
  1246. CURTASK exps[level].nval =
  1247. -(exp_getnval(&(CURTASK exps[level + 1])));
  1248. break;
  1249. }
  1250. /* set variable type to requested precision (JBV) */
  1251. CURTASK exps[level].type = (char) precision;
  1252. CURTASK exps[level].operation = NUMBER;
  1253. /* decrement the stack once */
  1254. op_pulldown(1);
  1255. return TRUE;
  1256. }
  1257. static int
  1258. op_posation(int level, int precision)
  1259. {
  1260. bwx_DEBUG(__FUNCTION__);
  1261. switch (precision)
  1262. {
  1263. case STRING:
  1264. /* both sides of the operation should be numbers for logical
  1265. * comparison; if not, report an error */
  1266. sprintf(bwb_ebuf, "Strings cannot be compared logically.");
  1267. bwb_error(bwb_ebuf);
  1268. return FALSE;
  1269. break;
  1270. default:
  1271. CURTASK exps[level].nval =
  1272. (exp_getnval(&(CURTASK exps[level + 1])));
  1273. break;
  1274. }
  1275. /* set variable type to requested precision (JBV) */
  1276. CURTASK exps[level].type = (char) precision;
  1277. CURTASK exps[level].operation = NUMBER;
  1278. /* decrement the stack once */
  1279. op_pulldown(1);
  1280. return TRUE;
  1281. }
  1282. /***************************************************************
  1283. FUNCTION: op_islevelstr()
  1284. DESCRIPTION: This function determines whether the
  1285. operation at a specified level involves a
  1286. string constant or variable.
  1287. ***************************************************************/
  1288. static int
  1289. op_islevelstr(int level)
  1290. {
  1291. bwx_DEBUG(__FUNCTION__);
  1292. /* first see if the level holds a string constant */
  1293. if (CURTASK exps[level].operation == CONST_STRING)
  1294. {
  1295. return TRUE;
  1296. }
  1297. /* see if the level holds a string variable */
  1298. if (CURTASK exps[level].operation == VARIABLE)
  1299. {
  1300. if (CURTASK exps[level].xvar->type == STRING)
  1301. {
  1302. return TRUE;
  1303. }
  1304. }
  1305. /* test has failed, return FALSE */
  1306. return FALSE;
  1307. }
  1308. /***************************************************************
  1309. FUNCTION: op_getprecision()
  1310. DESCRIPTION: This function finds the precision for
  1311. an operation by comparing the precision
  1312. at this level and that two levels below.
  1313. ***************************************************************/
  1314. static int
  1315. op_getprecision(int level)
  1316. {
  1317. bwx_DEBUG(__FUNCTION__);
  1318. /* first test for string value */
  1319. if ((CURTASK exps[level + 1].type == STRING)
  1320. || (CURTASK exps[level - 1].type == STRING))
  1321. {
  1322. return STRING;
  1323. }
  1324. /* Both are numbers, so we should be able to find a suitable
  1325. * precision level by starting with the top and moving down; check
  1326. * first for double precision */
  1327. else
  1328. {
  1329. return NUMBER;
  1330. }
  1331. }
  1332. /***************************************************************
  1333. FUNCTION: op_pulldown()
  1334. DESCRIPTION: This function pulls the expression stack
  1335. down a specified number of levels, decrementing
  1336. the expression stack counter (bycalling dec_esc())
  1337. and decrementing the current "level" of operation
  1338. processing.
  1339. ***************************************************************/
  1340. static int
  1341. op_pulldown(int how_far)
  1342. {
  1343. int level;
  1344. register int c;
  1345. bwx_DEBUG(__FUNCTION__);
  1346. /* first pull down the actual variables themselves */
  1347. level = op_level + (2 - how_far);
  1348. while (CURTASK expsc >= (level + how_far))
  1349. {
  1350. /*------------------------------------------------------*/
  1351. /* But before memcpy, deallocate sbuffer for level, and */
  1352. /* afterwards, set sbuffer for level + how_far to NULL! */
  1353. /* Else konfusion reigns the next time around... (JBV) */
  1354. /*------------------------------------------------------*/
  1355. if (CURTASK exps[level].sval.sbuffer != NULL) /* JBV */
  1356. FREE(CURTASK exps[level].sval.sbuffer, "op_pulldown");
  1357. memcpy(&CURTASK exps[level], &CURTASK exps[level + how_far],
  1358. (size_t) (sizeof(struct exp_ese)));
  1359. CURTASK exps[level + how_far].sval.sbuffer = NULL; /* JBV */
  1360. ++level;
  1361. }
  1362. /* decrement the expression stack counter */
  1363. for (c = 0; c < how_far; ++c)
  1364. {
  1365. if (dec_esc() == TRUE)
  1366. {
  1367. --op_level;
  1368. }
  1369. else
  1370. {
  1371. return FALSE;
  1372. }
  1373. }
  1374. return TRUE;
  1375. }
  1376. /* EOF */