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_elx.c < prev    next >
Text File  |  1993-11-09  |  36KB  |  1,191 lines

  1. /****************************************************************
  2.  
  3.         bwb_elx.c       Parse Elements of Expressions
  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:       exp_paren()
  36.  
  37.     DESCRIPTION:    This function interprets a parenthetical
  38.             expression, calling bwb_exp() (recursively)
  39.             to resolve the internal expression.
  40.  
  41. ***************************************************************/
  42.  
  43. #if ANSI_C
  44. int
  45. exp_paren( char *expression )
  46. #else
  47. int
  48. exp_paren( expression )
  49.    char *expression;
  50. #endif
  51.    {
  52.    struct exp_ese *e;
  53.    int s_pos;                           /* position in build buffer */
  54.    int loop;
  55.    int paren_level;
  56.  
  57.    /* find a string enclosed by parentheses */
  58.  
  59.    CURTASK exps[ CURTASK expsc ].pos_adv = 1;       /* start beyond open paren */
  60.    s_pos = 0;
  61.    loop = TRUE;
  62.    paren_level = 1;
  63.    CURTASK exps[ CURTASK expsc ].string[ 0 ] = '¥0';
  64.  
  65.    while( loop == TRUE )
  66.       {
  67.  
  68.       /* check the current character */
  69.  
  70.       switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  71.          {
  72.  
  73.          case '¥r':                /* these tests added v1.11 */
  74.          case '¥n':
  75.          case '¥0':
  76.             bwb_error( err_incomplete );
  77.             loop = FALSE;
  78.             break;
  79.  
  80.          case '(':
  81.             ++paren_level;
  82.             CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  83.                = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  84.             ++s_pos;
  85.             CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  86.             break;
  87.  
  88.          case ')':
  89.  
  90.             --paren_level;
  91.             if ( paren_level == 0 )
  92.                {
  93.                loop = FALSE;
  94.                }
  95.             else
  96.                {
  97.                CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  98.                   = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  99.                ++s_pos;
  100.                CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  101.                }
  102.             break;
  103.  
  104.          case '¥"':                             /* embedded string constant */
  105.             ++CURTASK exps[ CURTASK expsc ].pos_adv;
  106.             while ( ( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] != '¥"' )
  107.                && ( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] != '¥0' ) )
  108.                {
  109.                CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  110.                   = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  111.                ++s_pos;
  112.                CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  113.                ++CURTASK exps[ CURTASK expsc ].pos_adv;
  114.                }
  115.             break;
  116.  
  117.          default:
  118.             CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  119.                = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  120.             ++s_pos;
  121.             CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  122.             break;
  123.          }
  124.  
  125.       /* advance the counter */
  126.  
  127.       ++CURTASK exps[ CURTASK expsc ].pos_adv;
  128.  
  129.       }
  130.  
  131. #if INTENSIVE_DEBUG
  132.    sprintf( bwb_ebuf, "in exp_paren() found internal string <%s>",
  133.       CURTASK exps[ CURTASK expsc ].string );
  134.    bwb_debug( bwb_ebuf );
  135. #endif
  136.  
  137.    /* call bwb_exp() recursively to interpret this expression */
  138.  
  139.    CURTASK exps[ CURTASK expsc ].rec_pos = 0;
  140.    e = bwb_exp( CURTASK exps[ CURTASK expsc ].string, FALSE,
  141.           &( CURTASK exps[ CURTASK expsc ].rec_pos ) );
  142.  
  143.    /* assign operation and value at this level */
  144.  
  145.    CURTASK exps[ CURTASK expsc ].type = e->type;
  146.  
  147.    switch ( e->type )
  148.       {
  149.       case STRING:
  150.          CURTASK exps[ CURTASK expsc ].operation = CONST_STRING;
  151.          str_btob( exp_getsval( &( CURTASK exps[ CURTASK expsc ] )), exp_getsval( e ) );
  152.          break;
  153.       default:
  154.          CURTASK exps[ CURTASK expsc ].operation = NUMBER;
  155.          CURTASK exps[ CURTASK expsc ].nval = exp_getnval( e );
  156.          break;
  157.       }
  158.  
  159.    return TRUE;
  160.  
  161.    }
  162.  
  163. /***************************************************************
  164.  
  165.         FUNCTION:       exp_strconst()
  166.  
  167.         DESCRIPTION:    This function interprets a string
  168.             constant.
  169.  
  170. ***************************************************************/
  171.  
  172. #if ANSI_C
  173. int
  174. exp_strconst( char *expression )
  175. #else
  176. int
  177. exp_strconst( expression )
  178.    char *expression;
  179. #endif
  180.    {
  181.    int e_pos, s_pos;
  182.  
  183.    /* assign values to structure */
  184.  
  185.    CURTASK exps[ CURTASK expsc ].type = STRING;
  186.    CURTASK exps[ CURTASK expsc ].operation = CONST_STRING;
  187.  
  188.    /* set counters */
  189.  
  190.    s_pos = 0;
  191.    CURTASK exps[ CURTASK expsc ].pos_adv = e_pos = 1;
  192.    CURTASK exps[ CURTASK expsc ].string[ 0 ] = '¥0';
  193.  
  194.    /* read the string up until the next double quotation mark */
  195.  
  196.    while( expression[ e_pos ] != '¥"' )
  197.       {
  198.       CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ e_pos ];
  199.       ++e_pos;
  200.       ++s_pos;
  201.       ++CURTASK exps[ CURTASK expsc ].pos_adv;
  202.       CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  203.       if ( s_pos >= ( MAXSTRINGSIZE - 1 ) )
  204.          {
  205. #if PROG_ERRORS
  206.          sprintf( bwb_ebuf, "string <%s> exceeds maximum size (%d) for string constant.",
  207.             expression, MAXSTRINGSIZE );
  208.          bwb_error( bwb_ebuf );
  209. #else
  210.          bwb_error( err_overflow );
  211. #endif
  212.          return OP_NULL;
  213.          }
  214.       }
  215.  
  216.    /* now write string over to bstring */
  217.  
  218.    str_ctob( &( CURTASK exps[ CURTASK expsc ].sval ), CURTASK exps[ CURTASK expsc ].string );
  219.  
  220.    /* advance past last double quotation mark */
  221.  
  222.    ++CURTASK exps[ CURTASK expsc ].pos_adv;
  223.  
  224.    /* return */
  225.  
  226.    return TRUE;
  227.  
  228.    }
  229.  
  230. /***************************************************************
  231.  
  232.         FUNCTION:    exp_numconst()
  233.  
  234.         DESCRIPTION:    This function interprets a numerical
  235.             constant.
  236.  
  237. ***************************************************************/
  238.  
  239. #if ANSI_C
  240. int
  241. exp_numconst( char *expression )
  242. #else
  243. int
  244. exp_numconst( expression )
  245.    char *expression;
  246. #endif
  247.    {
  248.    int base;                            /* numerical base for the constant */
  249.    static struct bwb_variable mantissa; /* mantissa of floating-point number */
  250.    static int init = FALSE;        /* is mantissa variable initialized? */
  251.    int exponent;                        /* exponent for floating point number */
  252.    int man_start;                       /* starting point of mantissa */
  253.    int s_pos;                           /* position in build string */
  254.    int build_loop;
  255.    int need_pm;
  256.    int i;
  257.    bnumber d;
  258. #if CHECK_RECURSION
  259.    static int in_use = FALSE;                   /* boolean: is function in use? */
  260.  
  261.    /* check recursion status */
  262.  
  263.    if ( in_use == TRUE )
  264.       {
  265.       sprintf( bwb_ebuf, "Recursion error in bwb_exp.c:exp_findop(): recursion violation." );
  266.       bwb_error( bwb_ebuf );
  267.       }
  268.  
  269.    /* reset recursion status indicator */
  270.  
  271.    else
  272.       {
  273.       in_use = TRUE;
  274.       }
  275. #endif
  276.  
  277.    /* initialize the variable if necessary */
  278.  
  279. #if INTENSIVE_DEBUG
  280.    strcpy( mantissa.name, "(mantissa)" );
  281. #endif
  282.  
  283.    if ( init == FALSE )
  284.       {
  285.       init = TRUE;
  286.       var_make( &mantissa, NUMBER );
  287.       }
  288.  
  289.    /* be sure that the array_pos[ 0 ] for mantissa is set to dim_base;
  290.       this is necessary because mantissa might be used before dim_base
  291.       is set */
  292.  
  293.    mantissa.array_pos[ 0 ] = dim_base;
  294.  
  295. #if INTENSIVE_DEBUG
  296.    sprintf( bwb_ebuf, "in exp_numconst(): received <%s>, eval <%c>",
  297.       expression, expression[ 0 ] );
  298.    bwb_debug( bwb_ebuf );
  299. #endif
  300.  
  301.    need_pm = FALSE;
  302.    CURTASK exps[ CURTASK expsc ].nval = (bnumber) 0;
  303.  
  304.    /* check the first character(s) to determine numerical base
  305.       and starting point of the mantissa */
  306.  
  307.    switch( expression[ 0 ] )
  308.       {
  309.       case '-':
  310.       case '+':
  311.       case '0':
  312.       case '1':
  313.       case '2':
  314.       case '3':
  315.       case '4':
  316.       case '5':
  317.       case '6':
  318.       case '7':
  319.       case '8':
  320.       case '9':
  321.       case '.':
  322.          base = 10;                     /* decimal constant */
  323.      man_start = 0;                 /* starts at position 0 */
  324.      need_pm = FALSE;
  325.          break;
  326.       case '&':                         /* hex or octal constant */
  327.          if ( ( expression[ 1 ] == 'H' ) || ( expression[ 1 ] == 'h' ))
  328.             {
  329.             base = 16;                  /* hexadecimal constant */
  330.             man_start = 2;              /* starts at position 2 */
  331.             }
  332.          else
  333.             {
  334.             base = 8;                   /* octal constant */
  335.             if ( ( expression[ 1 ] == 'O' ) || ( expression[ 1 ] == 'o' ))
  336.                {
  337.                man_start = 2;           /* starts at position 2 */
  338.                }
  339.             else
  340.                {
  341.                man_start = 1;           /* starts at position 1 */
  342.                }
  343.             }
  344.          break;
  345.       default:
  346.  
  347. #if PROG_ERRORS
  348.          sprintf( bwb_ebuf, "expression <%s> is not a numerical constant.",
  349.             expression );
  350.          bwb_error( bwb_ebuf );
  351. #else
  352.          bwb_error( err_syntax );
  353. #endif
  354.          return OP_NULL;
  355.       }
  356.  
  357.    /* now build the mantissa according to the numerical base */
  358.  
  359.    switch( base )
  360.       {
  361.  
  362.       case 10:                          /* decimal constant */
  363.  
  364.          /* initialize counters */
  365.  
  366.          CURTASK exps[ CURTASK expsc ].pos_adv = man_start;
  367.          CURTASK exps[ CURTASK expsc ].type = NUMBER;
  368.          CURTASK exps[ CURTASK expsc ].string[ 0 ] = '¥0';
  369.          s_pos = 0;
  370.          exponent = OP_NULL;
  371.          build_loop = TRUE;
  372.  
  373.          /* loop to build the string */
  374.  
  375.          while ( build_loop == TRUE )
  376.             {
  377.             switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  378.                {
  379.                case '-':                        /* prefixed plus or minus */
  380.                case '+':
  381.  
  382.                   /* in the first position, a plus or minus sign can
  383.                      be added to the beginning of the string to be
  384.                      scanned */
  385.  
  386.                   if ( CURTASK exps[ CURTASK expsc ].pos_adv == man_start )
  387.                      {
  388.                      CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  389.                      ++CURTASK exps[ CURTASK expsc ].pos_adv;  /* advance to next character */
  390.                      ++s_pos;
  391.                      CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  392.                      }
  393.  
  394.                   /* but in any other position, the plus or minus sign
  395.                      must be taken as an operator and thus as terminating
  396.                      the string to be scanned */
  397.  
  398.                   else
  399.                      {
  400.                      build_loop = FALSE;
  401.                      }
  402.                   break;
  403.                case '.':                        /* note at least single precision */
  404.                case '0':                        /* or ordinary digit */
  405.                case '1':
  406.                case '2':
  407.                case '3':
  408.                case '4':
  409.                case '5':
  410.                case '6':
  411.                case '7':
  412.                case '8':
  413.                case '9':
  414.                   CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  415.                   ++CURTASK exps[ CURTASK expsc ].pos_adv;  /* advance to next character */
  416.                   ++s_pos;
  417.                   CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  418.                   break;
  419.  
  420.            case '#':                        /* Microsoft-type precision indicator; ignored but terminates */
  421.            case '!':                        /* Microsoft-type precision indicator; ignored but terminates */
  422.           ++CURTASK exps[ CURTASK expsc ].pos_adv;  /* advance to next character */
  423.           CURTASK exps[ CURTASK expsc ].type = NUMBER;
  424.           exponent = FALSE;
  425.           build_loop = FALSE;
  426.           break;
  427.  
  428.            case 'E':                        /* exponential, single precision */
  429.                case 'e':
  430.                   ++CURTASK exps[ CURTASK expsc ].pos_adv;  /* advance to next character */
  431.                   CURTASK exps[ CURTASK expsc ].type = NUMBER;
  432.           exponent = TRUE;
  433.                   build_loop = FALSE;
  434.           break;
  435.  
  436.                case 'D':                        /* exponential, double precision */
  437.                case 'd':
  438.                   ++CURTASK exps[ CURTASK expsc ].pos_adv;  /* advance to next character */
  439.                   CURTASK exps[ CURTASK expsc ].type = NUMBER;
  440.           exponent = TRUE;
  441.                   build_loop = FALSE;
  442.                   break;
  443.  
  444.                default:                         /* anything else, terminate */
  445.                   build_loop = FALSE;
  446.                   break;
  447.                }
  448.  
  449.             }
  450.  
  451.          /* assign the value to the mantissa variable */
  452.          
  453. #if NUMBER_DOUBLE
  454.          sscanf( CURTASK exps[ CURTASK expsc ].string, "%lf", 
  455.            var_findnval( &mantissa, mantissa.array_pos ));
  456. #else
  457.          sscanf( CURTASK exps[ CURTASK expsc ].string, "%f", 
  458.            var_findnval( &mantissa, mantissa.array_pos ));
  459. #endif
  460.  
  461. #if INTENSIVE_DEBUG
  462.          sprintf( bwb_ebuf, "in exp_numconst(): read mantissa, string <%s> val <%lf>",
  463.             CURTASK exps[ CURTASK expsc ].string, var_getnval( &mantissa ) );
  464.          bwb_debug( bwb_ebuf );
  465. #endif
  466.  
  467.          /* test if integer bounds have been exceeded */
  468.  
  469.          if ( CURTASK exps[ CURTASK expsc ].type == NUMBER )
  470.             {
  471.             i = (int) var_getnval( &mantissa );
  472.             d = (bnumber) i;
  473.             if ( d != var_getnval( &mantissa ))
  474.                {
  475.                CURTASK exps[ CURTASK expsc ].type = NUMBER;
  476. #if INTENSIVE_DEBUG
  477.                sprintf( bwb_ebuf, "in exp_numconst(): integer bounds violated, promote to NUMBER" );
  478.                bwb_debug( bwb_ebuf );
  479. #endif               
  480.                }
  481.             }
  482.  
  483.          /* read the exponent if there is one */
  484.  
  485.          if ( exponent == TRUE )
  486.             {
  487.  
  488.         /* allow a plus or minus once at the beginning */
  489.  
  490.         need_pm = TRUE;
  491.  
  492.         /* initialize counters */
  493.  
  494.             CURTASK exps[ CURTASK expsc ].string[ 0 ] = '¥0';
  495.             s_pos = 0;
  496.             build_loop = TRUE;
  497.  
  498.             /* loop to build the string */
  499.  
  500.             while ( build_loop == TRUE )
  501.                {
  502.                switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  503.                   {
  504.           case '-':                        /* prefixed plus or minus */
  505.                   case '+':
  506.  
  507.              if ( need_pm == TRUE )        /* only allow once */
  508.             {
  509.             CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  510.             ++CURTASK exps[ CURTASK expsc ].pos_adv;  /* advance to next character */
  511.             ++s_pos;
  512.             CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  513.             }
  514.              else
  515.             {
  516.             build_loop = FALSE;
  517.             }
  518.              break;
  519.  
  520.           case '0':                        /* or ordinary digit */
  521.                   case '1':
  522.                   case '2':
  523.                   case '3':
  524.                   case '4':
  525.                   case '5':
  526.                   case '6':
  527.                   case '7':
  528.                   case '8':
  529.                   case '9':
  530.  
  531.                      CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  532.                      ++CURTASK exps[ CURTASK expsc ].pos_adv;  /* advance to next character */
  533.                      ++s_pos;
  534.              CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  535.              need_pm = FALSE;
  536.                      break;
  537.  
  538.                   default:                         /* anything else, terminate */
  539.                      build_loop = FALSE;
  540.                      break;
  541.                   }
  542.  
  543.                }                                /* end of build loop for exponent */
  544.  
  545.             /* assign the value to the user variable */
  546.  
  547. #if NUMBER_DOUBLE
  548.             sscanf( CURTASK exps[ CURTASK expsc ].string, "%lf",
  549.                &( CURTASK exps[ CURTASK expsc ].nval ) );
  550. #else
  551.             sscanf( CURTASK exps[ CURTASK expsc ].string, "%f",
  552.                &( CURTASK exps[ CURTASK expsc ].nval ) );
  553. #endif
  554.  
  555. #if INTENSIVE_DEBUG
  556.         sprintf( bwb_ebuf, "in exp_numconst(): exponent is <%d>",
  557.                (int) CURTASK exps[ CURTASK expsc ].nval );
  558.             bwb_debug( bwb_ebuf );
  559. #endif
  560.  
  561.             }                           /* end of exponent search */
  562.  
  563.          if ( CURTASK exps[ CURTASK expsc ].nval == (bnumber) 0 )
  564.             {
  565.             CURTASK exps[ CURTASK expsc ].nval = var_getnval( &mantissa );
  566.             }
  567.          else
  568.             {
  569.             CURTASK exps[ CURTASK expsc ].nval = var_getnval( &mantissa )
  570.                * pow( (bnumber) 10.0, (bnumber) CURTASK exps[ CURTASK expsc ].nval );
  571.             }
  572.  
  573.          break;
  574.  
  575.       case 8:                           /* octal constant */
  576.  
  577.          /* initialize counters */
  578.  
  579.          CURTASK exps[ CURTASK expsc ].pos_adv = man_start;
  580.          CURTASK exps[ CURTASK expsc ].type = NUMBER;
  581.          CURTASK exps[ CURTASK expsc ].string[ 0 ] = '¥0';
  582.          s_pos = 0;
  583.          exponent = OP_NULL;
  584.          build_loop = TRUE;
  585.  
  586.          /* loop to build the string */
  587.  
  588.          while ( build_loop == TRUE )
  589.             {
  590.             switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  591.                {
  592.                case '0':                        /* or ordinary digit */
  593.                case '1':
  594.                case '2':
  595.                case '3':
  596.                case '4':
  597.                case '5':
  598.                case '6':
  599.                case '7':
  600.                   CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  601.                   ++CURTASK exps[ CURTASK expsc ].pos_adv;  /* advance to next character */
  602.                   ++s_pos;
  603.                   CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  604.                   break;
  605.  
  606.                default:                         /* anything else, terminate */
  607.                   build_loop = FALSE;
  608.                   break;
  609.                }
  610.  
  611.             }
  612.  
  613.          /* now scan the string to determine the number */
  614.  
  615.          sscanf( CURTASK exps[ CURTASK expsc ].string, "%o", &i );
  616.          CURTASK exps[ CURTASK expsc ].nval = (bnumber) i;
  617.  
  618.          break;
  619.  
  620.       case 16:                          /* hexadecimal constant */
  621.  
  622.          /* initialize counters */
  623.  
  624.          CURTASK exps[ CURTASK expsc ].pos_adv = man_start;
  625.          CURTASK exps[ CURTASK expsc ].type = NUMBER;
  626.          CURTASK exps[ CURTASK expsc ].string[ 0 ] = '¥0';
  627.          s_pos = 0;
  628.          exponent = OP_NULL;
  629.          build_loop = TRUE;
  630.  
  631.          /* loop to build the string */
  632.  
  633.          while ( build_loop == TRUE )
  634.             {
  635.             switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  636.                {
  637.                case '0':                        /* or ordinary digit */
  638.                case '1':
  639.                case '2':
  640.                case '3':
  641.                case '4':
  642.                case '5':
  643.                case '6':
  644.                case '7':
  645.                case '8':
  646.                case '9':
  647.                case 'A':
  648.                case 'a':
  649.                case 'B':
  650.                case 'b':
  651.                case 'C':
  652.                case 'c':
  653.                case 'D':
  654.                case 'd':
  655.                case 'E':
  656.                case 'e':
  657.                   CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  658.  
  659.                   ++CURTASK exps[ CURTASK expsc ].pos_adv;  /* advance to next character */
  660.                   ++s_pos;
  661.                   CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  662.                   break;
  663.  
  664.                default:                         /* anything else, terminate */
  665.                   build_loop = FALSE;
  666.                   break;
  667.                }
  668.  
  669.             }
  670.  
  671.          /* now scan the string to determine the number */
  672.  
  673.          sscanf( CURTASK exps[ CURTASK expsc ].string, "%x", &i );
  674.          CURTASK exps[ CURTASK expsc ].nval = (bnumber) i;
  675.          break;
  676.       }
  677.  
  678.    /* note that the operation at this level is now a determined NUMBER */
  679.  
  680.    CURTASK exps[ CURTASK expsc ].operation = NUMBER;
  681.  
  682. #if INTENSIVE_DEBUG
  683.    sprintf( bwb_ebuf, "in exp_numconst(): exit level <%d> precision <%c> value <%lf>",
  684.       CURTASK expsc, CURTASK exps[ CURTASK expsc ].type, exp_getnval( &( CURTASK exps[ CURTASK expsc ] ) ) );
  685.    bwb_debug( bwb_ebuf );
  686. #endif
  687.  
  688. #if CHECK_RECURSION
  689.    in_use = FALSE;
  690. #endif
  691.  
  692.    return TRUE;
  693.  
  694.    }
  695.  
  696. /***************************************************************
  697.  
  698.     FUNCTION:       exp_function()
  699.  
  700.     DESCRIPTION:    This function interprets a function,
  701.             calling bwb_exp() (recursively) to resolve any
  702.             arguments to the function.
  703.  
  704. ***************************************************************/
  705.  
  706. #if ANSI_C
  707. int
  708. exp_function( char *expression )
  709. #else
  710. int
  711. exp_function( expression )
  712.    char *expression;
  713. #endif
  714.    {
  715.    struct exp_ese *e;
  716.    int s_pos;                           /* position in build buffer */
  717.    int loop;
  718.    int paren_level;
  719.    int n_args;
  720.    struct bwb_variable *v;
  721.    struct bwb_variable argv[ MAX_FARGS ];
  722.    bstring *b;
  723. #if INTENSIVE_DEBUG
  724.    char tbuf[ MAXSTRINGSIZE + 1 ];
  725.  
  726.    sprintf( bwb_ebuf, "in exp_function(): entered function, expression <%s>",
  727.       expression );
  728.    bwb_debug( bwb_ebuf );
  729. #endif
  730.  
  731.    /* assign pointers to argument stack */
  732.  
  733.    /* get the function name */
  734.  
  735.    exp_getvfname( expression, CURTASK exps[ CURTASK expsc ].string );
  736.  
  737. #if INTENSIVE_DEBUG
  738.    sprintf( bwb_ebuf, "in exp_function(): name is <%s>.",
  739.       CURTASK exps[ CURTASK expsc ].string );
  740.    bwb_debug( bwb_ebuf );
  741. #endif
  742.  
  743.    /* now find the function itself */
  744.  
  745.    CURTASK exps[ CURTASK expsc ].function = fnc_find( CURTASK exps[ CURTASK expsc ].string );
  746.  
  747.    /* check to see if it is valid */
  748.  
  749.    if ( CURTASK exps[ CURTASK expsc ].function == NULL )
  750.       {
  751. #if PROG_ERRORS
  752.       sprintf( bwb_ebuf, "Failed to find function <%s>.",
  753.          CURTASK exps[ CURTASK expsc ].string );
  754.       bwb_error( bwb_ebuf );
  755. #else
  756.       bwb_error( err_uf  );
  757. #endif
  758.       return OP_ERROR;
  759.       }
  760.  
  761.    /* note that this level is a function */
  762.  
  763.    CURTASK exps[ CURTASK expsc ].operation = FUNCTION;
  764.    CURTASK exps[ CURTASK expsc ].pos_adv = strlen( CURTASK exps[ CURTASK expsc ].string );
  765.  
  766.    /* check for begin parenthesis */
  767.  
  768.    loop = TRUE;
  769.    while( loop == TRUE )
  770.       {
  771.       switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  772.          {
  773.  
  774.          case ' ':                              /* whitespace */
  775.          case '¥t':
  776.             ++CURTASK exps[ CURTASK expsc ].pos_adv;        /* advance */
  777.             break;
  778.  
  779.          case '(':                              /* begin paren */
  780.  
  781. #if INTENSIVE_DEBUG
  782.             sprintf( bwb_ebuf, "in exp_function(): found begin parenthesis." );
  783.             bwb_debug( bwb_ebuf );
  784. #endif
  785.  
  786.             ++CURTASK exps[ CURTASK expsc ].pos_adv;        /* advance beyond it */
  787.             paren_level = 1;                    /* set paren_level */
  788.             loop = FALSE;                       /* and break out */
  789.             break;
  790.  
  791.          default:                               /* anything else */
  792.             loop = FALSE;
  793.             paren_level = 0;                    /* do not look for arguments */
  794.             break;
  795.          }
  796.       }
  797.  
  798.    /* find arguments within parentheses */
  799.    /* for each argument, find a string ending with ',' or with end parenthesis */
  800.  
  801.    n_args = 0;
  802.    s_pos = 0;
  803.    CURTASK exps[ CURTASK expsc ].string[ 0 ] = '¥0';
  804.  
  805.    while( paren_level > 0 )
  806.       {
  807.  
  808.       /* check the current character */
  809.  
  810.       switch( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] )
  811.          {
  812.  
  813.          case ',':                      /* end of an argument */
  814.  
  815.             if ( paren_level == 1 )     /* ignore ',' within parentheses */
  816.                {
  817.  
  818.                /* call bwb_exp() recursively to resolve the argument */
  819.  
  820.                if ( exp_validarg( CURTASK exps[ CURTASK expsc ].string ) == TRUE )
  821.                   {
  822. #if INTENSIVE_DEBUG
  823.           sprintf( bwb_ebuf,
  824.              "in exp_function(): valid argument (not last)." );
  825.                   bwb_debug( bwb_ebuf );
  826. #endif
  827.  
  828.                   CURTASK exps[ CURTASK expsc ].rec_pos = 0;
  829.                   e = bwb_exp( CURTASK exps[ CURTASK expsc ].string, FALSE,
  830.                      &( CURTASK exps[ CURTASK expsc ].rec_pos ) );
  831.  
  832.                   /* assign operation and value at this level */
  833.  
  834.                   var_make( &( argv[ n_args ] ), e->type );
  835.  
  836.                   switch( argv[ n_args ].type )
  837.                      {
  838.                      case NUMBER:
  839.                         * var_findnval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  840.                             = exp_getnval( e );
  841.                         break;
  842.                      case STRING:
  843.                         str_btob( var_findsval( &( argv[ n_args ] ),
  844.                            argv[ n_args ].array_pos ), exp_getsval( e ) );
  845.                         break;
  846.                      }
  847.  
  848.                   ++n_args;                /* increment number of arguments */
  849.  
  850.                   }
  851.  
  852.                s_pos = 0;               /* reset counter */
  853.                CURTASK exps[ CURTASK expsc ].string[ 0 ] = '¥0';
  854.                }
  855.  
  856.             else
  857.                {
  858.                CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  859.                   = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  860.                ++s_pos;
  861.                CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  862.                }
  863.             break;
  864.  
  865.          case '(':
  866.             ++paren_level;
  867.             CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  868.                = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  869.             ++s_pos;
  870.             CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  871.             break;
  872.  
  873.          case ')':
  874.             --paren_level;
  875.  
  876. #if INTENSIVE_DEBUG
  877.             sprintf( bwb_ebuf,
  878.                "in exp_function(): hit close parenthesis." );
  879.             bwb_debug( bwb_ebuf );
  880. #endif
  881.  
  882.             if ( paren_level == 0 )
  883.                {
  884.  
  885. #if INTENSIVE_DEBUG
  886.                sprintf( bwb_ebuf,
  887.                   "in exp_function(): paren level 0." );
  888.                bwb_debug( bwb_ebuf );
  889. #endif
  890.  
  891.                /* call bwb_exp() recursively to resolve the argument */
  892.  
  893.                if ( exp_validarg( CURTASK exps[ CURTASK expsc ].string ) == TRUE )
  894.                   {
  895. #if INTENSIVE_DEBUG
  896.           sprintf( bwb_ebuf,
  897.              "in exp_function(): valid argument (last)." );
  898.           bwb_debug( bwb_ebuf );
  899. #endif
  900.  
  901.                   CURTASK exps[ CURTASK expsc ].rec_pos = 0;
  902.                   e = bwb_exp( CURTASK exps[ CURTASK expsc ].string, FALSE,
  903.                      &( CURTASK exps[ CURTASK expsc ].rec_pos ) );
  904.  
  905. #if INTENSIVE_DEBUG
  906.           sprintf( bwb_ebuf,
  907.              "in exp_function(): return from bwb_exp(), last arg, type <%c> op <%d>",
  908.              e->type, e->operation );
  909.           bwb_debug( bwb_ebuf );
  910. #endif
  911.  
  912.                   /* assign operation and value at this level */
  913.  
  914.                   var_make( &( argv[ n_args ] ), e->type );
  915.  
  916.                   switch( argv[ n_args ].type )
  917.                      {
  918.                      case NUMBER:
  919.                         * var_findnval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  920.                             = exp_getnval( e );
  921.                         break;
  922.                      case STRING:
  923.                         str_btob( var_findsval( &( argv[ n_args ] ),
  924.                            argv[ n_args ].array_pos ), exp_getsval( e ) );
  925.                         break;
  926.                      }
  927.  
  928.                   ++n_args;                /* increment number of arguments */
  929.  
  930.                   }
  931.  
  932.                s_pos = 0;               /* reset counter */
  933.                CURTASK exps[ CURTASK expsc ].string[ 0 ] = '¥0';
  934.                }
  935.  
  936.             else
  937.                {
  938.                CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  939.                   = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  940.                ++s_pos;
  941.                CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  942.                }
  943.             break;
  944.  
  945.          case '¥"':                             /* embedded string constant */
  946.  
  947.             /* add the initial quotation mark */
  948.  
  949.             CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  950.                = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  951.             ++s_pos;
  952.             CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  953.             ++CURTASK exps[ CURTASK expsc ].pos_adv;
  954.  
  955.             /* add intervening characters */
  956.  
  957.             while ( ( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] != '¥"' )
  958.                && ( expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] != '¥0' ) )
  959.                {
  960.                CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  961.                   = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  962.                ++s_pos;
  963.                CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  964.                ++CURTASK exps[ CURTASK expsc ].pos_adv;
  965.                }
  966.  
  967.             /* add the concluding quotation mark */
  968.  
  969.             CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  970.                = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  971.             ++s_pos;
  972.             CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  973.             /* the following bracketed out 14 July 1992; since this counter */
  974.             /* incremented at the end of the switch statement, this may */
  975.             /* increment it past the next character needed */
  976.             /* ++CURTASK exps[ CURTASK expsc ].pos_adv; */
  977.             break;
  978.  
  979.          default:
  980.             CURTASK exps[ CURTASK expsc ].string[ s_pos ]
  981.                = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
  982.             ++s_pos;
  983.             CURTASK exps[ CURTASK expsc ].string[ s_pos ] = '¥0';
  984. #if INTENSIVE_DEBUG
  985.             sprintf( bwb_ebuf, "in exp_function(): new char <%d>=<%c>",
  986.                expression[ CURTASK exps[ CURTASK expsc ].pos_adv ],
  987.                expression[ CURTASK exps[ CURTASK expsc ].pos_adv ] );
  988.             bwb_debug( bwb_ebuf );
  989.             sprintf( bwb_ebuf, "in exp_function(): building <%s>.",
  990.                CURTASK exps[ CURTASK expsc ].string );
  991.             bwb_debug( bwb_ebuf );
  992. #endif
  993.             break;
  994.          }
  995.  
  996.       /* advance the counter */
  997.  
  998.       ++CURTASK exps[ CURTASK expsc ].pos_adv;
  999.  
  1000.       }
  1001.  
  1002. #if INTENSIVE_DEBUG
  1003.    sprintf( bwb_ebuf, "in exp_function(): ready to call function vector" );
  1004.    bwb_debug( bwb_ebuf );
  1005. #endif
  1006.  
  1007.    /* call the function vector */
  1008.  
  1009. #if INTENSIVE_DEBUG
  1010.    sprintf( bwb_ebuf, "in exp_function(): calling preset function" );
  1011.    bwb_debug( bwb_ebuf );
  1012. #endif
  1013.  
  1014.    v = CURTASK exps[ CURTASK expsc ].function->vector ( n_args, &( argv[ 0 ] ),
  1015.       CURTASK exps[ CURTASK expsc ].function->id );
  1016.  
  1017. #if INTENSIVE_DEBUG
  1018.    sprintf( bwb_ebuf, "in exp_function(): return from function vector, type <%c>",
  1019.       v->type );
  1020.    bwb_debug( bwb_ebuf );
  1021. #endif
  1022.  
  1023.    /* assign the value at this level */
  1024.  
  1025.    CURTASK exps[ CURTASK expsc ].type = (char) v->type;
  1026.    
  1027.    switch( v->type )
  1028.       {
  1029.       case STRING:
  1030.          CURTASK exps[ CURTASK expsc ].operation = CONST_STRING;
  1031.  
  1032. #if INTENSIVE_DEBUG
  1033.          sprintf( bwb_ebuf, "in exp_function(): ready to assign STRING" );
  1034.          bwb_debug( bwb_ebuf );
  1035. #endif
  1036.  
  1037.          b = var_findsval( v, v->array_pos );
  1038.          str_btob( exp_getsval( &( CURTASK exps[ CURTASK expsc ] )), b );
  1039.  
  1040. #if INTENSIVE_DEBUG
  1041.          str_btoc( tbuf, b );
  1042.          sprintf( bwb_ebuf, "in exp_function(): string assigned <%s>", tbuf );
  1043.          bwb_debug( bwb_ebuf );
  1044. #endif
  1045.  
  1046.          break;
  1047.  
  1048.       default:
  1049.          CURTASK exps[ CURTASK expsc ].operation = NUMBER;
  1050.          CURTASK exps[ CURTASK expsc ].nval = var_getnval( v );
  1051.          break;
  1052.       }
  1053.  
  1054. #if INTENSIVE_DEBUG
  1055.    sprintf( bwb_ebuf, "in exp_function(): end of function" );
  1056.    bwb_debug( bwb_ebuf );
  1057. #endif
  1058.  
  1059.    /* return */
  1060.  
  1061.    return TRUE;
  1062.  
  1063.    }
  1064.  
  1065. /***************************************************************
  1066.  
  1067.     FUNCTION:       exp_variable()
  1068.  
  1069.     DESCRIPTION:    This function interprets a variable.
  1070.  
  1071. ***************************************************************/
  1072.  
  1073. #if ANSI_C
  1074. int
  1075. exp_variable( char *expression )
  1076. #else
  1077. int
  1078. exp_variable( expression )
  1079.    char *expression;
  1080. #endif
  1081.    {
  1082.    int pos;
  1083.    int *pp;
  1084.    int n_params;
  1085.    register int n;
  1086.    struct bwb_variable *v;
  1087.    bstring *b;
  1088.    int p;
  1089.  
  1090. #if INTENSIVE_DEBUG
  1091.    sprintf( bwb_ebuf, "in exp_variable(): entered function." );
  1092.    bwb_debug( bwb_ebuf );
  1093. #endif
  1094.  
  1095.    /* get the variable name */
  1096.  
  1097.    exp_getvfname( expression, CURTASK exps[ CURTASK expsc ].string );
  1098.  
  1099.    /* now find the variable itself */
  1100.  
  1101.    v = CURTASK exps[ CURTASK expsc ].xvar = var_find( CURTASK exps[ CURTASK expsc ].string );
  1102.  
  1103. #if INTENSIVE_DEBUG
  1104.    sprintf( bwb_ebuf, "in exp_variable(): level <%d>, found variable name <%s>",
  1105.       CURTASK expsc, CURTASK exps[ CURTASK expsc ].xvar->name );
  1106.    bwb_debug( bwb_ebuf );
  1107. #endif
  1108.  
  1109.    /* note that this level is a variable */
  1110.  
  1111.    CURTASK exps[ CURTASK expsc ].operation = VARIABLE;
  1112.  
  1113.    /* read subscripts */
  1114.  
  1115.    pos = strlen( CURTASK exps[ CURTASK expsc ].string );
  1116.    if ( ( v->dimensions == 1 ) && ( v->array_sizes[ 0 ] == 1 ))
  1117.       {
  1118. #if INTENSIVE_DEBUG
  1119.       sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has 1 dimension",
  1120.          CURTASK exps[ CURTASK expsc ].xvar->name );
  1121.       bwb_debug( bwb_ebuf );
  1122. #endif
  1123.       pos = strlen( v->name );
  1124.       n_params = 1;
  1125.       pp = &p;
  1126.       pp[ 0 ] = dim_base;
  1127.       }
  1128.    else
  1129.       {
  1130. #if INTENSIVE_DEBUG
  1131.       sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has > 1 dimensions",
  1132.          CURTASK exps[ CURTASK expsc ].xvar->name );
  1133.       bwb_debug( bwb_ebuf );
  1134. #endif
  1135.       dim_getparams( expression, &pos, &n_params, &pp );
  1136.       }
  1137.  
  1138.    CURTASK exps[ CURTASK expsc ].pos_adv = pos;
  1139.    for ( n = 0; n < v->dimensions; ++n )
  1140.       {
  1141.       CURTASK exps[ CURTASK expsc ].array_pos[ n ] = v->array_pos[ n ] = pp[ n ];
  1142.       }
  1143.  
  1144. #if INTENSIVE_DEBUG
  1145.    for ( n = 0; n < v->dimensions; ++ n )
  1146.       {
  1147.       sprintf( bwb_ebuf, "in exp_variable(): var <%s> array_pos element <%d> is <%d>.",
  1148.          v->name, n, v->array_pos[ n ] );
  1149.       bwb_debug( bwb_ebuf );
  1150.       }
  1151. #endif
  1152.  
  1153.    /* assign the type and value at this level */
  1154.  
  1155.    CURTASK exps[ CURTASK expsc ].type = (char) v->type;
  1156.    
  1157.    switch( v->type )
  1158.       {
  1159.       case STRING:
  1160.          b = var_findsval( v, v->array_pos );
  1161. #if TEST_BSTRING
  1162.          sprintf( bwb_ebuf, "in exp_variable(): b string name is <%s>",
  1163.             b->name );
  1164.          bwb_debug( bwb_ebuf );
  1165. #endif
  1166. #if OLDWAY
  1167.      CURTASK exps[ CURTASK expsc ].sval.length = b->length;
  1168.      CURTASK exps[ CURTASK expsc ].sval.sbuffer = b->sbuffer;
  1169. #endif
  1170.      str_btob( &( CURTASK exps[ CURTASK expsc ].sval ), b );
  1171.          break;
  1172.       default:
  1173.          CURTASK exps[ CURTASK expsc ].nval = var_getnval( v );
  1174.          break;
  1175.       }
  1176.  
  1177. #if INTENSIVE_DEBUG
  1178.    sprintf( bwb_ebuf, "in exp_variable(): exit, name <%s>, level <%d>, op <%d>",
  1179.       v->name, CURTASK expsc, CURTASK exps[ CURTASK expsc ].operation  );
  1180.    bwb_debug( bwb_ebuf );
  1181. #endif
  1182.  
  1183.    /* return */
  1184.  
  1185.    return TRUE;
  1186.  
  1187.    }
  1188.  
  1189.  
  1190.  
  1191.