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_exp.c < prev    next >
Text File  |  1996-10-10  |  36KB  |  1,468 lines

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