home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / bwbasic.zip / src / bwb_exp.c < prev    next >
C/C++ Source or Header  |  1993-04-27  |  40KB  |  1,576 lines

  1. /****************************************************************
  2.  
  3.         bwb_exp.c       Expression Parser
  4.                         for Bywater BASIC Interpreter
  5.  
  6.                         Copyright (c) 1992, Ted A. Campbell
  7.  
  8.                         Bywater Software
  9.                         P. O. Box 4023
  10.                         Duke Station
  11.                         Durham, NC  27706
  12.  
  13.                         email: tcamp@acpub.duke.edu
  14.  
  15.         Copyright and Permissions Information:
  16.  
  17.         All U.S. and international copyrights are claimed by the
  18.         author. The author grants permission to use this code
  19.         and software based on it under the following conditions:
  20.         (a) in general, the code and software based upon it may be
  21.         used by individuals and by non-profit organizations; (b) it
  22.         may also be utilized by governmental agencies in any country,
  23.         with the exception of military agencies; (c) the code and/or
  24.         software based upon it may not be sold for a profit without
  25.         an explicit and specific permission from the author, except
  26.         that a minimal fee may be charged for media on which it is
  27.         copied, and for copying and handling; (d) the code must be
  28.         distributed in the form in which it has been released by the
  29.         author; and (e) the code and software based upon it may not
  30.         be used for illegal activities.
  31.  
  32. ****************************************************************/
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <ctype.h>
  38. #include <math.h>
  39.  
  40. #include "bwbasic.h"
  41. #include "bwb_mes.h"
  42.  
  43. int exp_esc = 0;                        /* expression stack counter */
  44.  
  45. /***************************************************************
  46.  
  47.         FUNCTION:   bwb_exp()
  48.  
  49.         DESCRIPTION:  This is the function by which the expression
  50.         parser is called.
  51.  
  52. ***************************************************************/
  53.  
  54. struct exp_ese *
  55. bwb_exp( char *expression, int assignment, int *position )
  56.    {
  57.    struct exp_ese *rval;            /* return value */
  58.    int entry_level, main_loop, adv_loop, err_condition;
  59.    char *e;                                     /* pointer to current string */
  60.    int r;                                       /* return value from functions */
  61.    register int c;                              /* quick counter */
  62.  
  63.    #if INTENSIVE_DEBUG
  64.    sprintf( bwb_ebuf, "in bwb_exp(): expression <%s> assignment <%d> level <%d>",
  65.       & ( expression[ *position ] ), assignment, exp_esc );
  66.    bwb_debug( bwb_ebuf );
  67.    #endif
  68.  
  69.    /* save the entry level of the expression stack in order to
  70.       check it at the end of this function */
  71.  
  72.    entry_level = exp_esc;
  73.    err_condition = FALSE;
  74.  
  75.    /* advance past whitespace or beginningg of line segment */
  76.  
  77.    if ( expression[ *position ] == ':' )
  78.       {
  79.       ++( *position );
  80.       }
  81.    adv_ws( expression, position );
  82.    if ( expression[ *position ] == ':' )
  83.       {
  84.       ++( *position );
  85.       adv_ws( expression, position );
  86.       }
  87.  
  88.    /* increment the expression stack counter to get a new level */
  89.  
  90.    inc_esc();
  91.  
  92.    /* check to be sure there is a legitimate expression
  93.       and set initial parameters for the main loop */
  94.  
  95.    adv_loop = TRUE;
  96.    while( adv_loop == TRUE )
  97.       {
  98.       switch( expression[ *position ] )
  99.          {
  100.          case ' ':                           /* whitespace */
  101.          case '\t':
  102.             ++(*position);
  103.             break;
  104.          case '\0':                          /* end of string */
  105.          case '\r':
  106.          case '\n':
  107.             main_loop = adv_loop = FALSE;    /* break out of loop */
  108.             break;
  109.          default:
  110.             adv_loop = FALSE;
  111.             main_loop = TRUE;
  112.             exp_es[ exp_esc ].pos_adv = 0;
  113.             break;
  114.          }
  115.       }
  116.  
  117.    /* main parsing loop */
  118.  
  119.    while ( main_loop == TRUE )
  120.       {
  121.  
  122.       /* set variable <e> to the start of the expression */
  123.  
  124.       e = &( expression[ *position ] );
  125.  
  126.       #if INTENSIVE_DEBUG
  127.       sprintf( bwb_ebuf, "in bwb_exp(): main loop, level <%d> element <%s> ",
  128.          exp_esc, e );
  129.       bwb_debug( bwb_ebuf );
  130.       #endif
  131.  
  132.       /* detect the operation required at this level */
  133.  
  134.       exp_es[ exp_esc ].operation = exp_findop( e );
  135.  
  136.       #if INTENSIVE_DEBUG
  137.       sprintf( bwb_ebuf, "in bwb_exp(): exp_findop() returned <%d>",
  138.          exp_es[ exp_esc ].operation );
  139.       bwb_debug( bwb_ebuf );
  140.       #endif
  141.  
  142.       /* perform actions specific to the operation */
  143.  
  144.       switch( exp_es[ exp_esc ].operation )
  145.          {
  146.          case OP_ERROR:
  147.             main_loop = FALSE;
  148.             err_condition = TRUE;
  149.             break;
  150.          case OP_TERMINATE:
  151.             main_loop = FALSE;
  152.             /* *position += 1; */
  153.             dec_esc();
  154.             break;
  155.          case OP_STRJOIN:                  /* string join or tab */
  156.          case OP_STRTAB:
  157.             main_loop = FALSE;
  158.             dec_esc();
  159.             break;
  160.          case OP_ADD:                      /* in the case of any numerical operation, */
  161.          case OP_SUBTRACT:
  162.          case OP_MULTIPLY:
  163.          case OP_DIVIDE:
  164.          case OP_MODULUS:
  165.          case OP_EXPONENT:
  166.          case OP_INTDIVISION:
  167.          case OP_GREATERTHAN:
  168.          case OP_LESSTHAN:
  169.          case OP_GTEQ:
  170.          case OP_LTEQ:
  171.          case OP_NOTEQUAL:
  172.          case OP_NOT:
  173.          case OP_AND:
  174.          case OP_OR:
  175.          case OP_XOR:
  176.          case OP_IMPLIES:
  177.          case OP_EQUIV:
  178.  
  179.             #if INTENSIVE_DEBUG
  180.             sprintf( bwb_ebuf, "in bwb_exp(): operator detected." );
  181.             bwb_debug( bwb_ebuf );
  182.             #endif
  183.  
  184.             exp_es[ exp_esc ].pos_adv = -1;             /* set to strange number */
  185.  
  186.             /* cycle through operator table to find match */
  187.  
  188.             for ( c = 0; c < N_OPERATORS; ++c )
  189.                {
  190.                if ( exp_ops[ c ].operation == exp_es[ exp_esc ].operation )
  191.                   {
  192.                   exp_es[ exp_esc ].pos_adv = strlen( exp_ops[ c ].symbol );
  193.                   }
  194.                }
  195.  
  196.             if ( exp_es[ exp_esc ].pos_adv == -1 )      /* was a match found? */
  197.                {
  198.                exp_es[ exp_esc ].pos_adv = 0;           /* no -- set to 0 */
  199.                }
  200.             break;                         /* and move on */
  201.  
  202.          case OP_EQUALS:
  203.  
  204.             #if INTENSIVE_DEBUG
  205.             sprintf( bwb_ebuf, "in bwb_exp(): equal sign detected." );
  206.             bwb_debug( bwb_ebuf );
  207.             #endif
  208.  
  209.             if ( assignment == TRUE )
  210.                {
  211.                exp_es[ exp_esc ].operation = OP_ASSIGN;
  212.                }
  213.             exp_es[ exp_esc ].pos_adv = 1;
  214.             break;
  215.  
  216.          case PARENTHESIS:
  217.             r = exp_paren( e );
  218.             break;
  219.          case CONST_STRING:
  220.             r = exp_strconst( e );
  221.             break;
  222.          case CONST_NUMERICAL:
  223.             r = exp_numconst( e );
  224.         #if INTENSIVE_DEBUG
  225.             sprintf( bwb_ebuf, "in bwb_exp(): return from exp_numconst(), r = <%d>",
  226.                r );
  227.             bwb_debug( bwb_ebuf );
  228.             #endif
  229.             break;
  230.  
  231.          case FUNCTION:
  232.  
  233.             #if INTENSIVE_DEBUG
  234.             sprintf( bwb_ebuf, "in bwb_exp(): calling exp_function(), expression <%s>",
  235.                e );
  236.             bwb_debug( bwb_ebuf );
  237.             #endif
  238.  
  239.             r = exp_function( e );
  240.             break;
  241.  
  242.          case VARIABLE:
  243.             r = exp_variable( e );
  244.             break;
  245.          default:
  246.             err_condition = TRUE;
  247.             main_loop = FALSE;
  248.             #if PROG_ERRORS
  249.             sprintf( bwb_ebuf, "in bwb_exp.c:bwb_exp(): unidentified operation (%d).",
  250.                exp_es[ exp_esc ].operation );
  251.             bwb_error( bwb_ebuf );
  252.             #else
  253.             bwb_error( err_syntax );
  254.             #endif
  255.             break;
  256.          }
  257.  
  258.       /* increment *position counter based on previous actions */
  259.  
  260.       *position += exp_es[ exp_esc ].pos_adv;
  261.       exp_es[ exp_esc ].pos_adv = 0;            /* reset advance counter */
  262.  
  263.       #if INTENSIVE_DEBUG
  264.       sprintf( bwb_ebuf, "in bwb_exp(): advanced position; r <%d> err_c <%d>",
  265.          r, err_condition );
  266.       bwb_debug( bwb_ebuf );
  267.       #endif
  268.  
  269.       #if INTENSIVE_DEBUG
  270.       if ( exp_es[ exp_esc ].operation == OP_EQUALS )
  271.          {
  272.          sprintf( bwb_ebuf, "in bwb_exp(): with OP_EQUALS: finished case" );
  273.          bwb_debug( bwb_ebuf );
  274.          }
  275.       #endif
  276.  
  277.       /* check for end of string */
  278.  
  279.       adv_loop = TRUE;
  280.       while( adv_loop == TRUE )
  281.          {
  282.          switch( expression[ *position ] )
  283.             {
  284.             case ' ':                           /* whitespace */
  285.             case '\t':
  286.                ++(*position);
  287.                break;
  288.             case '\0':                          /* end of string */
  289.             case '\r':
  290.             case '\n':
  291.             case ':':
  292.                main_loop = adv_loop = FALSE;    /* break out of loop */
  293.                break;
  294.             default:
  295.                adv_loop = FALSE;
  296.                break;
  297.             }
  298.          }
  299.  
  300.       /* get a new stack level before looping */
  301.  
  302.       if ( main_loop == TRUE )
  303.          {
  304.          r = inc_esc();
  305.          #if INTENSIVE_DEBUG
  306.          sprintf( bwb_ebuf, "in bwb_exp(): increment esc, r <%d>, err_c <%d>",
  307.             r, err_condition );
  308.          bwb_debug( bwb_ebuf );
  309.          #endif
  310.          }
  311.  
  312.       /* check for error return */
  313.  
  314.       if ( r == OP_ERROR )
  315.          {
  316.          #if INTENSIVE_DEBUG
  317.          sprintf( bwb_ebuf, "in bwb_exp(): found r == OP_ERROR." );
  318.          bwb_debug( bwb_ebuf );
  319.          #endif
  320.          main_loop = FALSE;
  321.          err_condition = TRUE;
  322.          }
  323.       else
  324.          {
  325.          r = TRUE;
  326.          }
  327.  
  328.       }                                 /* end of main parsing loop */
  329.  
  330.    #if INTENSIVE_DEBUG
  331.    sprintf( bwb_ebuf, "in bwb_exp(): breakout from main parsing loop, r <%d> err_c <%d>",
  332.       r, err_condition );
  333.    bwb_debug( bwb_ebuf );
  334.    #endif
  335.  
  336.    /* check error condition */
  337.  
  338.    if ( err_condition == TRUE )
  339.       {
  340.  
  341.       #if INTENSIVE_DEBUG
  342.       sprintf( bwb_ebuf, "ERROR: error detected in expression parser" );
  343.       bwb_debug( bwb_ebuf );
  344.       #endif
  345.  
  346.       /* decrement the expression stack counter until it matches entry_level */
  347.  
  348.       while( exp_esc > entry_level )
  349.          {
  350.          dec_esc();
  351.          }
  352.  
  353.       }
  354.  
  355.    /* no error; normal exit from function */
  356.  
  357.    else
  358.       {
  359.  
  360.       /* are any more operations needed? if we are still at entry level,
  361.          then they are not */
  362.  
  363.       /* try operations */
  364.  
  365.       exp_operation( entry_level );
  366.  
  367.       /* see what is on top of the stack */
  368.  
  369.       if ( exp_esc > ( entry_level + 1 ))
  370.          {
  371.          switch( exp_es[ exp_esc ].operation )
  372.             {
  373.             case OP_STRJOIN:
  374.                if ( exp_esc != ( entry_level + 2 ))
  375.                   {
  376.                   #if PROG_ERRORS
  377.                   sprintf( bwb_ebuf, "in bwb_exp(): OP_STRJOIN in wrong position." );
  378.                   bwb_error( bwb_ebuf );
  379.                   #else
  380.                   bwb_error( err_syntax );
  381.                   #endif
  382.                   }
  383.                break;
  384.             default:
  385.                #if PROG_ERRORS
  386.                sprintf( bwb_ebuf, "in bwb_exp(): incomplete expression." );
  387.                bwb_error( bwb_ebuf );
  388.                #else
  389.                bwb_error( err_syntax );
  390.                #endif
  391.                break;
  392.             }
  393.  
  394.          /* decrement the expression stack counter */
  395.  
  396.          #if INTENSIVE_DEBUG
  397.          sprintf( bwb_ebuf, "in bwb_exp(): before dec_esc type is <%c>",
  398.             exp_es[ exp_esc ].type );
  399.          bwb_debug( bwb_ebuf );
  400.          #endif
  401.  
  402.          dec_esc();
  403.  
  404.          }
  405.  
  406.       /* assign rvar to the variable for the current level */
  407.  
  408.       rval = &( exp_es[ exp_esc ] );
  409.  
  410.       /* decrement the expression stack counter */
  411.  
  412.       dec_esc();
  413.  
  414.       /* check the current level before exit */
  415.  
  416.       if ( entry_level != exp_esc )
  417.          {
  418.          #if PROG_ERRORS
  419.          sprintf( bwb_ebuf, "in bwb_exp(): exit stack level (%d) does not match entry stack level (%d)",
  420.             exp_esc, entry_level );
  421.          bwb_error( bwb_ebuf );
  422.          #else
  423.          bwb_error( err_overflow );
  424.          #endif
  425.          }
  426.  
  427.       }
  428.  
  429.    /* return a pointer to the last stack level */
  430.  
  431.    return rval;
  432.  
  433.    }
  434.  
  435. /***************************************************************
  436.  
  437.         FUNCTION:   exp_findop()
  438.  
  439.         DESCRIPTION:  This function reads the expression to find
  440.         what operation is required at its stack level.
  441.  
  442. ***************************************************************/
  443.  
  444. int
  445. exp_findop( char *expression )
  446.    {
  447.    char *pointer;                               /* pointer to start of string */
  448.    register int c;                              /* character counter */
  449.    int carry_on;                                /* boolean: control while loop */
  450.    int rval;                                    /* return value */
  451.    char tbuf[ MAXSTRINGSIZE + 1 ];
  452.  
  453.    #if INTENSIVE_DEBUG
  454.    sprintf( bwb_ebuf, "in exp_findop(): received <%s>", expression );
  455.    bwb_debug( bwb_ebuf );
  456.    #endif
  457.  
  458.    /* set return value to OP_NULL initially */
  459.  
  460.    rval = OP_NULL;
  461.  
  462.    /* assign local pointer to expression to begin reading */
  463.  
  464.    pointer = expression;
  465.  
  466.    /* advance to the first significant character */
  467.  
  468.    carry_on = TRUE;
  469.    while ( carry_on == TRUE )
  470.       {
  471.       switch( *pointer )
  472.          {
  473.          case ' ':                              /* whitespace */
  474.          case '\t':
  475.             ++pointer;                          /* increment the pointer */
  476.             break;                              /* and move on */
  477.          default:
  478.             carry_on = FALSE;                   /* break out of while loop */
  479.             break;
  480.          }
  481.       }
  482.  
  483.    /* we now have the first significant character and can begin parsing */
  484.  
  485.    /* check the first character for an indication of a parenthetical
  486.       expression, a string constant, or a numerical constant that begins
  487.       with a digit (numerical constants beginning with a plus or minus
  488.       sign or hex/octal/binary constants will have to be detected by
  489.       exp_isnc() */
  490.  
  491.    carry_on = TRUE;
  492.    switch ( *pointer )
  493.       {
  494.       case '\"':                /* this should indicate a string constant */
  495.          rval = CONST_STRING;
  496.          break;
  497.       case '(':                 /* this will indicate a simple parenthetical expression */
  498.          rval = PARENTHESIS;
  499.          break;
  500.       case ':':                 /* terminate processing */
  501.          rval = OP_TERMINATE;
  502.          break;
  503.       case '0':                 /* these will indicate a numerical constant */
  504.       case '1':
  505.       case '2':
  506.       case '3':
  507.       case '4':
  508.       case '5':
  509.       case '6':
  510.       case '7':
  511.       case '8':
  512.       case '9':
  513.       case '.':
  514.       case '&':                 /* designator for hex or octal constant */
  515.          rval = CONST_NUMERICAL;
  516.          break;
  517.       }
  518.  
  519.    #if INTENSIVE_DEBUG
  520.    sprintf( bwb_ebuf, "in exp_findop(): rval pos 1 is <%d>", rval );
  521.    bwb_debug( bwb_ebuf );
  522.    #endif
  523.  
  524.    /* string constants, numerical constants, open parentheses, and
  525.       the plus and minus operators have been checked at this point;
  526.       but if the return value is still OP_NULL, other possibilities
  527.       must be checked, namely, other operators, function names, and
  528.       variable names */
  529.  
  530.    /* get a character string to be interpreted */
  531.  
  532.    if ( rval == OP_NULL )
  533.       {
  534.  
  535.       carry_on = TRUE;
  536.       c = 0;
  537.       tbuf[ c ] = *pointer;
  538.       ++c;
  539.       tbuf[ c ] = '\0';
  540.       while( carry_on == TRUE )
  541.          {
  542.          switch( pointer[ c ] )
  543.             {
  544.             case ' ':                           /* whitespace */
  545.             case '\t':
  546.             case '(':
  547.             case ')':
  548.             case ',':
  549.             case ';':
  550.             case '\0':
  551.             case '\n':
  552.             case '\r':
  553.                carry_on = FALSE;
  554.                break;
  555.             default:
  556.                tbuf[ c ] = pointer[ c ];
  557.                ++c;
  558.                tbuf[ c ] = '\0';
  559.                break;
  560.             }
  561.          }
  562.  
  563.       }
  564.  
  565.    /* check for a BASIC command */
  566.  
  567.    if ( rval == OP_NULL )
  568.       {
  569.       rval = exp_iscmd( tbuf );
  570.       }
  571.  
  572.    /* check for numerical constant */
  573.  
  574.    if ( rval == OP_NULL )
  575.       {
  576.       rval = exp_isnc( tbuf );
  577.       }
  578.  
  579.    /* check for other operators */
  580.  
  581.    if ( rval == OP_NULL )
  582.       {
  583.       rval = exp_isop( tbuf );
  584.       }
  585.  
  586.    /* check for function name */
  587.  
  588.    if ( rval == OP_NULL )
  589.       {
  590.       rval = exp_isfn( tbuf );
  591.       }
  592.  
  593.    /* last: check for variable name, and assign it if there
  594.       is not already one */
  595.  
  596.    if ( rval == OP_NULL )
  597.       {
  598.       rval = exp_isvn( tbuf );
  599.       }
  600.  
  601.    /* return the value assigned (or OP_NULL if none assigned) */
  602.  
  603.    return rval;
  604.  
  605.    }
  606.  
  607. /***************************************************************
  608.  
  609.         FUNCTION:   exp_isnc()
  610.  
  611.         DESCRIPTION:  This function reads the expression to find
  612.         if a logical or mathematical operation is required at
  613.         this point.
  614.  
  615. ***************************************************************/
  616.  
  617. int
  618. exp_isnc( char *expression )
  619.    {
  620.  
  621.    switch( expression[ 0 ] )
  622.       {
  623.       case '0':                 /* these will indicate a numerical constant */
  624.       case '1':
  625.       case '2':
  626.       case '3':
  627.       case '4':
  628.       case '5':
  629.       case '6':
  630.       case '7':
  631.       case '8':
  632.       case '9':
  633.       case '&':                 /* indicator for hex or octal constant */
  634.          return CONST_NUMERICAL;
  635.       case '+':
  636.       case '-':
  637.  
  638.          /* if the previous stack level was a numerical value or a string,
  639.             then this is certainly not one; return OP_NULL here
  640.             and let the next function call to exp_isop() determine
  641.             the (plus or minus) operator */
  642.  
  643.          if (  ( exp_es[ exp_esc - 1 ].operation == NUMBER )
  644.             || ( exp_es[ exp_esc - 1 ].operation == VARIABLE )
  645.             || ( exp_es[ exp_esc - 1 ].operation == CONST_STRING ) )
  646.             {
  647.  
  648.             #if INTENSIVE_DEBUG
  649.             sprintf( bwb_ebuf, "in exp_isnc(): previous function is a number or string" );
  650.             bwb_debug( bwb_ebuf );
  651.             #endif
  652.  
  653.             return OP_NULL;
  654.             }
  655.  
  656.          /* similarly, if the previous stack level was a variable
  657.             with a numerical value (not a string), then this level
  658.             must be an operator, not a numerical constant */
  659.  
  660.          if ( ( exp_es[ exp_esc - 1 ].operation == VARIABLE )
  661.             && ( exp_es[ exp_esc - 1 ].type != STRING ))
  662.             {
  663.             return OP_NULL;
  664.             }
  665.  
  666.          /* failing these tests, the argument must be a numerical
  667.             constant preceded by a plus or minus sign */
  668.  
  669.          return CONST_NUMERICAL;
  670.  
  671.       default:
  672.          return OP_NULL;
  673.       }
  674.  
  675.    }
  676.  
  677. /***************************************************************
  678.  
  679.         FUNCTION:   exp_isop()
  680.  
  681.         DESCRIPTION:  This function reads the expression to find
  682.         if a logical or mathematical operation is required at
  683.         this point.
  684.  
  685.         This function presupposes that a numerical constant with
  686.         affixed plus or minus sign has been ruled out.
  687.  
  688. ***************************************************************/
  689.  
  690. int
  691. exp_isop( char *expression )
  692.    {
  693.    register int c;                              /* counter */
  694.    char tbuf[ MAXSTRINGSIZE + 1 ];
  695.  
  696.    /* first convert the expression to upper-case so that comparisons
  697.       will work */
  698.  
  699.    for ( c = 0; expression[ c ] != '\0'; ++c )
  700.       {
  701.       if ( islower( expression[ c ] ))
  702.          {
  703.          tbuf[ c ] = toupper( expression[ c ] );
  704.          }
  705.       else
  706.          {
  707.          tbuf[ c ] = expression[ c ];
  708.          }
  709.       tbuf[ c + 1 ] = '\0';
  710.       }
  711.  
  712.    #if INTENSIVE_DEBUG
  713.    sprintf( bwb_ebuf, "in exp_isop(): expression is <%s>", tbuf );
  714.    bwb_debug( bwb_ebuf );
  715.    #endif
  716.  
  717.    /* compare the initial characters of the string with the table
  718.       of operators */
  719.  
  720.    for ( c = 0; c < N_OPERATORS; ++c )
  721.       {
  722.       if ( strncmp( tbuf, exp_ops[ c ].symbol,
  723.          (size_t) strlen( exp_ops[ c ].symbol ) ) == 0 )
  724.          {
  725.  
  726.          #if INTENSIVE_DEBUG
  727.          sprintf( bwb_ebuf, "in exp_isop(): match <%s>, number <%d>.",
  728.             exp_ops[ c ].symbol, c );
  729.          bwb_debug( bwb_ebuf );
  730.          #endif
  731.  
  732.          return exp_ops[ c ].operation;
  733.          }
  734.       }
  735.  
  736.    /* search failed; return OP_NULL */
  737.  
  738.    return OP_NULL;
  739.  
  740.    }
  741.  
  742. /***************************************************************
  743.  
  744.         FUNCTION:   exp_iscmd()
  745.  
  746.         DESCRIPTION:  This function reads the expression to find
  747.         if a BASIC command name is present; if so, it returns
  748.         OP_TERMINATE to terminate expression parsing.  This is
  749.         critical, for example, in parsing a conditional following
  750.         IF where THEN, ELSE, and other BASIC commands may follow.
  751.  
  752. ***************************************************************/
  753.  
  754. int
  755. exp_iscmd( char *expression )
  756.    {
  757.    register int n;
  758.    char tbuf[ MAXSTRINGSIZE + 1 ];
  759.  
  760.    /* capitalize the expression */
  761.  
  762.    for ( n = 0; expression[ n ] != '\0'; ++n )
  763.       {
  764.       if ( n >= MAXARGSIZE )
  765.          {
  766.          #if PROG_ERRORS
  767.          sprintf( bwb_ebuf, "Maximum arguments size exceeded." );
  768.          bwb_error( bwb_ebuf );
  769.          #else
  770.          bwb_error( err_overflow );
  771.          #endif
  772.          }
  773.       if ( islower( expression[ n ] ) != FALSE )
  774.          {
  775.          tbuf[ n ] = toupper( expression[ n ] );
  776.          }
  777.       else
  778.          {
  779.          tbuf[ n ] = expression[ n ];
  780.          }
  781.       tbuf[ n + 1 ] = '\0';
  782.       }
  783.  
  784.    #if INTENSIVE_DEBUG
  785.    sprintf( bwb_ebuf, "in exp_iscmd(): expression received <%s>, converted <%s>.",
  786.       expression, tbuf );
  787.    bwb_debug( bwb_ebuf );
  788.    #endif
  789.  
  790.    /* first check for THEN or ELSE statements */
  791.  
  792.    if ( strcmp( tbuf, "THEN" ) == 0 )
  793.       {
  794.       #if INTENSIVE_DEBUG
  795.       sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
  796.          tbuf );
  797.       bwb_debug( bwb_ebuf );
  798.       #endif
  799.       return OP_TERMINATE;
  800.       }
  801.  
  802.    if ( strcmp( tbuf, "ELSE" ) == 0 )
  803.       {
  804.       #if INTENSIVE_DEBUG
  805.       sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
  806.          tbuf );
  807.       bwb_debug( bwb_ebuf );
  808.       #endif
  809.       return OP_TERMINATE;
  810.       }
  811.  
  812.    /* run through the command table and search for a match */
  813.  
  814.    for ( n = 0; n < COMMANDS; ++n )
  815.       {
  816.       if ( strcmp( tbuf, bwb_cmdtable[ n ].name ) == 0 )
  817.          {
  818.          #if INTENSIVE_DEBUG
  819.          sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
  820.             tbuf );
  821.          bwb_debug( bwb_ebuf );
  822.          #endif
  823.          return OP_TERMINATE;
  824.          }
  825.       #if INTENSIVE_DEBUG
  826.       else
  827.          {
  828.          sprintf( bwb_ebuf, "in exp_iscmd(): No match, <%s> and <%s>; returns %d",
  829.             tbuf, bwb_cmdtable[ n ].name,
  830.             strcmp( tbuf, bwb_cmdtable[ n ].name ) );
  831.          bwb_debug( bwb_ebuf );
  832.          }
  833.       #endif
  834.       }
  835.  
  836.    /* search failed, return NULL */
  837.  
  838.    return OP_NULL;
  839.  
  840.    }
  841.  
  842. /***************************************************************
  843.  
  844.         FUNCTION:   exp_isfn()
  845.  
  846.         DESCRIPTION:  This function reads the expression to find
  847.         if a function name is present at this point.
  848.  
  849. ***************************************************************/
  850.  
  851. int
  852. exp_isfn( char *expression )
  853.    {
  854.  
  855.    if ( fnc_find( expression ) == NULL )
  856.       {
  857.       #if INTENSIVE_DEBUG
  858.       sprintf( bwb_ebuf, "in exp_isfn(): failed to find function <%s>",
  859.          expression );
  860.       bwb_debug( bwb_ebuf );
  861.       #endif
  862.       return OP_NULL;
  863.       }
  864.    else
  865.       {
  866.       #if INTENSIVE_DEBUG
  867.       sprintf( bwb_ebuf, "in exp_isfn(): found function <%s>",
  868.          expression );
  869.       bwb_debug( bwb_ebuf );
  870.       #endif
  871.       return FUNCTION;
  872.       }
  873.  
  874.    }
  875.  
  876. /***************************************************************
  877.  
  878.         FUNCTION:   exp_isvn()
  879.  
  880.         DESCRIPTION:  This function reads the expression to find
  881.         if a variable name at this point.
  882.  
  883. ***************************************************************/
  884.  
  885. int
  886. exp_isvn( char *expression )
  887.    {
  888.  
  889.    exp_getvfname( expression, exp_es[ exp_esc ].string );
  890.  
  891.    if ( var_find( exp_es[ exp_esc ].string ) == NULL )
  892.       {
  893.       #if INTENSIVE_DEBUG
  894.       sprintf( bwb_ebuf, "in exp_isvn(): failed to find variable <%s>",
  895.          expression );
  896.       bwb_debug( bwb_ebuf );
  897.       #endif
  898.       return OP_NULL;
  899.       }
  900.    else
  901.       {
  902.       #if INTENSIVE_DEBUG
  903.       sprintf( bwb_ebuf, "in exp_isvn(): found variable <%s>",
  904.          exp_es[ exp_esc ].string );
  905.       bwb_debug( bwb_ebuf );
  906.       #endif
  907.       return VARIABLE;
  908.       }
  909.  
  910.    }
  911.  
  912. /***************************************************************
  913.  
  914.         FUNCTION:   exp_getvfname()
  915.  
  916.         DESCRIPTION:  This function reads the expression to find
  917.         a variable or function name at this point.
  918.  
  919. ***************************************************************/
  920.  
  921. int
  922. exp_getvfname( char *source, char *destination )
  923.    {
  924.    int s_pos, d_pos;                    /* source, destination positions */
  925.  
  926.    s_pos = d_pos = 0;
  927.    destination[ 0 ] = '\0';
  928.    while( source[ s_pos ] != '\0' )
  929.       {
  930.  
  931.       /* all aphabetical characters are acceptable */
  932.  
  933.       if ( isalpha( source[ s_pos ] ) != 0 )
  934.  
  935.          {
  936.          destination[ d_pos ] = source[ s_pos ];
  937.  
  938.          ++d_pos;
  939.          ++s_pos;
  940.          destination[ d_pos ] = '\0';
  941.          }
  942.  
  943.       /* numerical characters are acceptable but not in the first position */
  944.  
  945.       else if (( isdigit( source[ s_pos ] ) != 0 ) && ( d_pos != 0 ))
  946.          {
  947.          destination[ d_pos ] = source[ s_pos ];
  948.          ++d_pos;
  949.          ++s_pos;
  950.          destination[ d_pos ] = '\0';
  951.          }
  952.  
  953.       /* other characters will have to be tried on their own merits */
  954.  
  955.       else
  956.          {
  957.          switch( source[ s_pos ] )
  958.             {
  959.  
  960.             case '.':                           /* tolerated non-alphabetical characters */
  961.  
  962.             case '_':
  963.                destination[ d_pos ] = source[ s_pos ];
  964.                ++d_pos;
  965.                ++s_pos;
  966.                destination[ d_pos ] = '\0';
  967.                break;
  968.  
  969.             case STRING:                        /* terminating characters */
  970.             case SINGLE:
  971.             case DOUBLE:
  972.             case INTEGER:
  973.                destination[ d_pos ] = source[ s_pos ];
  974.                ++d_pos;
  975.                ++s_pos;
  976.                destination[ d_pos ] = '\0';
  977.  
  978.                return TRUE;
  979.             default:                            /* anything else is non-tolerated */
  980.                return FALSE;
  981.             }
  982.          }
  983.       }
  984.  
  985.    #if INTENSIVE_DEBUG
  986.    sprintf( bwb_ebuf, "in exp_getvfname(): found name <%s>", destination );
  987.    bwb_debug( bwb_ebuf );
  988.    #endif
  989.  
  990.    return TRUE;                         /* exit after coming to the end */
  991.  
  992.    }
  993.  
  994. /***************************************************************
  995.  
  996.         FUNCTION:   exp_validarg()
  997.  
  998.         DESCRIPTION:  This function reads the expression to
  999.         determine whether it is a valid argument (to be
  1000.         read recursively by bwb_exp() and passed to a
  1001.         function.
  1002.  
  1003. ***************************************************************/
  1004.  
  1005. int
  1006. exp_validarg( char *expression )
  1007.    {
  1008.    register int c;
  1009.  
  1010.    #if INTENSIVE_DEBUG
  1011.    sprintf( bwb_ebuf, "in exp_validarg(): expression <%s>.",
  1012.       expression );
  1013.    bwb_debug( bwb_ebuf );
  1014.    #endif
  1015.  
  1016.    c = 0;
  1017.    while ( TRUE )
  1018.       {
  1019.       switch( expression[ c ] )
  1020.          {
  1021.          case ' ':
  1022.          case '\t':
  1023.             ++c;
  1024.             break;
  1025.          case '\0':
  1026.             return FALSE;
  1027.          default:
  1028.             return TRUE;
  1029.          }
  1030.       }
  1031.  
  1032.    }
  1033.  
  1034. /***************************************************************
  1035.  
  1036.         FUNCTION:   exp_getdval()
  1037.  
  1038.         DESCRIPTION:
  1039.  
  1040. ***************************************************************/
  1041.  
  1042. double
  1043. exp_getdval( struct exp_ese *e )
  1044.    {
  1045.  
  1046.    /* check for variable */
  1047.  
  1048.    if ( e->operation == VARIABLE )
  1049.       {
  1050.       switch( e->type )
  1051.          {
  1052.          case DOUBLE:
  1053.             return (* var_finddval( e->xvar, e->array_pos ));
  1054.          case SINGLE:
  1055.             return (double) (* var_findfval( e->xvar, e->array_pos ));
  1056.          case INTEGER:
  1057.             return (double) (* var_findival( e->xvar, e->array_pos ));
  1058.          default:
  1059.             bwb_error( err_mismatch );
  1060.             return (double) 0.0;
  1061.          }
  1062.       }
  1063.  
  1064.    /* must be a numerical value */
  1065.  
  1066.    if ( e->operation != NUMBER )
  1067.       {
  1068.       #if PROG_ERRORS
  1069.       sprintf( bwb_ebuf, "in exp_getdval(): operation <%d> is not a number",
  1070.          e->operation );
  1071.       bwb_error( bwb_ebuf );
  1072.       #else
  1073.       bwb_error( err_syntax );
  1074.       #endif
  1075.       return (double) 0.0;
  1076.       }
  1077.  
  1078.    /* return specific values */
  1079.  
  1080.    switch( e->type )
  1081.       {
  1082.       case SINGLE:
  1083.          return (double) e->fval;
  1084.       case INTEGER:
  1085.          return (double) e->ival;
  1086.       case DOUBLE:
  1087.          return e->dval;
  1088.       default:
  1089.          #if PROG_ERRORS
  1090.          sprintf( bwb_ebuf, "in exp_getdval(): type is <%c>",
  1091.             e->type );
  1092.          bwb_error( bwb_ebuf );
  1093.          #else
  1094.          bwb_error( err_syntax );
  1095.          #endif
  1096.          return (double) 0.0;
  1097.       }
  1098.  
  1099.    }
  1100.  
  1101. /***************************************************************
  1102.  
  1103.         FUNCTION:   exp_getfval()
  1104.  
  1105.         DESCRIPTION:
  1106.  
  1107. ***************************************************************/
  1108.  
  1109. float
  1110. exp_getfval( struct exp_ese *e )
  1111.    {
  1112.  
  1113.    #if INTENSIVE_DEBUG
  1114.    sprintf( bwb_ebuf, "in exp_getfval(): entry" );
  1115.    bwb_debug( bwb_ebuf );
  1116.    #endif
  1117.  
  1118.    /* check for variable */
  1119.  
  1120.    if ( e->operation == VARIABLE )
  1121.       {
  1122.       #if INTENSIVE_DEBUG
  1123.       sprintf( bwb_ebuf, "in exp_getfval(): returning variable" );
  1124.       bwb_debug( bwb_ebuf );
  1125.       #endif
  1126.  
  1127.       switch( e->type )
  1128.          {
  1129.          case DOUBLE:
  1130.             return (float) (* var_finddval( e->xvar, e->array_pos ));
  1131.          case SINGLE:
  1132.             return (* var_findfval( e->xvar, e->array_pos ));
  1133.          case INTEGER:
  1134.             return (float) (* var_findival( e->xvar, e->array_pos ));
  1135.          default:
  1136.             bwb_error( err_mismatch );
  1137.             return (float) 0.0;
  1138.          }
  1139.       }
  1140.  
  1141.    /* must be a numerical value */
  1142.  
  1143.    if ( e->operation != NUMBER )
  1144.       {
  1145.       #if PROG_ERRORS
  1146.       sprintf( bwb_ebuf, "in exp_getfval(): operation <%d> is not a number",
  1147.          e->operation );
  1148.       bwb_error( bwb_ebuf );
  1149.       #else
  1150.       bwb_error( err_syntax );
  1151.       #endif
  1152.       return (float) 0.0;
  1153.       }
  1154.  
  1155.    /* return specific values */
  1156.  
  1157.    switch( e->type )
  1158.       {
  1159.       case SINGLE:
  1160.          #if INTENSIVE_DEBUG
  1161.          sprintf( bwb_ebuf, "in exp_getfval(): returning from SINGLE, val <%f>",
  1162.             e->fval );
  1163.          bwb_debug( bwb_ebuf );
  1164.          #endif
  1165.          return e->fval;
  1166.       case INTEGER:
  1167.          #if INTENSIVE_DEBUG
  1168.          sprintf( bwb_ebuf, "in exp_getfval(): returning from INTEGER, val <%d>",
  1169.             e->ival );
  1170.          bwb_debug( bwb_ebuf );
  1171.          #endif
  1172.          return (float) e->ival;
  1173.       case DOUBLE:
  1174.          #if INTENSIVE_DEBUG
  1175.          sprintf( bwb_ebuf, "in exp_getfval(): returning from DOUBLE, val <%lf>",
  1176.             e->dval );
  1177.          bwb_debug( bwb_ebuf );
  1178.          #endif
  1179.          return (float) e->dval;
  1180.       default:
  1181.          #if PROG_ERRORS
  1182.          sprintf( bwb_ebuf, "in exp_getfval(): type is <%c>",
  1183.             e->type );
  1184.          bwb_error( bwb_ebuf );
  1185.          #else
  1186.          bwb_error( err_syntax );
  1187.          #endif
  1188.          return (float) 0.0;
  1189.       }
  1190.  
  1191.    }
  1192.  
  1193. /***************************************************************
  1194.  
  1195.         FUNCTION:   exp_getival()
  1196.  
  1197.         DESCRIPTION:
  1198.  
  1199. ***************************************************************/
  1200.  
  1201. int
  1202. exp_getival( struct exp_ese *e )
  1203.    {
  1204.  
  1205.    /* check for variable */
  1206.  
  1207.    if ( e->operation == VARIABLE )
  1208.       {
  1209.       switch( e->type )
  1210.          {
  1211.          case DOUBLE:
  1212.             return (int) (* var_finddval( e->xvar, e->array_pos ));
  1213.          case SINGLE:
  1214.             return (int) (* var_findfval( e->xvar, e->array_pos ));
  1215.          case INTEGER:
  1216.             return (* var_findival( e->xvar, e->array_pos ));
  1217.          default:
  1218.             bwb_error( err_mismatch );
  1219.             return 0;
  1220.          }
  1221.       }
  1222.  
  1223.    /* must be a numerical value */
  1224.  
  1225.    if ( e->operation != NUMBER )
  1226.       {
  1227.       #if PROG_ERRORS
  1228.       sprintf( bwb_ebuf, "in exp_getival(): operation <%d> is not a number",
  1229.          e->operation );
  1230.       bwb_error( bwb_ebuf );
  1231.       #else
  1232.       bwb_error( err_syntax );
  1233.       #endif
  1234.       return 0;
  1235.       }
  1236.  
  1237.    /* return specific values */
  1238.  
  1239.    switch( e->type )
  1240.       {
  1241.       case SINGLE:
  1242.          return (int) e->fval;
  1243.       case INTEGER:
  1244.          return e->ival;
  1245.       case DOUBLE:
  1246.          return (int) e->dval;
  1247.       default:
  1248.          #if PROG_ERRORS
  1249.          sprintf( bwb_ebuf, "in exp_getival(): type is <%c>",
  1250.             e->type );
  1251.          bwb_error( bwb_ebuf );
  1252.          #else
  1253.          bwb_error( err_syntax );
  1254.          #endif
  1255.          return 0;
  1256.       }
  1257.  
  1258.    }
  1259.  
  1260. /***************************************************************
  1261.  
  1262.         FUNCTION:   exp_getsval()
  1263.  
  1264.         DESCRIPTION:
  1265.  
  1266. ***************************************************************/
  1267.  
  1268. bstring *
  1269. exp_getsval( struct exp_ese *e )
  1270.    {
  1271.    static bstring b;
  1272.    #if TEST_BSTRING
  1273.    static int init = FALSE;
  1274.  
  1275.    if ( init == FALSE )
  1276.       {
  1277.       sprintf( b.name, "<exp_getsval() bstring>" );
  1278.       }
  1279.    #endif
  1280.  
  1281.    b.rab = FALSE;
  1282.  
  1283.    /* return based on operation type */
  1284.  
  1285.    switch( e->operation )
  1286.       {
  1287.       case CONST_STRING:
  1288.       case OP_STRJOIN:
  1289.          return &( e->sval );
  1290.       case VARIABLE:
  1291.         switch( e->type )
  1292.             {
  1293.         case STRING:
  1294.                return var_findsval( e->xvar, e->array_pos );
  1295.             case DOUBLE:
  1296.                sprintf( bwb_ebuf, "%lf ", exp_getdval( e ) );
  1297.                str_ctob( &b, bwb_ebuf );
  1298.                return &b;
  1299.             case SINGLE:
  1300.                sprintf( bwb_ebuf, "%f ", exp_getfval( e ) );
  1301.                str_ctob( &b, bwb_ebuf );
  1302.                return &b;
  1303.             case INTEGER:
  1304.                sprintf( bwb_ebuf, "%d ", exp_getival( e ) );
  1305.                str_ctob( &b, bwb_ebuf );
  1306.                return &b;
  1307.             default:
  1308.                #if PROG_ERRORS
  1309.                sprintf( bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
  1310.                   e->type );
  1311.                bwb_error( bwb_ebuf );
  1312.                #else
  1313.                bwb_error( err_syntax );
  1314.                #endif
  1315.                return NULL;
  1316.             }
  1317.      break;
  1318.  
  1319.       case NUMBER:
  1320.         switch( e->type )
  1321.             {
  1322.         case DOUBLE:
  1323.                sprintf( bwb_ebuf, "%lf ", exp_getdval( e ) );
  1324.                str_ctob( &b, bwb_ebuf );
  1325.                return &b;
  1326.             case SINGLE:
  1327.                sprintf( bwb_ebuf, "%f ", exp_getfval( e ) );
  1328.                str_ctob( &b, bwb_ebuf );
  1329.                return &b;
  1330.             case INTEGER:
  1331.                sprintf( bwb_ebuf, "%d ", exp_getival( e ) );
  1332.                str_ctob( &b, bwb_ebuf );
  1333.                return &b;
  1334.             default:
  1335.                #if PROG_ERRORS
  1336.                sprintf( bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
  1337.                   e->type );
  1338.                bwb_error( bwb_ebuf );
  1339.                #else
  1340.                bwb_error( err_syntax );
  1341.                #endif
  1342.                return NULL;
  1343.             }
  1344.      break;
  1345.       default:
  1346.          #if PROG_ERRORS
  1347.          sprintf( bwb_ebuf, "in exp_getsval(): operation <%d> inappropriate",
  1348.             e->operation );
  1349.          bwb_error( bwb_ebuf );
  1350.          #else
  1351.          bwb_error( err_syntax );
  1352.          #endif
  1353.          return NULL;
  1354.       }
  1355.  
  1356.    /* this point may not be reached */
  1357.  
  1358.    return NULL;
  1359.  
  1360.    }
  1361.  
  1362. /***************************************************************
  1363.  
  1364.         FUNCTION:   exp_findfval()
  1365.  
  1366.         DESCRIPTION:
  1367.  
  1368. ***************************************************************/
  1369.  
  1370. #ifdef NO_LONGER_IMPLEMENTED
  1371. float *
  1372. exp_findfval( struct exp_ese *e )
  1373.    {
  1374.  
  1375.    #if INTENSIVE_DEBUG
  1376.    sprintf( bwb_ebuf, "in exp_findfval(): entry" );
  1377.    bwb_debug( bwb_ebuf );
  1378.    #endif
  1379.  
  1380.    /* check for variable */
  1381.  
  1382.    if ( e->operation == VARIABLE )
  1383.       {
  1384.       #if INTENSIVE_DEBUG
  1385.       sprintf( bwb_ebuf, "in exp_getfval(): returning variable" );
  1386.       bwb_debug( bwb_ebuf );
  1387.       #endif
  1388.       return var_findfval( e->xvar, e->xvar->array_pos );
  1389.       }
  1390.  
  1391.    /* must be a numerical value */
  1392.  
  1393.    if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
  1394.       {
  1395.       #if PROG_ERRORS
  1396.       sprintf( bwb_ebuf, "in exp_findfval(): operation is not a single-precision number" );
  1397.       bwb_error( bwb_ebuf );
  1398.       #else
  1399.       bwb_error( err_syntax );
  1400.       #endif
  1401.       return NULL;
  1402.       }
  1403.  
  1404.    /* return specific value */
  1405.  
  1406.    return &( e->fval );
  1407.  
  1408.    }
  1409.  
  1410. /***************************************************************
  1411.  
  1412.         FUNCTION:   exp_finddval()
  1413.  
  1414.         DESCRIPTION:
  1415.  
  1416. ***************************************************************/
  1417.  
  1418. double *
  1419. exp_finddval( struct exp_ese *e )
  1420.    {
  1421.  
  1422.    #if INTENSIVE_DEBUG
  1423.    sprintf( bwb_ebuf, "in exp_finddval(): entry" );
  1424.    bwb_debug( bwb_ebuf );
  1425.    #endif
  1426.  
  1427.    /* check for variable */
  1428.  
  1429.    if ( e->operation == VARIABLE )
  1430.       {
  1431.       #if INTENSIVE_DEBUG
  1432.       sprintf( bwb_ebuf, "in exp_getdval(): returning variable" );
  1433.       bwb_debug( bwb_ebuf );
  1434.       #endif
  1435.       return var_finddval( e->xvar, e->xvar->array_pos );
  1436.       }
  1437.  
  1438.    /* must be a numerical value */
  1439.  
  1440.    if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
  1441.       {
  1442.       #if PROG_ERRORS
  1443.       sprintf( bwb_ebuf, "in exp_finddval(): operation is not a double-precision number" );
  1444.       bwb_error( bwb_ebuf );
  1445.       #else
  1446.       bwb_error( err_syntax );
  1447.       #endif
  1448.       return NULL;
  1449.       }
  1450.  
  1451.    /* return specific value */
  1452.  
  1453.    return &( e->dval );
  1454.  
  1455.    }
  1456.  
  1457. /***************************************************************
  1458.  
  1459.         FUNCTION:   exp_findival()
  1460.  
  1461.         DESCRIPTION:
  1462.  
  1463. ***************************************************************/
  1464.  
  1465. int *
  1466. exp_findival( struct exp_ese *e )
  1467.    {
  1468.  
  1469.    #if INTENSIVE_DEBUG
  1470.    sprintf( bwb_ebuf, "in exp_findival(): entry" );
  1471.    bwb_debug( bwb_ebuf );
  1472.    #endif
  1473.  
  1474.    /* check for variable */
  1475.  
  1476.    if ( e->operation == VARIABLE )
  1477.       {
  1478.       #if INTENSIVE_DEBUG
  1479.       sprintf( bwb_ebuf, "in exp_getival(): returning variable" );
  1480.       bwb_debug( bwb_ebuf );
  1481.       #endif
  1482.       return var_findival( e->xvar, e->xvar->array_pos );
  1483.       }
  1484.  
  1485.    /* must be a numerical value */
  1486.  
  1487.    if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
  1488.       {
  1489.       #if PROG_ERRORS
  1490.       sprintf( bwb_ebuf, "in exp_findival(): operation is not an integer number" );
  1491.       bwb_error( bwb_ebuf );
  1492.       #else
  1493.       bwb_error( err_syntax );
  1494.       #endif
  1495.       return NULL;
  1496.       }
  1497.  
  1498.    /* return specific value */
  1499.  
  1500.    return &( e->ival );
  1501.  
  1502.    }
  1503. #endif
  1504.  
  1505. /***************************************************************
  1506.  
  1507.         FUNCTION:   inc_esc()
  1508.  
  1509.         DESCRIPTION:  This function increments the expression
  1510.         stack counter.
  1511.  
  1512. ***************************************************************/
  1513.  
  1514. int
  1515. inc_esc( void )
  1516.    {
  1517.  
  1518.    #if INTENSIVE_DEBUG
  1519.    sprintf( bwb_ebuf, "in inc_esc(): prev level <%d>",
  1520.       exp_esc );
  1521.    bwb_debug ( bwb_ebuf );
  1522.    #endif
  1523.  
  1524.    ++exp_esc;
  1525.    if ( exp_esc >= ESTACKSIZE )
  1526.       {
  1527.       --exp_esc;
  1528.       #if PROG_ERRORS
  1529.       sprintf( bwb_ebuf, "in inc_esc(): Maximum expression stack exceeded <%d>",
  1530.          exp_esc );
  1531.       bwb_error( bwb_ebuf );
  1532.       #else
  1533.       bwb_error( err_overflow );
  1534.       #endif
  1535.       return OP_NULL;
  1536.       }
  1537.  
  1538.    #if INTENSIVE_DEBUG
  1539.    sprintf( exp_es[ exp_esc ].string, "New Expression Stack Level %d", exp_esc );
  1540.    #endif
  1541.  
  1542.    exp_es[ exp_esc ].type = INTEGER;
  1543.    exp_es[ exp_esc ].operation = OP_NULL;
  1544.    exp_es[ exp_esc ].pos_adv = 0;
  1545.  
  1546.    return TRUE;
  1547.    }
  1548.  
  1549. /***************************************************************
  1550.  
  1551.         FUNCTION:   dec_esc()
  1552.  
  1553.         DESCRIPTION:  This function decrements the expression
  1554.         stack counter.
  1555.  
  1556. ***************************************************************/
  1557.  
  1558. int
  1559. dec_esc( void )
  1560.    {
  1561.    --exp_esc;
  1562.    if ( exp_esc < 0 )
  1563.       {
  1564.       exp_esc = 0;
  1565.       #if PROG_ERRORS
  1566.       sprintf( bwb_ebuf, "in dec_esc(): Expression stack counter < 0." );
  1567.       bwb_error( bwb_ebuf );
  1568.       #else
  1569.       bwb_error( err_overflow );
  1570.       #endif
  1571.       return OP_NULL;
  1572.       }
  1573.  
  1574.    return TRUE;
  1575.    }
  1576.