home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / PRG / bwbasic-2.10.sit / bwbasic-2.10 / bwb_ops.c < prev    next >
Text File  |  1993-11-09  |  47KB  |  1,929 lines

  1. /****************************************************************
  2.  
  3.         bwb_ops.c       Expression Parsing Operations
  4.                         for Bywater BASIC Interpreter
  5.  
  6.                         Copyright (c) 1993, Ted A. Campbell
  7.                         Bywater Software
  8.  
  9.                         email: tcamp@delphi.com
  10.  
  11.         Copyright and Permissions Information:
  12.  
  13.         All U.S. and international rights are claimed by the author,
  14.         Ted A. Campbell.
  15.  
  16.     This software is released under the terms of the GNU General
  17.     Public License (GPL), which is distributed with this software
  18.     in the file "COPYING".  The GPL specifies the terms under
  19.     which users may copy and use the software in this distribution.
  20.  
  21.     A separate license is available for commercial distribution,
  22.     for information on which you should contact the author.
  23.  
  24. ****************************************************************/
  25.  
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #include <math.h>
  29.  
  30. #include "bwbasic.h"
  31. #include "bwb_mes.h"
  32.  
  33. /* declarations for functions visible in this file only */
  34.  
  35. #if ANSI_C
  36. static int op_oplevel( int level );
  37. static int op_add( int level, int precision );
  38. static int op_subtract( int level, int precision );
  39. static int op_multiply( int level, int precision );
  40. static int op_divide( int level, int precision );
  41. static int op_assign( int level, int precision );
  42. static int op_equals( int level, int precision );
  43. static int op_lessthan( int level, int precision );
  44. static int op_greaterthan( int level, int precision );
  45. static int op_lteq( int level, int precision );
  46. static int op_gteq( int level, int precision );
  47. static int op_notequal( int level, int precision );
  48. static int op_modulus( int level, int precision );
  49. static int op_exponent( int level, int precision );
  50. static int op_intdiv( int level, int precision );
  51. static int op_or( int level, int precision );
  52. static int op_and( int level, int precision );
  53. static int op_not( int level, int precision );
  54. static int op_xor( int level, int precision );
  55. static int op_islevelstr( int level );
  56. static int op_getprecision( int level );
  57. static int op_isoperator( int operation );
  58. static int op_pulldown( int how_far );
  59. #else
  60. static int op_oplevel();
  61. static int op_add();
  62. static int op_subtract();
  63. static int op_multiply();
  64. static int op_divide();
  65. static int op_assign();
  66. static int op_equals();
  67. static int op_lessthan();
  68. static int op_greaterthan();
  69. static int op_lteq();
  70. static int op_gteq();
  71. static int op_notequal();
  72. static int op_modulus();
  73. static int op_exponent();
  74. static int op_intdiv();
  75. static int op_or();
  76. static int op_and();
  77. static int op_not();
  78. static int op_xor();
  79. static int op_islevelstr();
  80. static int op_getprecision();
  81. static int op_isoperator();
  82. static int op_pulldown();
  83. #endif                /* ANSI_C for prototypes */
  84.  
  85. static int op_level;
  86.  
  87. /***************************************************************
  88.  
  89.     FUNCTION:       exp_operation()
  90.  
  91.     DESCRIPTION:    This function performs whatever operations
  92.             are necessary at the end of function bwb_exp()
  93.             (i.e., the end of the parsing of an expression;
  94.             see file bwb_exp.c).
  95.  
  96. ***************************************************************/
  97.  
  98. #if ANSI_C
  99. int
  100. exp_operation( int entry_level )
  101. #else
  102. int
  103. exp_operation( entry_level )
  104.    int entry_level;
  105. #endif
  106.    {
  107.    register int precedence;
  108.    int operator;
  109.  
  110. #if INTENSIVE_DEBUG
  111.    sprintf( bwb_ebuf, "in exp_operation(): entered function." );
  112.    bwb_debug( bwb_ebuf );
  113. #endif
  114.  
  115.    /* cycle through all levels of precedence and perform required
  116.       operations */
  117.  
  118.    for ( precedence = 0; precedence <= MAX_PRECEDENCE; ++precedence )
  119.       {
  120.  
  121.       /* Operation loop: cycle through every level above entry level
  122.          and perform required operations as needed */
  123.  
  124.       op_level = entry_level + 1;
  125.       while( ( op_level < CURTASK expsc )
  126.          && ( op_isoperator( CURTASK exps[ op_level ].operation ) == FALSE ))
  127.          {
  128.          ++op_level;
  129.          }
  130.  
  131.       while ( ( op_level > entry_level ) && ( op_level < CURTASK expsc ) )
  132.          {
  133.  
  134.          /* see if the operation at this level is an operator with the
  135.             appropriate precedence level by running through the table
  136.             of operators */
  137.  
  138.          for ( operator = 0; operator < N_OPERATORS; ++operator )
  139.             {
  140.  
  141.             if ( exp_ops[ operator ].operation == CURTASK exps[ op_level ].operation )
  142.                {
  143.  
  144.                /* check for appropriate level of precedence */
  145.  
  146.                if ( exp_ops[ operator ].precedence == precedence )
  147.                   {
  148.  
  149. #if INTENSIVE_DEBUG
  150.                   sprintf( bwb_ebuf, "in exp_operation(): level <%d> operation <%d>",
  151.                      op_level, CURTASK exps[ op_level ].operation );
  152.                   bwb_debug( bwb_ebuf );
  153. #endif
  154.  
  155.                   op_oplevel( op_level );     /* perform the operation */
  156.  
  157.                   }
  158.                }
  159.             }
  160.  
  161.          /* advance level if appropriate; one must check, however, since
  162.             the op_oplevel() function may have decremented CURTASK expsc */
  163.  
  164.          if ( op_level < CURTASK expsc )
  165.             {
  166.             ++op_level;
  167.  
  168. #if INTENSIVE_DEBUG
  169.             sprintf( bwb_ebuf, "in exp_operation() first increment op_level to <%d>",
  170.                op_level );
  171.             bwb_debug( bwb_ebuf );
  172. #endif
  173.  
  174.             while ( ( op_isoperator( CURTASK exps [ op_level ].operation ) == FALSE )
  175.                && ( op_level < CURTASK expsc ) )
  176.                {
  177.                ++op_level;
  178.  
  179. #if INTENSIVE_DEBUG
  180.                sprintf( bwb_ebuf, "in exp_operation() further increment op_level to <%d>",
  181.                   op_level );
  182.                bwb_debug( bwb_ebuf );
  183. #endif
  184.  
  185.                }
  186.             }                           /* end of increment of op_level */
  187.  
  188.          }                              /* end of for loop for stack levels */
  189.  
  190.       }                                 /* end of for loop for precedence levels */
  191.  
  192.    return TRUE;
  193.  
  194.    }                                    /* end of function exp_operation() */
  195.  
  196.  
  197. /***************************************************************
  198.  
  199.     FUNCTION:       op_oplevel()
  200.  
  201.     DESCRIPTION:    This function performs a specific operation
  202.             at a specific level as the expression parser
  203.             resolves its arguments.
  204.  
  205. ***************************************************************/
  206.  
  207. #if ANSI_C
  208. static int
  209. op_oplevel( int level )
  210. #else
  211. static int
  212. op_oplevel( level )
  213.    int level;
  214. #endif
  215.    {
  216.    int precision;
  217.  
  218.    /* set the precision */
  219.  
  220.    if ( ( precision = op_getprecision( level ) ) == OP_ERROR )
  221.       {
  222. #if PROG_ERRORS
  223.       sprintf( bwb_ebuf, "exp_operation(): failed to set precision." );
  224.       bwb_error( bwb_ebuf );
  225. #else
  226.       bwb_error( err_mismatch );            /*** ??? ***/
  227. #endif
  228.       op_pulldown( 2 );
  229.       }
  230.  
  231.    /* precision is set correctly */
  232.  
  233.    else
  234.       {
  235. #if INTENSIVE_DEBUG
  236.       sprintf( bwb_ebuf, "in op_oplevel(): level <%d>, precision <%c>",
  237.          level, precision );
  238.       bwb_debug( bwb_ebuf );
  239. #endif
  240.  
  241.       switch ( CURTASK exps[ level ].operation )
  242.          {
  243.          case OP_ADD:
  244.             op_add( level, precision );
  245.             break;
  246.  
  247.          case OP_SUBTRACT:
  248.             op_subtract( level, precision );
  249.             break;
  250.  
  251.          case OP_MULTIPLY:
  252.             op_multiply( level, precision );
  253.             break;
  254.  
  255.          case OP_DIVIDE:
  256.             op_divide( level, precision );
  257.             break;
  258.  
  259.          case OP_ASSIGN:
  260.             op_assign( level, precision );
  261.             break;
  262.  
  263.          case OP_EQUALS:
  264.             op_equals( level, precision );
  265.             break;
  266.  
  267.          case OP_LESSTHAN:
  268.             op_lessthan( level, precision );
  269.             break;
  270.  
  271.          case OP_GREATERTHAN:
  272.             op_greaterthan( level, precision );
  273.             break;
  274.  
  275.          case OP_LTEQ:
  276.             op_lteq( level, precision );
  277.             break;
  278.  
  279.          case OP_GTEQ:
  280.             op_gteq( level, precision );
  281.             break;
  282.  
  283.          case OP_NOTEQUAL:
  284.             op_notequal( level, precision );
  285.             break;
  286.  
  287.          case OP_MODULUS:
  288.             op_modulus( level, precision );
  289.             break;
  290.  
  291.          case OP_INTDIVISION:
  292.             op_intdiv( level, precision );
  293.             break;
  294.  
  295.          case OP_OR:
  296.             op_or( level, precision );
  297.             break;
  298.  
  299.          case OP_AND:
  300.             op_and( level, precision );
  301.             break;
  302.  
  303.          case OP_NOT:
  304.             op_not( level, precision );
  305.             break;
  306.  
  307.          case OP_XOR:
  308.             op_xor( level, precision );
  309.             break;
  310.  
  311.          case OP_EXPONENT:
  312.             op_exponent( level, precision );
  313.             break;
  314.  
  315.          default:
  316. #if PROG_ERRORS
  317.             sprintf( bwb_ebuf, "PROGRAMMING ERROR: operator <%d> not (yet) supported.", CURTASK exps[ level ].operation );
  318.             op_pulldown( 2 );
  319.             bwb_error( bwb_ebuf );
  320. #else
  321.             bwb_error( err_syntax );
  322. #endif
  323.             break;
  324.          }                              /* end of case statement for operators */
  325.       }                                 /* end of else statement, precision set */
  326.  
  327.    return TRUE;
  328.  
  329.    }                                    /* end of function op_oplevel() */
  330.  
  331. /***************************************************************
  332.  
  333.     FUNCTION:       op_isoperator()
  334.  
  335.     DESCRIPTION:    This function detects whether its argument
  336.             is an operator.
  337.  
  338. ***************************************************************/
  339.  
  340. #if ANSI_C
  341. static int
  342. op_isoperator( int operation )
  343. #else
  344. static int
  345. op_isoperator( operation )
  346.    int operation;
  347. #endif
  348.    {
  349.    register int c;
  350.  
  351.    for( c = 0; c < N_OPERATORS; ++c )
  352.       {
  353.       if ( operation == exp_ops[ c ].operation )
  354.          {
  355.  
  356. #if INTENSIVE_DEBUG
  357.          sprintf( bwb_ebuf, "in op_isoperator(): found match <%s>",
  358.             exp_ops[ c ].symbol );
  359.          bwb_debug( bwb_ebuf );
  360. #endif
  361.  
  362.          return TRUE;
  363.          }
  364.       }
  365.  
  366.    /* test failed; return FALSE */
  367.  
  368. #if INTENSIVE_DEBUG
  369.    sprintf( bwb_ebuf, "in op_isoperator(): no match found for operation <%d>",
  370.       operation );
  371.    bwb_debug( bwb_ebuf );
  372. #endif
  373.  
  374.    return FALSE;
  375.  
  376.    }
  377.  
  378. /***************************************************************
  379.  
  380.         FUNCTION:       op_add()
  381.  
  382.         DESCRIPTION:      This function adds two numbers or
  383.                 concatenates two strings.
  384.  
  385. ***************************************************************/
  386.  
  387. #if ANSI_C
  388. static int
  389. op_add( int level, int precision )
  390. #else
  391. static int
  392. op_add( level, precision )
  393.    int level;
  394.    int precision;
  395. #endif
  396.    {
  397.    int error_condition;
  398.  
  399.    error_condition = FALSE;
  400.  
  401.    switch( precision )
  402.       {
  403.       case STRING:
  404.  
  405.          /* both sides of the operation should be strings for
  406.             string addition; if not, report an error */
  407.  
  408.          if (  ( op_islevelstr( level - 1 ) != TRUE )
  409.             || ( op_islevelstr( level + 1 ) != TRUE ) )
  410.             {
  411. #if PROG_ERRORS
  412.             sprintf( bwb_ebuf, "in op_add(): Type mismatch in string addition." );
  413.             bwb_error( bwb_ebuf );
  414. #else
  415.             bwb_error( err_mismatch );
  416. #endif
  417.             error_condition = TRUE;
  418.             }
  419.  
  420.          /* concatenate the two strings */
  421.  
  422.          if ( error_condition == FALSE )
  423.             {
  424.  
  425. #if INTENSIVE_DEBUG
  426.             sprintf( bwb_ebuf, "in op_add(): try exp_getsval(), level <%d> op <%d> type <%c>:",
  427.                level - 1, CURTASK exps[ level - 1 ].operation, CURTASK exps[ level - 1 ].type );
  428.             bwb_debug( bwb_ebuf );
  429.             exp_getsval( &( CURTASK exps[ level - 1 ] ));
  430.             sprintf( bwb_ebuf, "in op_add(): try exp_getsval(), level <%d> op <%d> type <%c>:",
  431.                level + 1, CURTASK exps[ level + 1 ].operation, CURTASK exps[ level + 1 ].type );
  432.             bwb_debug( bwb_ebuf );
  433.             exp_getsval( &( CURTASK exps[ level + 1 ] ));
  434.             sprintf( bwb_ebuf, "in op_add(): string addition, exp_getsval()s completed" );
  435.             bwb_debug( bwb_ebuf );
  436. #endif
  437.  
  438.             str_cat( exp_getsval( &( CURTASK exps[ level - 1 ] ) ), 
  439.                exp_getsval( &( CURTASK exps[ level + 1 ] ) ) );
  440.  
  441. #if INTENSIVE_DEBUG
  442.             sprintf( bwb_ebuf, "in op_add(): str_cat() returns <%d>-byte string to level <%d>",
  443.                exp_getsval( &( CURTASK exps[ level - 1 ] ) )->length, level - 1 );
  444.             bwb_debug( bwb_ebuf );
  445. #endif
  446.             }
  447.  
  448.          break;
  449.  
  450.       case NUMBER:
  451.          CURTASK exps[ level - 1 ].nval
  452.             = exp_getnval( &( CURTASK exps[ level - 1 ] ))
  453.             + exp_getnval( &( CURTASK exps[ level + 1 ] ));
  454.          CURTASK exps[ level - 1 ].operation = NUMBER;
  455.          break;
  456.  
  457.       }
  458.  
  459.    /* set variable to requested precision */
  460.  
  461.    CURTASK exps[ level - 1 ].type = (char) precision;
  462.  
  463. #if INTENSIVE_DEBUG
  464.    sprintf( bwb_ebuf, "in op_add() returns with operation <%d> type <%c>",
  465.       CURTASK exps[ level - 1 ].operation, CURTASK exps[ level - 1 ].type );
  466.    bwb_debug( bwb_ebuf );
  467. #endif
  468.  
  469.    /* decrement the stack twice */
  470.  
  471.    op_pulldown( 2 );
  472.  
  473.    return TRUE;
  474.  
  475.    }
  476.  
  477. /***************************************************************
  478.  
  479.     FUNCTION:       op_subtract()
  480.  
  481.     DESCRIPTION:    This function subtracts the number on
  482.             the left from the number on the right.
  483.  
  484. ***************************************************************/
  485.  
  486. #if ANSI_C
  487. static int
  488. op_subtract( int level, int precision )
  489. #else
  490. static int
  491. op_subtract( level, precision )
  492.    int level;
  493.    int precision;
  494. #endif
  495.    {
  496.  
  497.    switch( precision )
  498.       {
  499.       case STRING:
  500.  
  501.          /* both sides of the operation should be numbers for
  502.             string addition; if not, report an error */
  503.  
  504. #if PROG_ERRORS
  505.          sprintf( bwb_ebuf, "Strings cannot be subtracted." );
  506.          bwb_error( bwb_ebuf );
  507. #else
  508.          bwb_error( err_mismatch );
  509. #endif
  510.  
  511.          break;
  512.  
  513.       case NUMBER:
  514.          CURTASK exps[ level - 1 ].nval
  515.             = exp_getnval( &( CURTASK exps[ level - 1 ] ))
  516.             - exp_getnval( &( CURTASK exps[ level + 1 ] ));
  517.          break;
  518.  
  519.       }
  520.  
  521.    /* set variable to requested precision */
  522.  
  523.    CURTASK exps[ level - 1 ].type = (char) precision;
  524.    CURTASK exps[ level - 1 ].operation = NUMBER;
  525.  
  526.    /* decrement the stack twice */
  527.  
  528.    op_pulldown( 2 );
  529.  
  530.    return TRUE;
  531.  
  532.    }
  533.  
  534. /***************************************************************
  535.  
  536.     FUNCTION:       op_multiply()
  537.  
  538.     DESCRIPTION:    This function multiplies the number on
  539.             the left by the number on the right.
  540.  
  541. ***************************************************************/
  542.  
  543. #if ANSI_C
  544. static int
  545. op_multiply( int level, int precision )
  546. #else
  547. static int
  548. op_multiply( level, precision )
  549.    int level;
  550.    int precision;
  551. #endif
  552.    {
  553.  
  554.    switch( precision )
  555.       {
  556.       case STRING:
  557.  
  558.          /* both sides of the operation should be numbers for
  559.             string addition; if not, report an error */
  560.  
  561. #if PROG_ERRORS
  562.          sprintf( bwb_ebuf, "Strings cannot be multiplied." );
  563.          bwb_error( bwb_ebuf );
  564. #else
  565.          bwb_error( err_mismatch );
  566. #endif
  567.  
  568.          break;
  569.  
  570.       case NUMBER:
  571.          CURTASK exps[ level - 1 ].nval
  572.             = exp_getnval( &( CURTASK exps[ level - 1 ] ))
  573.             * exp_getnval( &( CURTASK exps[ level + 1 ] ));
  574.          break;
  575.  
  576.       }
  577.  
  578.    /* set variable to requested precision */
  579.  
  580.    CURTASK exps[ level - 1 ].type = (char) precision;
  581.    CURTASK exps[ level - 1 ].operation = NUMBER;
  582.  
  583.    /* decrement the stack twice */
  584.  
  585.    op_pulldown( 2 );
  586.  
  587.    return TRUE;
  588.  
  589.    }
  590.  
  591. /***************************************************************
  592.  
  593.     FUNCTION:       op_divide()
  594.  
  595.     DESCRIPTION:    This function divides the number on
  596.             the left by the number on the right.
  597.  
  598. ***************************************************************/
  599.  
  600. #if ANSI_C
  601. static int
  602. op_divide( int level, int precision )
  603. #else
  604. static int
  605. op_divide( level, precision )
  606.    int level;
  607.    int precision;
  608. #endif
  609.    {
  610.  
  611.    switch( precision )
  612.       {
  613.       case STRING:
  614.  
  615.          /* both sides of the operation should be numbers for
  616.             division; if not, report an error */
  617.  
  618. #if PROG_ERRORS
  619.          sprintf( bwb_ebuf, "Strings cannot be divided." );
  620.          bwb_error( bwb_ebuf );
  621. #else
  622.          bwb_error( err_mismatch );
  623. #endif
  624.  
  625.          break;
  626.  
  627.       case NUMBER:
  628.          if ( exp_getnval( &( CURTASK exps[ level + 1 ] ))
  629.             == (bnumber) 0 )
  630.             {
  631.             CURTASK exps[ level - 1 ].nval = (bnumber) -1.0;
  632.             op_pulldown( 2 );
  633. #if PROG_ERRORS
  634.             sprintf( bwb_ebuf, "Divide by 0." );
  635.             bwb_error( bwb_ebuf );
  636. #else
  637.             bwb_error( err_dbz );
  638. #endif
  639.             return FALSE;
  640.             }
  641.          CURTASK exps[ level - 1 ].nval
  642.             = exp_getnval( &( CURTASK exps[ level - 1 ] ))
  643.             / exp_getnval( &( CURTASK exps[ level + 1 ] ));
  644.          break;
  645.       }
  646.  
  647.    /* set variable to requested precision */
  648.  
  649.    CURTASK exps[ level - 1 ].type = (char) precision;
  650.    CURTASK exps[ level - 1 ].operation = NUMBER;
  651.  
  652.    /* decrement the stack twice */
  653.  
  654.    op_pulldown( 2 );
  655.  
  656.    return TRUE;
  657.  
  658.    }
  659.  
  660. /***************************************************************
  661.  
  662.     FUNCTION:       op_assign()
  663.  
  664.     DESCRIPTION:    This function assigns the value in the
  665.             right hand side to the variable in the
  666.             left hand side.
  667.  
  668. ***************************************************************/
  669.  
  670. #if ANSI_C
  671. static int
  672. op_assign( int level, int precision )
  673. #else
  674. static int
  675. op_assign( level, precision )
  676.    int level;
  677.    int precision;
  678. #endif
  679.    {
  680.  
  681.    /* Make sure the position one level below is a variable */
  682.  
  683.    if ( CURTASK exps[ level - 1 ].operation != VARIABLE )
  684.       {
  685.       op_pulldown( 2 );
  686. #if PROG_ERRORS
  687.       sprintf( bwb_ebuf, "in op_assign(): Assignment must be to variable: level -1 <%d> op <%d>",
  688.          level - 1, CURTASK exps[ level - 1 ].operation );
  689.       bwb_error( bwb_ebuf );
  690. #else
  691.       bwb_error( err_syntax );
  692. #endif
  693.       return FALSE;
  694.       }
  695.  
  696. #if INTENSIVE_DEBUG
  697.    sprintf( bwb_ebuf, "in op_assign(): entered function level <%d>",
  698.       level );
  699.    bwb_debug( bwb_ebuf );
  700. #endif
  701.  
  702.   /* if the assignment is numerical, then the precision should be set
  703.      to that of the variable on the left-hand side of the assignment */
  704.  
  705.    if ( precision != STRING )
  706.       {
  707.       precision = (int) CURTASK exps[ level - 1 ].type;
  708.       }
  709.  
  710.    switch( precision )
  711.       {
  712.       case STRING:
  713.  
  714. #if INTENSIVE_DEBUG
  715.          sprintf( bwb_ebuf, "in op_assign(): try exp_getsval(), level <%d> op <%d> type <%c>:",
  716.             level - 1, CURTASK exps[ level - 1 ].operation, CURTASK exps[ level - 1 ].type );
  717.          bwb_debug( bwb_ebuf );
  718.          exp_getsval( &( CURTASK exps[ level - 1 ] ));
  719.          sprintf( bwb_ebuf, "in op_assign(): try exp_getsval(), level <%d> op <%d> type <%c>:",
  720.             level + 1, CURTASK exps[ level + 1 ].operation, CURTASK exps[ level + 1 ].type );
  721.          bwb_debug( bwb_ebuf );
  722.          exp_getsval( &( CURTASK exps[ level + 1 ] ));
  723.          sprintf( bwb_ebuf, "in op_assign(): string addition, exp_getsval()s completed" );
  724.          bwb_debug( bwb_ebuf );
  725. #endif
  726.  
  727.          str_btob( exp_getsval( &( CURTASK exps[ level - 1 ] )),
  728.                    exp_getsval( &( CURTASK exps[ level + 1 ] )) );
  729.          break;
  730.  
  731.       case NUMBER:
  732.          * var_findnval( CURTASK exps[ level - 1 ].xvar, 
  733.             CURTASK exps[ level - 1 ].array_pos ) =
  734.             CURTASK exps[ level - 1 ].nval = 
  735.             exp_getnval( &( CURTASK exps[ level + 1 ] ) );
  736.          break;
  737.  
  738.       default:
  739. #if PROG_ERRORS
  740.          sprintf( bwb_ebuf, "in op_assign(): Variable before assignment operator has unidentified type." );
  741.          bwb_error( bwb_ebuf );
  742. #else
  743.          bwb_error( err_mismatch );
  744. #endif
  745.          return FALSE;
  746.  
  747.       }
  748.  
  749.    /* set variable to requested precision */
  750.  
  751.    CURTASK exps[ level - 1 ].type = (char) precision;
  752.  
  753.    /* decrement the stack twice */
  754.  
  755.    op_pulldown( 2 );
  756.  
  757.    return TRUE;
  758.  
  759.    }
  760.  
  761. /***************************************************************
  762.  
  763.     FUNCTION:       op_equals()
  764.  
  765.     DESCRIPTION:    This function compares two values and
  766.             returns an integer value: TRUE if they are
  767.             the same and FALSE if they are not.
  768.  
  769. ***************************************************************/
  770.  
  771. #if ANSI_C
  772. static int
  773. op_equals( int level, int precision )
  774. #else
  775. static int
  776. op_equals( level, precision )
  777.    int level;
  778.    int precision;
  779. #endif
  780.    {
  781.    int error_condition;
  782.    static bstring b;
  783.    bstring *bp;
  784.  
  785.    error_condition = FALSE;
  786.    b.rab = FALSE;
  787.  
  788.    switch( precision )
  789.       {
  790.       case STRING:
  791.  
  792.          /* both sides of the operation should be strings for
  793.             string addition; if not, report an error */
  794.  
  795.          if (  ( op_islevelstr( level - 1 ) != TRUE )
  796.             || ( op_islevelstr( level + 1 ) != TRUE ) )
  797.             {
  798. #if PROG_ERRORS
  799.             sprintf( bwb_ebuf, "in op_equals(): Type mismatch in string comparison." );
  800.             bwb_error( bwb_ebuf );
  801. #else
  802.             bwb_error( err_mismatch );
  803. #endif
  804.             error_condition = TRUE;
  805.             }
  806.  
  807.          /* compare the two strings */
  808.  
  809.          if ( error_condition == FALSE )
  810.             {
  811.             bp = exp_getsval( &( CURTASK exps[ level - 1 ] ));
  812. #if OLDWAY
  813.         b.length = bp->length;
  814.         b.sbuffer = bp->sbuffer;
  815. #endif
  816.         str_btob( &b, bp );
  817.  
  818.             if ( str_cmp( &b,
  819.                exp_getsval( &( CURTASK exps[ level + 1 ] )) ) == 0 )
  820.                {
  821.                CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  822.                }
  823.             else
  824.                {
  825.                CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  826.                }
  827.             }
  828.          break;
  829.  
  830.       case NUMBER:
  831.          if ( exp_getnval( &( CURTASK exps[ level - 1 ] ))
  832.             == exp_getnval( &( CURTASK exps[ level + 1 ] )) )
  833.             {
  834.             CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  835.             }
  836.          else
  837.             {
  838.             CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  839.             }
  840.          break;
  841.  
  842.       }
  843.  
  844.    /* set variable to integer and operation to NUMBER:
  845.       this must be done at the end, since at the beginning it
  846.       might cause op_islevelstr() to return a false error */
  847.  
  848.    CURTASK exps[ level - 1 ].type = NUMBER;
  849.    CURTASK exps[ level - 1 ].operation = NUMBER;
  850.  
  851.    /* decrement the stack */
  852.  
  853.    op_pulldown( 2 );
  854.  
  855.    return TRUE;
  856.  
  857.    }
  858.  
  859. /***************************************************************
  860.  
  861.     FUNCTION:       op_lessthan()
  862.  
  863.     DESCRIPTION:    This function compares two values and
  864.             returns an integer value: TRUE if the
  865.             left hand value is less than the right,
  866.             and FALSE if it is not.
  867.  
  868. ***************************************************************/
  869.  
  870. #if ANSI_C
  871. static int
  872. op_lessthan( int level, int precision )
  873. #else
  874. static int
  875. op_lessthan( level, precision )
  876.    int level;
  877.    int precision;
  878. #endif
  879.    {
  880.    int error_condition;
  881.  
  882.    error_condition = FALSE;
  883.  
  884.    switch( precision )
  885.       {
  886.       case STRING:
  887.  
  888.          /* both sides of the operation should be numbers for
  889.             string addition; if not, report an error */
  890.  
  891.          if (  ( op_islevelstr( level - 1 ) != TRUE )
  892.             || ( op_islevelstr( level + 1 ) != TRUE ) )
  893.             {
  894. #if PROG_ERRORS
  895.             sprintf( bwb_ebuf, "Type mismatch in string comparison." );
  896.             bwb_error( bwb_ebuf );
  897. #else
  898.             bwb_error( err_mismatch );
  899. #endif
  900.             error_condition = TRUE;
  901.             }
  902.  
  903.          /* compare the two strings */
  904.  
  905.          if ( error_condition == FALSE )
  906.             {
  907.             if ( str_cmp( exp_getsval( &( CURTASK exps[ level - 1 ] )),
  908.                exp_getsval( &( CURTASK exps[ level + 1 ] )) ) < 0 )
  909.                {
  910.                CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  911.                }
  912.             else
  913.                {
  914.                CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  915.                }
  916.             }
  917.          break;
  918.  
  919.       case NUMBER:
  920.          if ( exp_getnval( &( CURTASK exps[ level - 1 ] ))
  921.             < exp_getnval( &( CURTASK exps[ level + 1 ] )) )
  922.             {
  923.             CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  924.             }
  925.          else
  926.             {
  927.             CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  928.             }
  929.          break;
  930.  
  931.       }
  932.  
  933.    /* set variable to integer and operation to NUMBER:
  934.       this must be done at the end, since at the beginning it
  935.       might cause op_islevelstr() to return a false error */
  936.  
  937.    CURTASK exps[ level - 1 ].type = NUMBER;
  938.    CURTASK exps[ level - 1 ].operation = NUMBER;
  939.  
  940.    /* decrement the stack */
  941.  
  942.    op_pulldown( 2 );
  943.  
  944.    return TRUE;
  945.  
  946.    }
  947.  
  948. /***************************************************************
  949.  
  950.     FUNCTION:       op_greaterthan()
  951.  
  952.     DESCRIPTION:    This function compares two values and
  953.             returns an integer value: TRUE if the
  954.             left hand value is greater than the right,
  955.             and FALSE if it is not.
  956.  
  957. ***************************************************************/
  958.  
  959. #if ANSI_C
  960. static int
  961. op_greaterthan( int level, int precision )
  962. #else
  963. static int
  964. op_greaterthan( level, precision )
  965.    int level;
  966.    int precision;
  967. #endif
  968.    {
  969.    int error_condition;
  970.  
  971.    error_condition = FALSE;
  972.  
  973.    switch( precision )
  974.       {
  975.       case STRING:
  976.  
  977.          /* both sides of the operation should be numbers for
  978.             string addition; if not, report an error */
  979.  
  980.          if (  ( op_islevelstr( level - 1 ) != TRUE )
  981.             || ( op_islevelstr( level + 1 ) != TRUE ) )
  982.             {
  983. #if PROG_ERRORS
  984.             sprintf( bwb_ebuf, "Type mismatch in string comparison." );
  985.             bwb_error( bwb_ebuf );
  986. #else
  987.             bwb_error( err_mismatch );
  988. #endif
  989.             error_condition = TRUE;
  990.             }
  991.  
  992.          /* compare the two strings */
  993.  
  994.          if ( error_condition == FALSE )
  995.             {
  996.             if ( str_cmp( exp_getsval( &( CURTASK exps[ level - 1 ] )),
  997.                exp_getsval( &( CURTASK exps[ level + 1 ] )) ) > 0 )
  998.                {
  999.                CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  1000.                }
  1001.             else
  1002.                {
  1003.                CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  1004.                }
  1005.             }
  1006.          break;
  1007.  
  1008.       case NUMBER:
  1009.          if ( exp_getnval( &( CURTASK exps[ level - 1 ] ))
  1010.             > exp_getnval( &( CURTASK exps[ level + 1 ] )) )
  1011.             {
  1012.             CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  1013.             }
  1014.          else
  1015.             {
  1016.             CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  1017.             }
  1018.          break;
  1019.  
  1020.       }
  1021.  
  1022.    /* set variable to integer and operation to NUMBER:
  1023.       this must be done at the end, since at the beginning it
  1024.       might cause op_islevelstr() to return a false error */
  1025.  
  1026.    CURTASK exps[ level - 1 ].type = NUMBER;
  1027.    CURTASK exps[ level - 1 ].operation = NUMBER;
  1028.  
  1029.    /* decrement the stack */
  1030.  
  1031.    op_pulldown( 2 );
  1032.  
  1033.    return TRUE;
  1034.  
  1035.    }
  1036.  
  1037. /***************************************************************
  1038.  
  1039.     FUNCTION:       op_lteq()
  1040.  
  1041.     DESCRIPTION:    This function compares two values and
  1042.             returns an integer value: TRUE if the
  1043.             left hand value is less than or equal
  1044.             to the right, and FALSE if it is not.
  1045.  
  1046. ***************************************************************/
  1047.  
  1048. #if ANSI_C
  1049. static int
  1050. op_lteq( int level, int precision )
  1051. #else
  1052. static int
  1053. op_lteq( level, precision )
  1054.    int level;
  1055.    int precision;
  1056. #endif
  1057.    {
  1058.    int error_condition;
  1059.  
  1060.    error_condition = FALSE;
  1061.  
  1062.    switch( precision )
  1063.       {
  1064.       case STRING:
  1065.  
  1066.          /* both sides of the operation should be numbers for
  1067.             string addition; if not, report an error */
  1068.  
  1069.          if (  ( op_islevelstr( level - 1 ) != TRUE )
  1070.             || ( op_islevelstr( level + 1 ) != TRUE ) )
  1071.             {
  1072. #if PROG_ERRORS
  1073.             sprintf( bwb_ebuf, "Type mismatch in string comparison." );
  1074.             bwb_error( bwb_ebuf );
  1075. #else
  1076.             bwb_error( err_mismatch );
  1077. #endif
  1078.             error_condition = TRUE;
  1079.             }
  1080.  
  1081.          /* compare the two strings */
  1082.  
  1083.          if ( error_condition == FALSE )
  1084.             {
  1085.             if ( str_cmp( exp_getsval( &( CURTASK exps[ level - 1 ] )),
  1086.                exp_getsval( &( CURTASK exps[ level + 1 ] )) ) <= 0 )
  1087.                {
  1088.                CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  1089.                }
  1090.             else
  1091.                {
  1092.                CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  1093.                }
  1094.             }
  1095.          break;
  1096.  
  1097.       case NUMBER:
  1098.          if ( exp_getnval( &( CURTASK exps[ level - 1 ] ))
  1099.             <= exp_getnval( &( CURTASK exps[ level + 1 ] )) )
  1100.             {
  1101.             CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  1102.             }
  1103.          else
  1104.             {
  1105.             CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  1106.             }
  1107.          break;
  1108.  
  1109.       }
  1110.  
  1111.    /* set variable to integer and operation to NUMBER:
  1112.       this must be done at the end, since at the beginning it
  1113.       might cause op_islevelstr() to return a false error */
  1114.  
  1115.    CURTASK exps[ level - 1 ].type = NUMBER;
  1116.    CURTASK exps[ level - 1 ].operation = NUMBER;
  1117.  
  1118.    /* decrement the stack */
  1119.  
  1120.    op_pulldown( 2 );
  1121.  
  1122.    return TRUE;
  1123.  
  1124.    }
  1125.  
  1126. /***************************************************************
  1127.  
  1128.     FUNCTION:       op_gteq()
  1129.  
  1130.     DESCRIPTION:    This function compares two values and
  1131.             returns an integer value: TRUE if the
  1132.             left hand value is greater than or equal
  1133.             to the right, and FALSE if it is not.
  1134.  
  1135. ***************************************************************/
  1136.  
  1137. #if ANSI_C
  1138. static int
  1139. op_gteq( int level, int precision )
  1140. #else
  1141. static int
  1142. op_gteq( level, precision )
  1143.    int level;
  1144.    int precision;
  1145. #endif
  1146.    {
  1147.    int error_condition;
  1148.  
  1149.    error_condition = FALSE;
  1150.  
  1151.    switch( precision )
  1152.       {
  1153.       case STRING:
  1154.  
  1155.          /* both sides of the operation should be numbers for
  1156.             string addition; if not, report an error */
  1157.  
  1158.          if (  ( op_islevelstr( level - 1 ) != TRUE )
  1159.             || ( op_islevelstr( level + 1 ) != TRUE ) )
  1160.             {
  1161. #if PROG_ERRORS
  1162.             sprintf( bwb_ebuf, "Type mismatch in string comparison." );
  1163.             bwb_error( bwb_ebuf );
  1164. #else
  1165.             bwb_error( err_mismatch );
  1166. #endif
  1167.             error_condition = TRUE;
  1168.             }
  1169.  
  1170.          /* compare the two strings */
  1171.  
  1172.          if ( error_condition == FALSE )
  1173.             {
  1174.             if ( str_cmp( exp_getsval( &( CURTASK exps[ level - 1 ] )),
  1175.                exp_getsval( &( CURTASK exps[ level + 1 ] )) ) >= 0 )
  1176.                {
  1177.                CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  1178.                }
  1179.             else
  1180.                {
  1181.                CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  1182.                }
  1183.             }
  1184.          break;
  1185.  
  1186.       case NUMBER:
  1187.          if ( exp_getnval( &( CURTASK exps[ level - 1 ] ))
  1188.             >= exp_getnval( &( CURTASK exps[ level + 1 ] )) )
  1189.             {
  1190.             CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  1191.             }
  1192.          else
  1193.             {
  1194.             CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  1195.             }
  1196.          break;
  1197.  
  1198.       }
  1199.  
  1200.    /* set variable to integer and operation to NUMBER:
  1201.       this must be done at the end, since at the beginning it
  1202.       might cause op_islevelstr() to return a false error */
  1203.  
  1204.    CURTASK exps[ level - 1 ].type = NUMBER;
  1205.    CURTASK exps[ level - 1 ].operation = NUMBER;
  1206.  
  1207.    /* decrement the stack */
  1208.  
  1209.    op_pulldown( 2 );
  1210.  
  1211.    return TRUE;
  1212.  
  1213.    }
  1214.  
  1215. /***************************************************************
  1216.  
  1217.     FUNCTION:       op_notequal()
  1218.  
  1219.     DESCRIPTION:    This function compares two values and
  1220.             returns an integer value: TRUE if they
  1221.             are not the same and FALSE if they are.
  1222.  
  1223. ***************************************************************/
  1224.  
  1225. #if ANSI_C
  1226. static int
  1227. op_notequal( int level, int precision )
  1228. #else
  1229. static int
  1230. op_notequal( level, precision )
  1231.    int level;
  1232.    int precision;
  1233. #endif
  1234.    {
  1235.    int error_condition;
  1236.  
  1237.    error_condition = FALSE;
  1238.  
  1239.    switch( precision )
  1240.       {
  1241.       case STRING:
  1242.  
  1243.          /* both sides of the operation should be numbers for
  1244.             string addition; if not, report an error */
  1245.  
  1246.          if (  ( op_islevelstr( level - 1 ) != TRUE )
  1247.             || ( op_islevelstr( level + 1 ) != TRUE ) )
  1248.             {
  1249. #if PROG_ERRORS
  1250.             sprintf( bwb_ebuf, "Type mismatch in string comparison." );
  1251.             bwb_error( bwb_ebuf );
  1252. #else
  1253.             bwb_error( err_mismatch );
  1254. #endif
  1255.             error_condition = TRUE;
  1256.             }
  1257.  
  1258.          /* compare the two strings */
  1259.  
  1260.          if ( error_condition == FALSE )
  1261.  
  1262.             {
  1263.             if ( str_cmp( exp_getsval( &( CURTASK exps[ level - 1 ] )),
  1264.                exp_getsval( &( CURTASK exps[ level + 1 ] )) ) != 0 )
  1265.                {
  1266.                CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  1267.                }
  1268.             else
  1269.                {
  1270.                CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  1271.                }
  1272.             }
  1273.          break;
  1274.  
  1275.       case NUMBER:
  1276.          if ( exp_getnval( &( CURTASK exps[ level - 1 ] ))
  1277.             != exp_getnval( &( CURTASK exps[ level + 1 ] )) )
  1278.             {
  1279.             CURTASK exps[ level - 1 ].nval = (bnumber) TRUE;
  1280.             }
  1281.          else
  1282.             {
  1283.             CURTASK exps[ level - 1 ].nval = (bnumber) FALSE;
  1284.             }
  1285.          break;
  1286.  
  1287.       }
  1288.  
  1289.    /* set variable to integer and operation to NUMBER:
  1290.       this must be done at the end, since at the beginning it
  1291.       might cause op_islevelstr() to return a false error */
  1292.  
  1293.    CURTASK exps[ level - 1 ].type = NUMBER;
  1294.    CURTASK exps[ level - 1 ].operation = NUMBER;
  1295.  
  1296.    /* decrement the stack */
  1297.  
  1298.    op_pulldown( 2 );
  1299.  
  1300.    return TRUE;
  1301.  
  1302.    }
  1303.  
  1304. /***************************************************************
  1305.  
  1306.     FUNCTION:       op_modulus()
  1307.  
  1308.     DESCRIPTION:    This function divides the number on
  1309.             the left by the number on the right
  1310.             and returns the remainder.
  1311.  
  1312. ***************************************************************/
  1313.  
  1314. #if ANSI_C
  1315. static int
  1316. op_modulus( int level, int precision )
  1317. #else
  1318. static int
  1319. op_modulus( level, precision )
  1320.    int level;
  1321.    int precision;
  1322. #endif
  1323.    {
  1324.    static double iportion;
  1325.  
  1326.    switch( precision )
  1327.       {
  1328.       case STRING:
  1329.  
  1330.          /* both sides of the operation should be numbers for
  1331.             string addition; if not, report an error */
  1332.  
  1333. #if PROG_ERRORS
  1334.          sprintf( bwb_ebuf, "Strings cannot be divided." );
  1335.          bwb_error( bwb_ebuf );
  1336. #else
  1337.          bwb_error( err_syntax );
  1338. #endif
  1339.  
  1340.          break;
  1341.  
  1342.       case NUMBER:
  1343.          if ( exp_getnval( &( CURTASK exps[ level + 1 ] ))
  1344.             == (bnumber) 0 )
  1345.             {
  1346.             CURTASK exps[ level - 1 ].nval = (bnumber) -1;
  1347.             op_pulldown( 2 );
  1348. #if PROG_ERRORS
  1349.             sprintf( bwb_ebuf, "Divide by 0." );
  1350.             bwb_error( bwb_ebuf );
  1351. #else
  1352.             bwb_error( err_dbz );
  1353. #endif
  1354.             return FALSE;
  1355.             }
  1356.          CURTASK exps[ level ].nval
  1357.             = exp_getnval( &( CURTASK exps[ level - 1 ] ))
  1358.             / exp_getnval( &( CURTASK exps[ level + 1 ] ));
  1359.          modf( (double) CURTASK exps[ level ].nval, &iportion );
  1360.          CURTASK exps[ level - 1 ].nval
  1361.             = exp_getnval( &( CURTASK exps[ level - 1 ] ))
  1362.             - ( exp_getnval( &( CURTASK exps[ level + 1 ] ))
  1363.             * iportion );
  1364.          break;
  1365.  
  1366.       }
  1367.  
  1368.    /* set variable to requested precision */
  1369.  
  1370.    CURTASK exps[ level - 1 ].type = (char) precision;
  1371.    CURTASK exps[ level - 1 ].operation = NUMBER;
  1372.  
  1373.    /* decrement the stack twice */
  1374.  
  1375.    op_pulldown( 2 );
  1376.  
  1377.    return TRUE;
  1378.  
  1379.    }
  1380.  
  1381. /***************************************************************
  1382.  
  1383.     FUNCTION:       op_exponent()
  1384.  
  1385.     DESCRIPTION:    This function finds the exponential value
  1386.             of a number (on the left) to the power
  1387.             indicated on the right-hand side.
  1388.  
  1389. ***************************************************************/
  1390.  
  1391. #if ANSI_C
  1392. static int
  1393. op_exponent( int level, int precision )
  1394. #else
  1395. static int
  1396. op_exponent( level, precision )
  1397.    int level;
  1398.    int precision;
  1399. #endif
  1400.    {
  1401.  
  1402. #if INTENSIVE_DEBUG
  1403.    sprintf( bwb_ebuf, "in op_exponent(): entered function level <%d>.",
  1404.       level );
  1405.    bwb_debug ( bwb_ebuf );
  1406. #endif
  1407.  
  1408.    switch( precision )
  1409.       {
  1410.       case STRING:
  1411.  
  1412.          /* both sides of the operation should be numbers for
  1413.             string addition; if not, report an error */
  1414.  
  1415. #if PROG_ERRORS
  1416.          sprintf( bwb_ebuf, "Strings cannot be taken as exponents." );
  1417.          bwb_error( bwb_ebuf );
  1418. #else
  1419.          bwb_error( err_mismatch );
  1420. #endif
  1421.  
  1422.          break;
  1423.  
  1424.       case NUMBER:
  1425.          CURTASK exps[ level - 1 ].nval
  1426.            = (bnumber) pow( (double) exp_getnval( &( CURTASK exps[ level - 1 ] )),
  1427.                   (double) exp_getnval( &( CURTASK exps[ level + 1 ] )) );
  1428.          break;
  1429.  
  1430.       }
  1431.  
  1432.    /* set variable to requested precision */
  1433.  
  1434.    CURTASK exps[ level - 1 ].type = (char) precision;
  1435.    CURTASK exps[ level - 1 ].operation = NUMBER;
  1436.  
  1437.    /* decrement the stack twice */
  1438.  
  1439.    op_pulldown( 2 );
  1440.  
  1441.    return TRUE;
  1442.  
  1443.    }
  1444.  
  1445. /***************************************************************
  1446.  
  1447.     FUNCTION:       op_intdiv()
  1448.  
  1449.     DESCRIPTION:    This function divides the number on
  1450.             the left by the number on the right,
  1451.             returning the result as an integer.
  1452.  
  1453. ***************************************************************/
  1454.  
  1455. #if ANSI_C
  1456. static int
  1457. op_intdiv( int level, int precision )
  1458. #else
  1459. static int
  1460. op_intdiv( level, precision )
  1461.    int level;
  1462.    int precision;
  1463. #endif
  1464.    {
  1465.  
  1466.    switch( precision )
  1467.       {
  1468.       case STRING:
  1469.  
  1470.          /* both sides of the operation should be numbers for
  1471.             string addition; if not, report an error */
  1472.  
  1473. #if PROG_ERRORS
  1474.          sprintf( bwb_ebuf, "Strings cannot be divided." );
  1475.          bwb_error( bwb_ebuf );
  1476. #else
  1477.          bwb_error( err_mismatch );
  1478. #endif
  1479.  
  1480.          break;
  1481.  
  1482.       default:
  1483.          if ( exp_getnval( &( CURTASK exps[ level + 1 ] ))
  1484.             == (bnumber) 0 )
  1485.             {
  1486.             CURTASK exps[ level - 1 ].nval = (bnumber) -1;
  1487.             op_pulldown( 2 );
  1488. #if PROG_ERRORS
  1489.             sprintf( bwb_ebuf, "Divide by 0." );
  1490.             bwb_error( bwb_ebuf );
  1491. #else
  1492.             bwb_error( err_dbz );
  1493. #endif
  1494.             return FALSE;
  1495.             }
  1496.  
  1497.          CURTASK exps[ level - 1 ].nval
  1498.             = exp_getnval( &( CURTASK exps[ level - 1 ] ))
  1499.             / exp_getnval( &( CURTASK exps[ level + 1 ] ));
  1500.          break;
  1501.       }
  1502.  
  1503.    /* set variable to requested precision */
  1504.  
  1505.    CURTASK exps[ level - 1 ].type = NUMBER;
  1506.    CURTASK exps[ level - 1 ].operation = NUMBER;
  1507.  
  1508.    /* decrement the stack twice */
  1509.  
  1510.    op_pulldown( 2 );
  1511.  
  1512.    return TRUE;
  1513.  
  1514.    }
  1515.  
  1516. /***************************************************************
  1517.  
  1518.     FUNCTION:       op_or()
  1519.  
  1520.     DESCRIPTION:    This function compares two integers and
  1521.             performs a logical NOT on them.
  1522.  
  1523. ***************************************************************/
  1524.  
  1525. #if ANSI_C
  1526. static int
  1527. op_or( int level, int precision )
  1528. #else
  1529. static int
  1530. op_or( level, precision )
  1531.    int level;
  1532.    int precision;
  1533. #endif
  1534.    {
  1535.  
  1536.    switch( precision )
  1537.       {
  1538.       case STRING:
  1539.  
  1540.          /* both sides of the operation should be numbers for
  1541.             logical comparison; if not, report an error */
  1542.  
  1543. #if PROG_ERRORS
  1544.          sprintf( bwb_ebuf, "Strings cannot be compared logically." );
  1545.          bwb_error( bwb_ebuf );
  1546. #else
  1547.          bwb_error( err_mismatch );
  1548. #endif
  1549.  
  1550.          break;
  1551.  
  1552.       case NUMBER:
  1553.          CURTASK exps[ level - 1 ].nval
  1554.             = (bnumber) ((int) exp_getnval( &( CURTASK exps[ level - 1 ] ))
  1555.             | (int) exp_getnval( &( CURTASK exps[ level + 1 ] )));
  1556.          break;
  1557.  
  1558.       }
  1559.  
  1560.    /* set variable type to integer */
  1561.  
  1562.    CURTASK exps[ level - 1 ].type = NUMBER;
  1563.    CURTASK exps[ level - 1 ].operation = NUMBER;
  1564.  
  1565.    /* decrement the stack twice */
  1566.  
  1567.    op_pulldown( 2 );
  1568.  
  1569.    return TRUE;
  1570.  
  1571.    }
  1572.  
  1573. /***************************************************************
  1574.  
  1575.     FUNCTION:       op_and()
  1576.  
  1577.     DESCRIPTION:    This function compares two integers and
  1578.             performs a logical NOT on them.
  1579.  
  1580. ***************************************************************/
  1581.  
  1582. #if ANSI_C
  1583. static int
  1584. op_and( int level, int precision )
  1585. #else
  1586. static int
  1587. op_and( level, precision )
  1588.    int level;
  1589.    int precision;
  1590. #endif
  1591.    {
  1592.  
  1593.    switch( precision )
  1594.       {
  1595.       case STRING:
  1596.  
  1597.  
  1598.          /* both sides of the operation should be numbers for
  1599.             logical comparison; if not, report an error */
  1600.  
  1601. #if PROG_ERRORS
  1602.          sprintf( bwb_ebuf, "Strings cannot be compared logically." );
  1603.          bwb_error( bwb_ebuf );
  1604. #else
  1605.          bwb_error( err_mismatch );
  1606. #endif
  1607.  
  1608.          break;
  1609.  
  1610.       case NUMBER:
  1611.          CURTASK exps[ level - 1 ].nval
  1612.             = (bnumber) ((int) exp_getnval( &( CURTASK exps[ level - 1 ] ))
  1613.             & (int) exp_getnval( &( CURTASK exps[ level + 1 ] )));
  1614.          break;
  1615.  
  1616.       }
  1617.  
  1618.    /* set variable type to integer */
  1619.  
  1620.    CURTASK exps[ level - 1 ].type = NUMBER;
  1621.    CURTASK exps[ level - 1 ].operation = NUMBER;
  1622.  
  1623.    /* decrement the stack twice */
  1624.  
  1625.    op_pulldown( 2 );
  1626.  
  1627.    return TRUE;
  1628.  
  1629.    }
  1630.  
  1631. /***************************************************************
  1632.  
  1633.     FUNCTION:       op_not()
  1634.  
  1635.     DESCRIPTION:    This function compares two integers and
  1636.             performs a logical NOT on them.
  1637.  
  1638. ***************************************************************/
  1639.  
  1640. #if ANSI_C
  1641. static int
  1642. op_not( int level, int precision )
  1643. #else
  1644. static int
  1645. op_not( level, precision )
  1646.    int level;
  1647.    int precision;
  1648. #endif
  1649.    {
  1650.  
  1651.    switch( precision )
  1652.       {
  1653.       case STRING:
  1654.  
  1655.  
  1656.          /* both sides of the operation should be numbers for
  1657.             logical comparison; if not, report an error */
  1658.  
  1659. #if PROG_ERRORS
  1660.          sprintf( bwb_ebuf, "Strings cannot be compared logically." );
  1661.          bwb_error( bwb_ebuf );
  1662. #else
  1663.          bwb_error( err_mismatch );
  1664. #endif
  1665.  
  1666.          break;
  1667.  
  1668.       default:
  1669.  
  1670. #if INTENSIVE_DEBUG
  1671.          sprintf( bwb_ebuf, "in op_not(): argument is <%d>, precision <%c>",
  1672.             (unsigned int) exp_getnval( &( CURTASK exps[ level + 1 ] )), precision );
  1673.          bwb_debug( bwb_ebuf );
  1674. #endif
  1675.  
  1676.          CURTASK exps[ level ].nval = (bnumber)
  1677.             ~( (int) exp_getnval( &( CURTASK exps[ level + 1 ] )) );
  1678.  
  1679. #if INTENSIVE_DEBUG
  1680.          sprintf( bwb_ebuf, "in op_not(): result is <%d>, precision <%c>",
  1681.             (int) r, precision );
  1682.          bwb_debug( bwb_ebuf );
  1683. #endif
  1684.  
  1685.          break;
  1686.       }
  1687.  
  1688.    /* set variable type to integer */
  1689.  
  1690.    CURTASK exps[ level ].type = NUMBER;
  1691.    CURTASK exps[ level ].operation = NUMBER;
  1692.  
  1693.    /* decrement the stack once */
  1694.  
  1695.    op_pulldown( 1 );
  1696.  
  1697. #if INTENSIVE_DEBUG
  1698.    sprintf( bwb_ebuf, "in op_not(): CURTASK expsc <%d>, level <%d> result <%d>",
  1699.       CURTASK expsc, level, CURTASK exps[ CURTASK expsc ].nval );
  1700.    bwb_debug( bwb_ebuf );
  1701. #endif
  1702.  
  1703.    return TRUE;
  1704.  
  1705.    }
  1706.  
  1707. /***************************************************************
  1708.  
  1709.     FUNCTION:       op_xor()
  1710.  
  1711.     DESCRIPTION:    This function compares two integers and
  1712.             performs a logical NOT on them.
  1713.  
  1714. ***************************************************************/
  1715.  
  1716. #if ANSI_C
  1717. static int
  1718. op_xor( int level, int precision )
  1719. #else
  1720. static int
  1721. op_xor( level, precision )
  1722.    int level;
  1723.    int precision;
  1724. #endif
  1725.    {
  1726.  
  1727.    switch( precision )
  1728.       {
  1729.       case STRING:
  1730.  
  1731.          /* both sides of the operation should be numbers for
  1732.             logical comparison; if not, report an error */
  1733.  
  1734. #if PROG_ERRORS
  1735.          sprintf( bwb_ebuf, "Strings cannot be compared logically." );
  1736.          bwb_error( bwb_ebuf );
  1737. #else
  1738.          bwb_error( err_mismatch );
  1739. #endif
  1740.  
  1741.          break;
  1742.  
  1743.       case NUMBER:
  1744.          CURTASK exps[ level - 1 ].nval
  1745.             = (bnumber) ((int) exp_getnval( &( CURTASK exps[ level - 1 ] ))
  1746.             ^ (int) exp_getnval( &( CURTASK exps[ level + 1 ] )));
  1747.          break;
  1748.  
  1749.       }
  1750.  
  1751.    /* set variable type to integer */
  1752.  
  1753.    CURTASK exps[ level - 1 ].type = NUMBER;
  1754.    CURTASK exps[ level - 1 ].operation = NUMBER;
  1755.  
  1756.    /* decrement the stack twice */
  1757.  
  1758.    op_pulldown( 2 );
  1759.  
  1760.    return TRUE;
  1761.  
  1762.    }
  1763.  
  1764. /***************************************************************
  1765.  
  1766.     FUNCTION:       op_islevelstr()
  1767.  
  1768.     DESCRIPTION:    This function determines whether the
  1769.             operation at a specified level involves a
  1770.             string constant or variable.
  1771.  
  1772. ***************************************************************/
  1773.  
  1774. #if ANSI_C
  1775. static int
  1776. op_islevelstr( int level )
  1777. #else
  1778. static int
  1779. op_islevelstr( level )
  1780.    int level;
  1781. #endif
  1782.    {
  1783.  
  1784.    /* first see if the level holds a string constant */
  1785.  
  1786.    if ( CURTASK exps[ level ].operation == CONST_STRING )
  1787.       {
  1788.  
  1789. #if INTENSIVE_DEBUG
  1790.       sprintf( bwb_ebuf, "in op_islevelstr(): string detected at level <%d>.",
  1791.          level );
  1792.       bwb_debug( bwb_ebuf );
  1793. #endif
  1794.  
  1795.       return TRUE;
  1796.       }
  1797.  
  1798.    /* see if the level holds a string variable */
  1799.  
  1800.    if ( CURTASK exps[ level ].operation == VARIABLE )
  1801.       {
  1802.       if ( CURTASK exps[ level ].xvar->type == STRING )
  1803.          {
  1804.  
  1805. #if INTENSIVE_DEBUG
  1806.          sprintf( bwb_ebuf, "in op_islevelstr(): string detected at level <%d>.",
  1807.             level );
  1808.          bwb_debug( bwb_ebuf );
  1809. #endif
  1810.  
  1811.          return TRUE;
  1812.          }
  1813.       }
  1814.  
  1815.    /* test has failed, return FALSE */
  1816.  
  1817. #if INTENSIVE_DEBUG
  1818.    sprintf( bwb_ebuf, "in op_islevelstr(): string not detected at level <%d>.",
  1819.       level );
  1820.    bwb_debug( bwb_ebuf );
  1821. #endif
  1822.  
  1823.    return FALSE;
  1824.  
  1825.    }
  1826.  
  1827. /***************************************************************
  1828.  
  1829.     FUNCTION:       op_getprecision()
  1830.  
  1831.     DESCRIPTION:    This function finds the precision for
  1832.             an operation by comparing the precision
  1833.             at this level and that two levels below.
  1834.  
  1835. ***************************************************************/
  1836.  
  1837. #if ANSI_C
  1838. static int
  1839. op_getprecision( int level )
  1840. #else
  1841. static int
  1842. op_getprecision( level )
  1843.    int level;
  1844. #endif
  1845.    {
  1846.  
  1847.    /* first test for string value */
  1848.  
  1849.    if (  ( CURTASK exps[ level + 1 ].type == STRING )
  1850.       || ( CURTASK exps[ level - 1 ].type == STRING ) )
  1851.       {
  1852.       return STRING;
  1853.       }
  1854.  
  1855.    /* Both are numbers, so we should be able to find a suitable
  1856.       precision level by starting with the top and moving down;
  1857.       check first for double precision */
  1858.  
  1859.    else
  1860.       {
  1861.       return NUMBER;
  1862.       }
  1863.  
  1864.    }
  1865.  
  1866. /***************************************************************
  1867.  
  1868.     FUNCTION:       op_pulldown()
  1869.  
  1870.     DESCRIPTION:    This function pulls the expression stack
  1871.             down a specified number of levels, decrementing
  1872.             the expression stack counter (bycalling dec_esc())
  1873.             and decrementing the current "level" of operation
  1874.             processing.
  1875.  
  1876. ***************************************************************/
  1877.  
  1878. #if ANSI_C
  1879. static int
  1880. op_pulldown( int how_far )
  1881. #else
  1882. static int
  1883. op_pulldown( how_far )
  1884.    int how_far;
  1885. #endif
  1886.    {
  1887.    int level;
  1888.    register int c;
  1889.  
  1890. #if INTENSIVE_DEBUG
  1891.    sprintf( bwb_ebuf, "in op_pulldown(): pull down e stack <%d> place(s)",
  1892.       how_far );
  1893.    bwb_debug( bwb_ebuf );
  1894. #endif
  1895.  
  1896.    /* first pull down the actual variables themselves */
  1897.  
  1898.    level = op_level + ( 2 - how_far );
  1899.    while ( CURTASK expsc >= ( level + how_far ) )
  1900.       {
  1901.  
  1902.       memcpy( &CURTASK exps[ level ], &CURTASK exps[ level + how_far ],
  1903.          (size_t) ( sizeof( struct exp_ese )) );
  1904.       ++level;
  1905.  
  1906.       }
  1907.  
  1908.    /* decrement the expression stack counter */
  1909.  
  1910.    for ( c = 0; c < how_far; ++c )
  1911.       {
  1912.  
  1913.       if ( dec_esc() == TRUE )
  1914.          {
  1915.          --op_level;
  1916.          }
  1917.       else
  1918.          {
  1919.          return FALSE;
  1920.          }
  1921.  
  1922.       }
  1923.  
  1924.    return TRUE;
  1925.  
  1926.    }
  1927.  
  1928.  
  1929.