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.
 
 
 
 
 
 

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