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_cnd.c < prev    next >
Text File  |  1993-11-09  |  56KB  |  2,409 lines

  1. /***************************************************************
  2.  
  3.         bwb_cnd.c       Conditional Expressions and Commands
  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 <math.h>
  28. #include <ctype.h>
  29.  
  30. #include "bwbasic.h"
  31. #include "bwb_mes.h"
  32.  
  33. /* declarations of functions visible to this file only */
  34.  
  35. #if ANSI_C
  36. static int cnd_thenels( char *buffer, int position, int *then, int *els );
  37. static int cnd_tostep( char *buffer, int position, int *to, int *step );
  38. static struct bwb_line *find_wend( struct bwb_line *l );
  39. static struct bwb_line *find_endif( struct bwb_line *l,
  40.    struct bwb_line **else_line );
  41. static int is_endif( struct bwb_line *l );
  42. extern int var_setnval( struct bwb_variable *v, bnumber i );
  43. static int case_eval( struct exp_ese *expression, struct exp_ese *minval,
  44.    struct exp_ese *maxval );
  45. static struct bwb_line *find_case( struct bwb_line *l );
  46. static struct bwb_line *find_endselect( struct bwb_line *l );
  47. static int is_endselect( struct bwb_line *l );
  48. static struct bwb_line *bwb_caseif( struct bwb_line *l );
  49.  
  50. #if STRUCT_CMDS
  51. static struct bwb_line *find_next( struct bwb_line *l );
  52. #endif
  53.  
  54. #else
  55. static int cnd_thenels();
  56. static int cnd_tostep();
  57. static struct bwb_line *find_wend();
  58. static struct bwb_line *find_endif();
  59. static int is_endif();
  60. extern int var_setnval();
  61. static int case_eval();
  62. static struct bwb_line *find_case();
  63. static struct bwb_line *find_endselect();
  64. static int is_endselect();
  65. static struct bwb_line *bwb_caseif();
  66.  
  67. #if STRUCT_CMDS
  68. static struct bwb_line *find_next();
  69. #endif
  70.  
  71. #endif                          /* ANSI_C for prototypes */
  72.  
  73. /***    IF-THEN-ELSE ***/
  74.  
  75. /***************************************************************
  76.  
  77.         FUNCTION:       bwb_if()
  78.  
  79.         DESCRIPTION:    This function handles the BASIC IF
  80.                         statement.
  81.  
  82.        SYNTAX:        IF expression THEN [statement [ELSE statement]]
  83.  
  84. ***************************************************************/
  85.  
  86. #if ANSI_C
  87. struct bwb_line *
  88. bwb_if( struct bwb_line *l )
  89. #else
  90. struct bwb_line *
  91. bwb_if( l )
  92.    struct bwb_line *l;
  93. #endif
  94.    {
  95.    int then, els;
  96.    struct exp_ese *e;
  97.    int glnumber;
  98.    int tpos;
  99.    static char tbuf[ MAXSTRINGSIZE + 1 ];
  100.    static struct bwb_line gline;
  101. #if STRUCT_CMDS
  102.    static struct bwb_line *else_line;
  103.    static struct bwb_line *endif_line;
  104. #endif
  105.  
  106. #if INTENSIVE_DEBUG
  107.    sprintf( bwb_ebuf, "in bwb_if(): entry, line <%d> buffer <%s>",
  108.       l->number, &( l->buffer[ l->position ] ) );
  109.    bwb_debug( bwb_ebuf );
  110.    getchar();
  111. #endif
  112.  
  113. #if INTENSIVE_DEBUG
  114.    if ( l == &gline )
  115.       {
  116.       sprintf( bwb_ebuf, "in bwb_if(): recursive call, l = &gline" );
  117.       bwb_debug( bwb_ebuf );
  118.       }
  119. #endif
  120.  
  121.    /* Call bwb_exp() to evaluate the condition. This should return
  122.       with position set to the "THEN" statement */
  123.  
  124.    e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  125.  
  126. #if INTENSIVE_DEBUG
  127.    sprintf( bwb_ebuf, "in bwb_if(): line <%d> condition returns <%d>",
  128.       l->number, exp_getnval( e ) );
  129.    bwb_debug( bwb_ebuf );
  130. #endif
  131.  
  132.    /* test for "THEN" and "ELSE" statements */
  133.  
  134.    cnd_thenels( l->buffer, l->position, &then, &els );
  135.  
  136. #if INTENSIVE_DEBUG
  137.    sprintf( bwb_ebuf, "in bwb_if(): return from cnd_thenelse, line is <%s>",
  138.       l->buffer );
  139.    bwb_debug( bwb_ebuf );
  140. #endif
  141.  
  142.    /* test for multiline IF statement: this presupposes ANSI-compliant
  143.       structured BASIC */
  144.  
  145. #if STRUCT_CMDS
  146.    tpos = then + strlen( CMD_THEN ) + 1;
  147.    if ( is_eol( l->buffer, &tpos ) == TRUE )
  148.       {
  149.  
  150. #if INTENSIVE_DEBUG
  151.       sprintf( bwb_ebuf, "in bwb_if(): found multi-line IF statement, line <%d>",
  152.          l->number );
  153.       bwb_debug( bwb_ebuf );
  154. #endif
  155.  
  156.       /* find END IF and possibly ELSE[IF] line(s) */
  157.  
  158.       else_line = NULL;
  159.       endif_line = find_endif( l, &else_line );
  160.  
  161.       /* evaluate the expression */
  162.  
  163.       if ( (int) exp_getnval( e ) != FALSE )
  164.          {
  165.          bwb_incexec();
  166.          bwb_setexec( l->next, 0, EXEC_IFTRUE );
  167.  
  168. #if MULTISEG_LINES
  169.          adv_eos( l->buffer, &( l->position ));
  170. #endif
  171.          return bwb_zline( l );
  172.          }
  173.  
  174.       else if ( else_line != NULL )
  175.          {
  176.          bwb_incexec();
  177.          bwb_setexec( else_line, 0, EXEC_IFFALSE );
  178.          else_line->position = 0;
  179.          return else_line;
  180.          }
  181.       else
  182.          {
  183.          bwb_setexec( endif_line, 0, CURTASK excs[ CURTASK exsc ].code );
  184.          endif_line->position = 0;
  185.          return endif_line;
  186.          }
  187.       }
  188.  
  189. #endif            /* STRUCT_CMDS for Multi-line IF...THEN */
  190.  
  191.    /* Not a Multi-line IF...THEN: test for THEN line-number */
  192.  
  193. #if INTENSIVE_DEBUG
  194.    sprintf( bwb_ebuf, "in bwb_if(): not multi-line; line is <%s>",
  195.       l->buffer );
  196.    bwb_debug( bwb_ebuf );
  197. #endif
  198.  
  199.    /* evaluate and execute */
  200.  
  201.    if ( (int) exp_getnval( e ) != FALSE )
  202.       {
  203.  
  204. #if INTENSIVE_DEBUG
  205.       sprintf( bwb_ebuf, "in bwb_if(): expression is TRUE" );
  206.       bwb_debug( bwb_ebuf );
  207. #endif
  208.  
  209.       if ( then == FALSE )
  210.          {
  211. #if PROG_ERRORS
  212.      sprintf( bwb_ebuf, "in bwb_if(): IF without THEN" );
  213.          bwb_error( bwb_ebuf );
  214. #else
  215.          bwb_error( err_syntax );
  216. #endif
  217.          }
  218.       else
  219.          {
  220.  
  221.      /* check for THEN followed by literal line number */
  222.  
  223.      tpos = then + strlen( CMD_THEN ) + 1;
  224.      adv_element( l->buffer, &tpos, tbuf );
  225.  
  226.      if ( isdigit( tbuf[ 0 ] ) != 0 )
  227.         {
  228.  
  229.         glnumber = atoi( tbuf );
  230.  
  231. #if INTENSIVE_DEBUG
  232.         sprintf( bwb_ebuf, "Detected THEN followed by line number <%d>",
  233.            glnumber );
  234.         bwb_debug( bwb_ebuf );
  235. #endif
  236.  
  237.         sprintf( tbuf, "%s %d", CMD_GOTO, glnumber );
  238.         gline.buffer = tbuf;
  239.         gline.marked = FALSE;
  240.         gline.position = 0;
  241.         gline.next = l->next;
  242.         bwb_setexec( &gline, 0, CURTASK excs[ CURTASK exsc ].code );
  243.         return &gline;
  244.         }
  245.  
  246.      /* form is not THEN followed by line number */
  247.  
  248.      else
  249.         {
  250.         bwb_setexec( l, then, CURTASK excs[ CURTASK exsc ].code );
  251.         l->position = then + strlen( CMD_THEN ) + 1;
  252.         }
  253.  
  254.      return l;
  255.      }
  256.       }
  257.    else
  258.       {
  259.  
  260. #if INTENSIVE_DEBUG
  261.       sprintf( bwb_ebuf, "in bwb_if(): expression is FALSE" );
  262.       bwb_debug( bwb_ebuf );
  263. #endif
  264.  
  265.       if ( els != FALSE )
  266.          {
  267.          l->position = els + strlen( CMD_ELSE ) + 1;
  268.          bwb_setexec( l, els, EXEC_NORM );
  269.      return l;
  270.      }
  271.       }
  272.  
  273.    /* if neither then nor else were found, advance to next line */
  274.    /* DO NOT advance to next segment (only if TRUE should we do that */
  275.  
  276.    l->next->position = 0;
  277.    return l->next;
  278.  
  279.    }
  280.  
  281. /***************************************************************
  282.  
  283.         FUNCTION:       cnd_thenelse()
  284.  
  285.         DESCRIPTION:    This function searches through the
  286.                         <buffer> beginning at point <position>
  287.                         and attempts to find positions of THEN
  288.                         and ELSE statements.
  289.  
  290. ***************************************************************/
  291.  
  292. #if ANSI_C
  293. static int
  294. cnd_thenels( char *buffer, int position, int *then, int *els )
  295. #else
  296. static int
  297. cnd_thenels( buffer, position, then, els )
  298.    char *buffer;
  299.    int position;
  300.    int *then;
  301.    int *els;
  302. #endif
  303.    {
  304.    int loop, t_pos, b_pos, p_word;
  305.    char tbuf[ MAXSTRINGSIZE + 1 ];
  306.  
  307. #if INTENSIVE_DEBUG
  308.    sprintf( bwb_ebuf, "in cnd_thenels(): entry, line is <%s>",
  309.       &( buffer[ position ] ) );
  310.    bwb_debug( bwb_ebuf );
  311. #endif
  312.  
  313.    /* set then and els to 0 initially */
  314.  
  315.    *then = *els = 0;
  316.  
  317.    /* loop to find words */
  318.  
  319.    p_word = b_pos = position;
  320.    t_pos = 0;
  321.    tbuf[ 0 ] = '¥0';
  322.    loop = TRUE;
  323.    while( loop == TRUE )
  324.       {
  325.  
  326.       switch( buffer[ b_pos ] )
  327.          {
  328.          case '¥0':                     /* end of string */
  329.          case ' ':                      /* whitespace = end of word */
  330.          case '¥t':
  331.  
  332. #if INTENSIVE_DEBUG
  333.             sprintf( bwb_ebuf, "in cnd_thenels(): word is <%s>", tbuf );
  334.             bwb_debug( bwb_ebuf );
  335. #endif
  336.  
  337.             if ( strncmp( tbuf, CMD_THEN, (size_t) strlen( CMD_THEN ) ) == 0 )
  338.                {
  339.  
  340. #if INTENSIVE_DEBUG
  341.                sprintf( bwb_ebuf, "in cnd_thenels(): THEN found at position <%d>.",
  342.                   p_word );
  343.                bwb_debug( bwb_ebuf );
  344.                sprintf( bwb_ebuf, "in cnd_thenelse(): after THEN, line is <%s>", buffer );
  345.                bwb_debug( bwb_ebuf );
  346. #endif
  347.  
  348.                *then = p_word;
  349.                }
  350.             else if ( strncmp( tbuf, CMD_ELSE, (size_t) strlen( CMD_ELSE ) ) == 0 )
  351.                {
  352.  
  353. #if INTENSIVE_DEBUG
  354.                sprintf( bwb_ebuf, "in cnd_thenels(): ELSE found at position <%d>.",
  355.                   p_word );
  356.                bwb_debug( bwb_ebuf );
  357.                sprintf( bwb_ebuf, "in cnd_thenelse(): after ELSE, line is <%s>", buffer );
  358.                bwb_debug( bwb_ebuf );
  359. #endif
  360.  
  361.                *els = p_word;
  362.                }
  363.  
  364.             /* check for end of the line */
  365.  
  366.             if ( buffer[ b_pos ] == '¥0' )
  367.                {
  368. #if INTENSIVE_DEBUG
  369.                sprintf( bwb_ebuf, "in cnd_thenels(): return: end of string" );
  370.                bwb_debug( bwb_ebuf );
  371. #endif
  372.                return TRUE;
  373.                }
  374.  
  375.             ++b_pos;
  376.             p_word = b_pos;
  377.             t_pos = 0;
  378.             tbuf[ 0 ] = '¥0';
  379.             break;
  380.  
  381.          default:
  382.             if ( islower( buffer[ b_pos ] ) != FALSE )
  383.                {
  384.                tbuf[ t_pos ] = (char) toupper( buffer[ b_pos ] );
  385.                }
  386.             else
  387.                {
  388.                tbuf[ t_pos ] = buffer[ b_pos ];
  389.                }
  390.             ++b_pos;
  391.             ++t_pos;
  392.             tbuf[ t_pos ] = '¥0';
  393.             break;
  394.          }
  395.  
  396.       }
  397.  
  398. #if INTENSIVE_DEBUG
  399.    sprintf( bwb_ebuf, "in cnd_thenelse(): exit, line is <%s>", buffer );
  400.    bwb_debug( bwb_ebuf );
  401. #endif
  402.  
  403.    return FALSE;
  404.  
  405.    }
  406.  
  407. #if STRUCT_CMDS
  408.  
  409. /***************************************************************
  410.  
  411.         FUNCTION:       bwb_else()
  412.  
  413.         DESCRIPTION:    This function handles the BASIC ELSE
  414.                         statement.
  415.  
  416.        SYNTAX:        ELSE
  417.  
  418. ***************************************************************/
  419.  
  420. #if ANSI_C
  421. struct bwb_line *
  422. bwb_else( struct bwb_line *l )
  423. #else
  424. struct bwb_line *
  425. bwb_else( l )
  426.    struct bwb_line *l;
  427. #endif
  428.    {
  429.    struct bwb_line *endif_line;
  430.    struct bwb_line *else_line;
  431.  
  432. #if INTENSIVE_DEBUG
  433.    sprintf( bwb_ebuf, "in bwb_else(): entered function" );
  434.    bwb_debug( bwb_ebuf );
  435. #endif
  436.  
  437.    /* If the code is EXEC_NORM, then this is a continuation of a single-
  438.       line IF...THEN...ELSE... statement and we should return */
  439.  
  440.    if ( CURTASK excs[ CURTASK exsc ].code == EXEC_NORM )
  441.       {
  442.  
  443. #if INTENSIVE_DEBUG
  444.       sprintf( bwb_ebuf, "in bwb_else(): detected EXEC_NORM" );
  445.       bwb_debug( bwb_ebuf );
  446. #endif
  447.  
  448.       return bwb_zline( l );
  449.       }
  450.  
  451.    endif_line = find_endif( l, &else_line );
  452.  
  453.    if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFTRUE )
  454.       {
  455.       endif_line->position = 0;
  456.       return endif_line;
  457.       }
  458.    else if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFFALSE )
  459.       {
  460.  
  461.       return bwb_zline( l );
  462.       }
  463.  
  464. #if PROG_ERRORS
  465.    sprintf( bwb_ebuf, "in bwb_else(): ELSE without IF" );
  466.    bwb_error( bwb_ebuf );
  467. #else
  468.    bwb_error( err_syntax );
  469. #endif
  470.  
  471.  
  472.    return bwb_zline( l );
  473.    }
  474.  
  475. /***************************************************************
  476.  
  477.         FUNCTION:       bwb_elseif()
  478.  
  479.         DESCRIPTION:    This function handles the BASIC ELSEIF
  480.                         statement.
  481.  
  482.     SYNTAX:        ELSEIF
  483.  
  484. ***************************************************************/
  485.  
  486. #if ANSI_C
  487. struct bwb_line *
  488. bwb_elseif( struct bwb_line *l )
  489. #else
  490. struct bwb_line *
  491. bwb_elseif( l )
  492.    struct bwb_line *l;
  493. #endif
  494.    {
  495.    struct bwb_line *endif_line;
  496.    struct bwb_line *else_line;
  497.    struct exp_ese *e;
  498.  
  499. #if INTENSIVE_DEBUG
  500.    sprintf( bwb_ebuf, "in bwb_elseif(): entered function" );
  501.    bwb_debug( bwb_ebuf );
  502. #endif
  503.  
  504.    else_line = NULL;
  505.    endif_line = find_endif( l, &else_line );
  506.  
  507.    if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFTRUE )
  508.       {
  509.       endif_line->position = 0;
  510.       return endif_line;
  511.       }
  512.  
  513.    else if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFFALSE )
  514.       {
  515.  
  516.       /* Call bwb_exp() to evaluate the condition. This should return
  517.          with position set to the "THEN" statement */
  518.  
  519.       e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  520.  
  521.       if ( (int) exp_getnval( e ) == TRUE )
  522.          {
  523.  
  524.          /* ELSEIF condition is TRUE: proceed to the next line */
  525.  
  526.          CURTASK excs[ CURTASK exsc ].code = EXEC_IFTRUE;
  527.  
  528. #if MULTISEG_LINES
  529.          adv_eos( l->buffer, &( l->position ));
  530. #endif
  531.          return bwb_zline( l );
  532.  
  533.          }
  534.  
  535.       /* ELSEIF condition FALSE: proceed to next ELSE line if there is one */
  536.  
  537.       else if ( else_line != NULL )
  538.          {
  539.          bwb_setexec( else_line, 0, EXEC_IFFALSE );
  540.          else_line->position = 0;
  541.          return else_line;
  542.          }
  543.  
  544.       /* ELSEIF condition is FALSE and no more ELSExx lines: proceed to END IF */
  545.  
  546.       else
  547.          {
  548.          bwb_setexec( endif_line, 0, CURTASK excs[ CURTASK exsc ].code );
  549.          endif_line->position = 0;
  550.          return endif_line;
  551.          }
  552.  
  553.       }
  554.  
  555. #if PROG_ERRORS
  556.    sprintf( bwb_ebuf, "in bwb_elseif(): ELSEIF without IF" );
  557.    bwb_error( bwb_ebuf );
  558. #else
  559.    bwb_error( err_syntax );
  560. #endif
  561.  
  562.  
  563. #if MULTISEG_LINES
  564.    adv_eos( l->buffer, &( l->position ));
  565. #endif
  566.    return bwb_zline( l );
  567.  
  568.    }
  569.  
  570. /***************************************************************
  571.  
  572.         FUNCTION:       bwb_endif()
  573.  
  574.         DESCRIPTION:    This function handles the BASIC END IF
  575.                         statement.
  576.  
  577.     SYNTAX:        END IF
  578.  
  579. ***************************************************************/
  580.  
  581. #if ANSI_C
  582. struct bwb_line *
  583. bwb_endif( struct bwb_line *l )
  584. #else
  585. struct bwb_line *
  586. bwb_endif( l )
  587.    struct bwb_line *l;
  588. #endif
  589.    {
  590.  
  591. #if INTENSIVE_DEBUG
  592.    sprintf( bwb_ebuf, "in bwb_endif(): entered function" );
  593.    bwb_debug( bwb_ebuf );
  594. #endif
  595.  
  596.    if (( CURTASK excs[ CURTASK exsc ].code != EXEC_IFTRUE )
  597.       && ( CURTASK excs[ CURTASK exsc ].code != EXEC_IFFALSE ))
  598.       {
  599. #if PROG_ERRORS
  600.       sprintf( bwb_ebuf, "in bwb_endif(): END IF without IF" );
  601.       bwb_error( bwb_ebuf );
  602. #else
  603.       bwb_error( err_syntax );
  604. #endif
  605.       }
  606.  
  607.    bwb_decexec();
  608.  
  609.  
  610. #if MULTISEG_LINES
  611.    adv_eos( l->buffer, &( l->position ));
  612. #endif
  613.    return bwb_zline( l );
  614.    }
  615.  
  616. /***************************************************************
  617.  
  618.         FUNCTION:       find_endif()
  619.  
  620.         DESCRIPTION:    This C function attempts to find an
  621.             END IF statement.
  622.  
  623. ***************************************************************/
  624.  
  625. #if ANSI_C
  626. static struct bwb_line *
  627. find_endif( struct bwb_line *l, struct bwb_line **else_line )
  628. #else
  629. static struct bwb_line *
  630. find_endif( l, else_line )
  631.    struct bwb_line *l;
  632.    struct bwb_line **else_line;
  633. #endif
  634.    {
  635.    struct bwb_line *current;
  636.    register int i_level;
  637.    int position;
  638.  
  639.    *else_line = NULL;
  640.    i_level = 1;
  641.    for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  642.       {
  643.       position = 0;
  644.       if ( current->marked != TRUE )
  645.          {
  646.          line_start( current->buffer, &position, &( current->lnpos ),
  647.             &( current->lnum ),
  648.             &( current->cmdpos ),
  649.             &( current->cmdnum ),
  650.             &( current->startpos ) );
  651.          }
  652.       current->position = current->startpos;
  653.  
  654.       if ( current->cmdnum > -1 )
  655.          {
  656.  
  657.          if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_if )
  658.             {
  659.             ++i_level;
  660.  
  661. #if INTENSIVE_DEBUG
  662.             sprintf( bwb_ebuf, "in find_endif(): found IF at line %d, level %d",
  663.                current->number, i_level );
  664.             bwb_debug( bwb_ebuf );
  665. #endif
  666.  
  667.             }
  668.          else if ( is_endif( current ) == TRUE )
  669.             {
  670.             --i_level;
  671.  
  672. #if INTENSIVE_DEBUG
  673.             sprintf( bwb_ebuf, "in find_endif(): found END IF at line %d, level %d",
  674.                current->number, i_level );
  675.             bwb_debug( bwb_ebuf );
  676. #endif
  677.  
  678.             if ( i_level == 0 )
  679.                {
  680.                return current;
  681.                }
  682.             }
  683.  
  684.          else if ( ( bwb_cmdtable[ current->cmdnum ].vector == bwb_else )
  685.             || ( bwb_cmdtable[ current->cmdnum ].vector == bwb_elseif ))
  686.             {
  687.  
  688.             /* we must only report the first ELSE or ELSE IF we encounter
  689.                at level 1 */
  690.  
  691.             if ( ( i_level == 1 ) && ( *else_line == NULL ))
  692.                {
  693.                *else_line = current;
  694.                }
  695.  
  696.             }
  697.          }
  698.       }
  699.  
  700. #if PROG_ERRORS
  701.    sprintf( bwb_ebuf, "Multiline IF without END IF" );
  702.    bwb_error( bwb_ebuf );
  703. #else
  704.    bwb_error( err_syntax  );
  705. #endif
  706.  
  707.    return NULL;
  708.  
  709.    }
  710.  
  711. /***************************************************************
  712.  
  713.     FUNCTION:       is_endif()
  714.  
  715.     DESCRIPTION:    This C function attempts to determine if
  716.             a given line contains an END IF statement.
  717.  
  718. ***************************************************************/
  719.  
  720. #if ANSI_C
  721. static int
  722. is_endif( struct bwb_line *l )
  723. #else
  724. static int
  725. is_endif( l )
  726.    struct bwb_line *l;
  727. #endif
  728.    {
  729.    int position;
  730.    char tbuf[ MAXVARNAMESIZE + 1];
  731.  
  732.    if ( bwb_cmdtable[ l->cmdnum ].vector != bwb_xend )
  733.       {
  734.       return FALSE;
  735.       }
  736.  
  737.    position = l->startpos;
  738.    adv_ws( l->buffer, &position );
  739.    adv_element( l->buffer, &position, tbuf );
  740.    bwb_strtoupper( tbuf );
  741.  
  742.    if ( strcmp( tbuf, "IF" ) == 0 )
  743.       {
  744.       return TRUE;
  745.       }
  746.  
  747.    return FALSE;
  748.  
  749.    }
  750.  
  751. /***************************************************************
  752.  
  753.         FUNCTION:       bwb_select()
  754.  
  755.         DESCRIPTION:    This C function handles the BASIC SELECT
  756.                         statement.
  757.  
  758.     SYNTAX:        SELECT CASE expression
  759.  
  760. ***************************************************************/
  761.  
  762. #if ANSI_C
  763. struct bwb_line *
  764. bwb_select( struct bwb_line *l )
  765. #else
  766. struct bwb_line *
  767. bwb_select( l )
  768.    struct bwb_line *l;
  769. #endif
  770.    {
  771.    char tbuf[ MAXSTRINGSIZE + 1 ];
  772.    struct exp_ese *e;
  773.  
  774. #if INTENSIVE_DEBUG
  775.    sprintf( bwb_ebuf, "in bwb_select(): entered function" );
  776.    bwb_debug( bwb_ebuf );
  777. #endif
  778.  
  779.    /* first element should be "CASE" */
  780.  
  781.    adv_element( l->buffer, &( l->position ), tbuf );
  782.    bwb_strtoupper( tbuf );
  783.    if ( strcmp( tbuf, "CASE" ) != 0 )
  784.       {
  785. #if PROG_ERRORS
  786.       sprintf( bwb_ebuf, "SELECT without CASE" );
  787.       bwb_error( bwb_ebuf );
  788. #else
  789.       bwb_error( err_syntax );
  790.  
  791.       return bwb_zline( l );
  792. #endif
  793.       }
  794.  
  795.    /* increment the level and set to EXEC_SELFALSE */
  796.  
  797.    bwb_incexec();
  798.    CURTASK excs[ CURTASK exsc ].code = EXEC_SELFALSE;
  799.  
  800.    /* evaluate the expression at this level */
  801.  
  802.    e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  803.  
  804. #if OLDWAY
  805.    memcpy( &( CURTASK excs[ CURTASK exsc ].expression ), e,
  806.       sizeof( struct exp_ese ) );
  807. #endif
  808.  
  809.    if ( e->type == STRING )
  810.       {
  811.       CURTASK excs[ CURTASK exsc ].expression.type = STRING;
  812.       str_btob( &( CURTASK excs[ CURTASK exsc ].expression.sval ),
  813.      &( e->sval ) );
  814.       }
  815.    else
  816.       {
  817.       CURTASK excs[ CURTASK exsc ].expression.type = NUMBER;
  818.       CURTASK excs[ CURTASK exsc ].expression.nval
  819.      = exp_getnval( e );
  820.       }
  821.  
  822.    /* return */
  823.  
  824. #if MULTISEG_LINES
  825.    adv_eos( l->buffer, &( l->position ));
  826. #endif
  827.  
  828.    return bwb_zline( l );
  829.    }
  830.  
  831. /***************************************************************
  832.  
  833.         FUNCTION:       bwb_case()
  834.  
  835.         DESCRIPTION:    This C function handles the BASIC CASE
  836.                         statement.
  837.  
  838.     SYNTAX:        CASE constant | IF partial-expression | ELSE
  839.  
  840. ***************************************************************/
  841.  
  842. #if ANSI_C
  843. struct bwb_line *
  844. bwb_case( struct bwb_line *l )
  845. #else
  846. struct bwb_line *
  847. bwb_case( l )
  848.    struct bwb_line *l;
  849. #endif
  850.    {
  851.    char tbuf[ MAXSTRINGSIZE + 1 ];
  852.    int oldpos;
  853.    struct exp_ese minvalue;
  854.    struct exp_ese *maxval, *minval;
  855.    struct bwb_line *retline;
  856.    char cbuf1[ MAXSTRINGSIZE + 1 ];
  857.    char cbuf2[ MAXSTRINGSIZE + 1 ];
  858.  
  859. #if INTENSIVE_DEBUG
  860.    sprintf( bwb_ebuf, "in bwb_case(): entered function" );
  861.    bwb_debug( bwb_ebuf );
  862. #endif
  863.  
  864.    /* if code is EXEC_SELTRUE, then we should jump to the end */
  865.  
  866.    if ( CURTASK excs[ CURTASK exsc ].code == EXEC_SELTRUE )
  867.       {
  868. #if INTENSIVE_DEBUG
  869.       sprintf( bwb_ebuf, "in bwb_case(): exit EXEC_SELTRUE" );
  870.       bwb_debug( bwb_ebuf );
  871. #endif
  872.       retline = find_endselect( l );
  873.       retline->position = 0;
  874.       return retline;
  875.       }
  876.  
  877.    /* read first element */
  878.  
  879.    oldpos = l->position;
  880.    adv_element( l->buffer, &( l->position ), tbuf );
  881.    bwb_strtoupper( tbuf );
  882.  
  883.    /* check for CASE IF */
  884.  
  885.    if ( strcmp( tbuf, CMD_IF ) == 0 )
  886.       {
  887.       return bwb_caseif( l );
  888.       }
  889.  
  890.    /* check for CASE ELSE: if true, simply proceed to the next line,
  891.       because other options should have been detected by now */
  892.  
  893.    else if ( strcmp( tbuf, CMD_ELSE ) == 0 )
  894.       {
  895. #if INTENSIVE_DEBUG
  896.       sprintf( bwb_ebuf, "in bwb_case(): execute CASE ELSE" );
  897.       bwb_debug( bwb_ebuf );
  898. #endif
  899.  
  900.       return bwb_zline( l );
  901.       }
  902.  
  903.    /* neither CASE ELSE nor CASE IF; presume constant here for min value */
  904.  
  905.    l->position = oldpos;
  906.    minval = bwb_exp( l->buffer, FALSE, &( l->position ));
  907.    memcpy( &minvalue, minval, sizeof( struct exp_ese ) );
  908.    maxval = minval = &minvalue;
  909.  
  910.    /* check for string value */
  911.  
  912.    if ( minvalue.type == STRING )
  913.       {
  914.  
  915.       str_btoc( cbuf1, &( CURTASK excs[ CURTASK exsc ].expression.sval ) );
  916.       str_btoc( cbuf2, &( minvalue.sval ) );
  917.  
  918. #if INTENSIVE_DEBUG
  919.       sprintf( bwb_ebuf, "in bwb_case(): compare strings <%s> and <%s>",
  920.      cbuf1, cbuf2 );
  921.       bwb_debug( bwb_ebuf );
  922. #endif
  923.  
  924.       if ( strncmp( cbuf1, cbuf2, MAXSTRINGSIZE ) == 0 )
  925.      {
  926. #if INTENSIVE_DEBUG
  927.      sprintf( bwb_ebuf, "in bwb_case(): string comparison returns TRUE" );
  928.      bwb_debug( bwb_ebuf );
  929. #endif
  930.      CURTASK excs[ CURTASK exsc ].code = EXEC_SELTRUE;
  931.  
  932. #if MULTISEG_LINES
  933.          adv_eos( l->buffer, &( l->position ));
  934. #endif
  935.      return bwb_zline( l );
  936.      }
  937.  
  938.       else
  939.      {
  940. #if INTENSIVE_DEBUG
  941.      sprintf( bwb_ebuf, "in bwb_case(): string comparison returns FALSE" );
  942.      bwb_debug( bwb_ebuf );
  943. #endif
  944.      retline = find_case( l );
  945.      retline->position = 0;
  946.      return retline;
  947.      }
  948.  
  949.       }
  950.  
  951.    /* not a string; advance */
  952.  
  953.    adv_ws( l->buffer, &( l->position ));
  954.  
  955.    /* check for TO */
  956.  
  957.    if ( is_eol( l->buffer, &( l->position )) != TRUE )
  958.       {
  959.  
  960.       /* find the TO statement */
  961.  
  962.       adv_element( l->buffer, &( l->position ), tbuf );
  963.       bwb_strtoupper( tbuf );
  964.       if ( strcmp( tbuf, CMD_TO ) != 0 )
  965.          {
  966. #if PROG_ERRORS
  967.          sprintf( bwb_ebuf, "CASE has inexplicable code following expression" );
  968.          bwb_error( bwb_ebuf );
  969. #else
  970.          bwb_error( err_syntax );
  971.  
  972. #if MULTISEG_LINES
  973.          adv_eos( l->buffer, &( l->position ));
  974. #endif
  975.          return bwb_zline( l );
  976. #endif
  977.          }
  978.  
  979.       /* now evaluate the MAX expression */
  980.  
  981.       maxval = bwb_exp( l->buffer, FALSE, &( l->position ));
  982.  
  983.       }
  984.  
  985.    /* evaluate the expression */
  986.  
  987.    if ( case_eval( &( CURTASK excs[ CURTASK exsc ].expression ),
  988.       minval, maxval ) == TRUE )
  989.       {
  990. #if INTENSIVE_DEBUG
  991.       sprintf( bwb_ebuf, "in bwb_case(): evaluation returns TRUE" );
  992.       bwb_debug( bwb_ebuf );
  993. #endif
  994.       CURTASK excs[ CURTASK exsc ].code = EXEC_SELTRUE;
  995.  
  996. #if MULTISEG_LINES
  997.       adv_eos( l->buffer, &( l->position ));
  998. #endif
  999.       return bwb_zline( l );
  1000.       }
  1001.  
  1002.    /* evaluation returns a FALSE value; find next CASE or END SELECT statement */
  1003.  
  1004.    else
  1005.       {
  1006. #if INTENSIVE_DEBUGb
  1007.       sprintf( bwb_ebuf, "in bwb_case(): evaluation returns FALSE" );
  1008.       bwb_debug( bwb_ebuf );
  1009. #endif
  1010.       retline = find_case( l );
  1011.       retline->position = 0;
  1012.       return retline;
  1013.       }
  1014.  
  1015.    }
  1016.  
  1017. /***************************************************************
  1018.  
  1019.         FUNCTION:       bwb_caseif()
  1020.  
  1021.         DESCRIPTION:    This C function handles the BASIC CASE IF
  1022.                         statement.
  1023.  
  1024. ***************************************************************/
  1025.  
  1026. #if ANSI_C
  1027. static struct bwb_line *
  1028. bwb_caseif( struct bwb_line *l )
  1029. #else
  1030. static struct bwb_line *
  1031. bwb_caseif( l )
  1032.    struct bwb_line *l;
  1033. #endif
  1034.    {
  1035.    char tbuf[ MAXSTRINGSIZE + 1 ];
  1036.    int position;
  1037.    struct exp_ese *r;
  1038.    struct bwb_line *retline;
  1039.  
  1040.    if ( CURTASK excs[ CURTASK exsc ].expression.type == NUMBER )
  1041.       {
  1042.       sprintf( tbuf, "%f %s",
  1043.          (float) CURTASK excs[ CURTASK exsc ].expression.nval,
  1044.          &( l->buffer[ l->position ] ) );
  1045.       }
  1046.    else
  1047.       {
  1048.       bwb_error( err_mismatch );
  1049. #if MULTISEG_LINES
  1050.       adv_eos( l->buffer, &( l->position ));
  1051. #endif
  1052.       return bwb_zline( l );
  1053.       }
  1054.  
  1055.    position = 0;
  1056.    r = bwb_exp( tbuf, FALSE, &position );
  1057.  
  1058.    if ( r->nval == (bnumber) TRUE )
  1059.       {
  1060.       CURTASK excs[ CURTASK exsc ].code = EXEC_SELTRUE;
  1061.  
  1062. #if MULTISEG_LINES
  1063.       adv_eos( l->buffer, &( l->position ));
  1064. #endif
  1065.       return bwb_zline( l );
  1066.       }
  1067.    else
  1068.       {
  1069.       retline = find_case( l );
  1070.       retline->position = 0;
  1071.       return retline;
  1072.       }
  1073.  
  1074.    }
  1075.  
  1076. /***************************************************************
  1077.  
  1078.         FUNCTION:       case_eval()
  1079.  
  1080.         DESCRIPTION:    This function evaluates a case statement
  1081.             by comparing minimum and maximum values
  1082.             with a set expression. It returns either
  1083.             TRUE or FALSE
  1084.  
  1085. ***************************************************************/
  1086.  
  1087. #if ANSI_C
  1088. static int
  1089. case_eval( struct exp_ese *expression, struct exp_ese *minval,
  1090.    struct exp_ese *maxval )
  1091. #else
  1092. static int
  1093. case_eval( expression, minval, maxval )
  1094.    struct exp_ese *expression;
  1095.    struct exp_ese *minval;
  1096.    struct exp_ese *maxval;
  1097. #endif
  1098.    {
  1099.  
  1100.    /* string value */
  1101.  
  1102.    if ( expression->type == STRING )
  1103.       {
  1104.       bwb_error( err_mismatch );
  1105.       return FALSE;
  1106.       }
  1107.  
  1108.    /* numerical value */
  1109.  
  1110. #if INTENSIVE_DEBUG
  1111.    sprintf( bwb_ebuf, "in case_eval(): n <%f> min <%f> max <%f>",
  1112.       (float) expression->nval,
  1113.       (float) minval->nval,
  1114.       (float) maxval->nval );
  1115.    bwb_debug( bwb_ebuf );
  1116. #endif
  1117.  
  1118.    if (  ( expression->nval >= minval->nval )
  1119.       && ( expression->nval <= maxval->nval ))
  1120.       {
  1121.       return TRUE;
  1122.       }
  1123.  
  1124.    return FALSE;
  1125.  
  1126.    }
  1127.  
  1128. /***************************************************************
  1129.  
  1130.         FUNCTION:       find_case()
  1131.  
  1132.         DESCRIPTION:    This function searches for a line containing
  1133.                         a CASE statement corresponding to a previous
  1134.                         SELECT CASE statement.
  1135.  
  1136. ***************************************************************/
  1137.  
  1138. #if ANSI_C
  1139. static struct bwb_line *
  1140. find_case( struct bwb_line *l )
  1141. #else
  1142. static struct bwb_line *
  1143. find_case( l )
  1144.    struct bwb_line *l;
  1145. #endif
  1146.    {
  1147.    struct bwb_line *current;
  1148.    register int c_level;
  1149.    int position;
  1150.  
  1151.    c_level = 1;
  1152.    for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  1153.       {
  1154.       position = 0;
  1155.       if ( current->marked != TRUE )
  1156.          {
  1157.          line_start( current->buffer, &position, &( current->lnpos ),
  1158.             &( current->lnum ),
  1159.             &( current->cmdpos ),
  1160.             &( current->cmdnum ),
  1161.             &( current->startpos ) );
  1162.          }
  1163.       current->position = current->startpos;
  1164.  
  1165.       if ( current->cmdnum > -1 )
  1166.          {
  1167.  
  1168.          if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_select )
  1169.             {
  1170.             ++c_level;
  1171.  
  1172. #if INTENSIVE_DEBUG
  1173.             sprintf( bwb_ebuf, "in find_case(): found SELECT at line %d, level %d",
  1174.                current->number, c_level );
  1175.             bwb_debug( bwb_ebuf );
  1176. #endif
  1177.  
  1178.             }
  1179.          else if ( is_endselect( current ) == TRUE )
  1180.             {
  1181.             --c_level;
  1182.  
  1183. #if INTENSIVE_DEBUG
  1184.             sprintf( bwb_ebuf, "in find_endif(): found END SELECT at line %d, level %d",
  1185.                current->number, c_level );
  1186.             bwb_debug( bwb_ebuf );
  1187. #endif
  1188.  
  1189.             if ( c_level == 0 )
  1190.                {
  1191.                return current;
  1192.                }
  1193.             }
  1194.  
  1195.          else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_case )
  1196.             {
  1197.             --c_level;
  1198.  
  1199. #if INTENSIVE_DEBUG
  1200.             sprintf( bwb_ebuf, "in find_case(): found CASE at line %d, level %d",
  1201.                current->number, c_level );
  1202.             bwb_debug( bwb_ebuf );
  1203. #endif
  1204.  
  1205.             if ( c_level == 0 )
  1206.                {
  1207.                return current;
  1208.                }
  1209.             }
  1210.          }
  1211.       }
  1212.  
  1213. #if PROG_ERRORS
  1214.    sprintf( bwb_ebuf, "SELECT without CASE" );
  1215.    bwb_error( bwb_ebuf );
  1216. #else
  1217.    bwb_error( err_syntax  );
  1218. #endif
  1219.  
  1220.    return NULL;
  1221.  
  1222.    }
  1223.  
  1224. /***************************************************************
  1225.  
  1226.         FUNCTION:       find_case()
  1227.  
  1228.         DESCRIPTION:    This function searches for a line containing
  1229.                         an END SELECT statement corresponding to a previous
  1230.                         SELECT CASE statement.
  1231.  
  1232. ***************************************************************/
  1233.  
  1234. #if ANSI_C
  1235. static struct bwb_line *
  1236. find_endselect( struct bwb_line *l )
  1237. #else
  1238. static struct bwb_line *
  1239. find_endselect( l )
  1240.    struct bwb_line *l;
  1241. #endif
  1242.    {
  1243.    struct bwb_line *current;
  1244.    register int c_level;
  1245.    int position;
  1246.  
  1247.    c_level = 1;
  1248.    for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  1249.       {
  1250.       position = 0;
  1251.       if ( current->marked != TRUE )
  1252.          {
  1253.          line_start( current->buffer, &position, &( current->lnpos ),
  1254.             &( current->lnum ),
  1255.             &( current->cmdpos ),
  1256.             &( current->cmdnum ),
  1257.             &( current->startpos ) );
  1258.          }
  1259.       current->position = current->startpos;
  1260.  
  1261.       if ( current->cmdnum > -1 )
  1262.          {
  1263.  
  1264.          if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_select )
  1265.             {
  1266.             ++c_level;
  1267.  
  1268. #if INTENSIVE_DEBUG
  1269.             sprintf( bwb_ebuf, "in find_case(): found SELECT at line %d, level %d",
  1270.                current->number, c_level );
  1271.             bwb_debug( bwb_ebuf );
  1272. #endif
  1273.  
  1274.             }
  1275.          else if ( is_endselect( current ) == TRUE )
  1276.             {
  1277.             --c_level;
  1278.  
  1279. #if INTENSIVE_DEBUG
  1280.             sprintf( bwb_ebuf, "in find_endif(): found END SELECT at line %d, level %d",
  1281.                current->number, c_level );
  1282.             bwb_debug( bwb_ebuf );
  1283. #endif
  1284.  
  1285.             if ( c_level == 0 )
  1286.                {
  1287.                return current;
  1288.                }
  1289.             }
  1290.          }
  1291.       }
  1292.  
  1293. #if PROG_ERRORS
  1294.    sprintf( bwb_ebuf, "SELECT without END SELECT" );
  1295.    bwb_error( bwb_ebuf );
  1296. #else
  1297.    bwb_error( err_syntax  );
  1298. #endif
  1299.  
  1300.    return NULL;
  1301.  
  1302.    }
  1303.  
  1304. /***************************************************************
  1305.  
  1306.     FUNCTION:       is_endselect()
  1307.  
  1308.     DESCRIPTION:    This C function attempts to determine if
  1309.             a given line contains an END SELECT statement.
  1310.  
  1311. ***************************************************************/
  1312.  
  1313. #if ANSI_C
  1314. static int
  1315. is_endselect( struct bwb_line *l )
  1316. #else
  1317. static int
  1318. is_endselect( l )
  1319.    struct bwb_line *l;
  1320. #endif
  1321.    {
  1322.    int position;
  1323.    char tbuf[ MAXVARNAMESIZE + 1];
  1324.  
  1325.    if ( bwb_cmdtable[ l->cmdnum ].vector != bwb_xend )
  1326.       {
  1327.       return FALSE;
  1328.       }
  1329.  
  1330.    position = l->startpos;
  1331.    adv_ws( l->buffer, &position );
  1332.    adv_element( l->buffer, &position, tbuf );
  1333.    bwb_strtoupper( tbuf );
  1334.  
  1335.    if ( strcmp( tbuf, "SELECT" ) == 0 )
  1336.       {
  1337.       return TRUE;
  1338.       }
  1339.  
  1340.    return FALSE;
  1341.  
  1342.    }
  1343.  
  1344. /***************************************************************
  1345.  
  1346.         FUNCTION:       bwb_endselect()
  1347.  
  1348.         DESCRIPTION:    This function handles the BASIC END
  1349.                         SELECT statement.
  1350.  
  1351.     SYNTAX:        END SELECT
  1352.  
  1353. ***************************************************************/
  1354.  
  1355. #if ANSI_C
  1356. struct bwb_line *
  1357. bwb_endselect( struct bwb_line *l )
  1358. #else
  1359. struct bwb_line *
  1360. bwb_endselect( l )
  1361.    struct bwb_line *l;
  1362. #endif
  1363.    {
  1364.  
  1365. #if INTENSIVE_DEBUG
  1366.    sprintf( bwb_ebuf, "in bwb_endselect(): entered function" );
  1367.    bwb_debug( bwb_ebuf );
  1368. #endif
  1369.  
  1370.    if (  ( CURTASK excs[ CURTASK exsc ].code != EXEC_SELTRUE  )
  1371.       && ( CURTASK excs[ CURTASK exsc ].code != EXEC_SELFALSE ))
  1372.       {
  1373. #if PROG_ERRORS
  1374.       sprintf( bwb_ebuf, "in bwb_endselect(): END SELECT without SELECT" );
  1375.       bwb_error( bwb_ebuf );
  1376. #else
  1377.       bwb_error( err_syntax );
  1378. #endif
  1379.       }
  1380.  
  1381.    bwb_decexec();
  1382.  
  1383.  
  1384. #if MULTISEG_LINES
  1385.    adv_eos( l->buffer, &( l->position ));
  1386. #endif
  1387.    return bwb_zline( l );
  1388.    }
  1389.  
  1390. #endif                /* STRUCT_CMDS */
  1391.  
  1392. #if COMMON_CMDS || STRUCT_CMDS
  1393.  
  1394. /***    WHILE-WEND ***/
  1395.  
  1396. /***************************************************************
  1397.  
  1398.         FUNCTION:       bwb_while()
  1399.  
  1400.         DESCRIPTION:    This function handles the BASIC WHILE
  1401.             statement and also the ANSI DO WHILE
  1402.             statement.
  1403.  
  1404.     SYNTAX:        WHILE expression
  1405.             DO WHILE expression
  1406.  
  1407. ***************************************************************/
  1408.  
  1409. #if ANSI_C
  1410. struct bwb_line *
  1411. bwb_while( struct bwb_line *l )
  1412. #else
  1413. struct bwb_line *
  1414. bwb_while( l )
  1415.    struct bwb_line *l;
  1416. #endif
  1417.    {
  1418.    struct exp_ese *e;
  1419.    struct bwb_line *r;
  1420.  
  1421.    /* call bwb_exp() to interpret the expression */
  1422.  
  1423.    e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  1424.  
  1425.    if ( (int) exp_getnval( e ) == TRUE )
  1426.       {
  1427.  
  1428.       /* if this is the first time at this WHILE statement, note it */
  1429.  
  1430.       if ( CURTASK excs[ CURTASK exsc ].while_line != l )
  1431.          {
  1432.  
  1433.          bwb_incexec();
  1434.          CURTASK excs[ CURTASK exsc ].while_line = l;
  1435.  
  1436.          /* find the WEND statement (or LOOP statement) */
  1437.  
  1438. #if STRUCT_CMDS
  1439.      if ( l->cmdnum == getcmdnum( CMD_DO ))
  1440.             {
  1441.         CURTASK excs[ CURTASK exsc ].wend_line = find_loop( l );
  1442.             }
  1443.          else
  1444.             {
  1445.         CURTASK excs[ CURTASK exsc ].wend_line = find_wend( l );
  1446.         }
  1447. #else
  1448.      CURTASK excs[ CURTASK exsc ].wend_line = find_wend( l );
  1449. #endif
  1450.  
  1451.          if ( CURTASK excs[ CURTASK exsc ].wend_line == NULL )
  1452.             {
  1453.             return bwb_zline( l );
  1454.             }
  1455.  
  1456. #if INTENSIVE_DEBUG
  1457.          sprintf( bwb_ebuf, "in bwb_while(): initialize WHILE loop, line <%d>",
  1458.             l->number );
  1459.          bwb_debug( bwb_ebuf );
  1460. #endif
  1461.  
  1462.          }
  1463. #if INTENSIVE_DEBUG
  1464.       else
  1465.          {
  1466.          sprintf( bwb_ebuf, "in bwb_while(): return to WHILE loop, line <%d>",
  1467.             l->number );
  1468.          bwb_debug( bwb_ebuf );
  1469.          }
  1470. #endif
  1471.  
  1472.       bwb_setexec( l, l->position, EXEC_WHILE );
  1473.       return bwb_zline( l );
  1474.       }
  1475.    else
  1476.       {
  1477.       CURTASK excs[ CURTASK exsc ].while_line = NULL;
  1478.       r = CURTASK excs[ CURTASK exsc ].wend_line;
  1479.       bwb_setexec( r, 0, CURTASK excs[ CURTASK exsc - 1 ].code );
  1480.       r->position = 0;
  1481.       bwb_decexec();
  1482.       return r;
  1483.       }
  1484.  
  1485.    }
  1486.  
  1487. /***************************************************************
  1488.  
  1489.         FUNCTION:       bwb_wend()
  1490.  
  1491.         DESCRIPTION:    This function handles the BASIC WEND
  1492.             statement and the LOOP statement ending
  1493.             a DO WHILE loop.
  1494.  
  1495.     SYNTAX:        WEND
  1496.             LOOP
  1497.  
  1498. ***************************************************************/
  1499.  
  1500. #if ANSI_C
  1501. struct bwb_line *
  1502. bwb_wend( struct bwb_line *l )
  1503. #else
  1504. struct bwb_line *
  1505. bwb_wend( l )
  1506.    struct bwb_line *l;
  1507. #endif
  1508.    {
  1509.  
  1510.    /* check integrity of WHILE loop */
  1511.  
  1512.    if ( CURTASK excs[ CURTASK exsc ].code != EXEC_WHILE )
  1513.       {
  1514. #if PROG_ERRORS
  1515.       sprintf( bwb_ebuf, "in bwb_wend(): exec stack code != EXEC_WHILE" );
  1516.       bwb_error( bwb_ebuf );
  1517. #else
  1518.       bwb_error( err_syntax );
  1519. #endif
  1520.       }
  1521.  
  1522.    if ( CURTASK excs[ CURTASK exsc ].while_line == NULL )
  1523.       {
  1524. #if PROG_ERRORS
  1525.       sprintf( bwb_ebuf, "in bwb_wend(): exec stack while_line == NULL" );
  1526.       bwb_error( bwb_ebuf );
  1527. #else
  1528.       bwb_error( err_syntax );
  1529. #endif
  1530.       }
  1531.  
  1532.    /* reset to the top of the current WHILE loop */
  1533.  
  1534. #if INTENSIVE_DEBUG
  1535.    sprintf( bwb_ebuf, "in bwb_wend() return to line <%d>",
  1536.       CURTASK excs[ CURTASK exsc ].while_line->number );
  1537.    bwb_debug( bwb_ebuf );
  1538. #endif
  1539.  
  1540.    CURTASK excs[ CURTASK exsc ].while_line->position = 0;
  1541.    bwb_setexec( CURTASK excs[ CURTASK exsc ].while_line, 0, EXEC_WHILE );
  1542.  
  1543.    return CURTASK excs[ CURTASK exsc ].while_line;
  1544.  
  1545.    }
  1546.  
  1547. /***************************************************************
  1548.  
  1549.         FUNCTION:       find_wend()
  1550.  
  1551.         DESCRIPTION:    This function searches for a line containing
  1552.                         a WEND statement corresponding to a previous
  1553.                         WHILE statement.
  1554.  
  1555. ***************************************************************/
  1556.  
  1557. #if ANSI_C
  1558. static struct bwb_line *
  1559. find_wend( struct bwb_line *l )
  1560. #else
  1561. static struct bwb_line *
  1562. find_wend( l )
  1563.    struct bwb_line *l;
  1564. #endif
  1565.    {
  1566.    struct bwb_line *current;
  1567.    register int w_level;
  1568.    int position;
  1569.  
  1570.    w_level = 1;
  1571.    for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  1572.       {
  1573.       position = 0;
  1574.       if ( current->marked != TRUE )
  1575.          {
  1576.          line_start( current->buffer, &position, &( current->lnpos ),
  1577.             &( current->lnum ),
  1578.             &( current->cmdpos ),
  1579.             &( current->cmdnum ),
  1580.             &( current->startpos ) );
  1581.          }
  1582.       current->position = current->startpos;
  1583.  
  1584.       if ( current->cmdnum > -1 )
  1585.          {
  1586.  
  1587.          if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_while )
  1588.             {
  1589.             ++w_level;
  1590.  
  1591. #if INTENSIVE_DEBUG
  1592.         sprintf( bwb_ebuf, "in find_wend(): found WHILE at line %d, level %d",
  1593.                current->number, w_level );
  1594.             bwb_debug( bwb_ebuf );
  1595. #endif
  1596.  
  1597.             }
  1598.          else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_wend )
  1599.             {
  1600.             --w_level;
  1601.  
  1602. #if INTENSIVE_DEBUG
  1603.         sprintf( bwb_ebuf, "in find_wend(): found WEND at line %d, level %d",
  1604.                current->number, w_level );
  1605.             bwb_debug( bwb_ebuf );
  1606. #endif
  1607.  
  1608.             if ( w_level == 0 )
  1609.                {
  1610.                return current->next;
  1611.                }
  1612.             }
  1613.          }
  1614.       }
  1615.  
  1616. #if PROG_ERRORS
  1617.    sprintf( bwb_ebuf, "in find_wend(): WHILE without WEND" );
  1618.    bwb_error( bwb_ebuf );
  1619. #else
  1620.    bwb_error( err_syntax  );
  1621. #endif
  1622.  
  1623.    return NULL;
  1624.  
  1625.    }
  1626.  
  1627. #if STRUCT_CMDS
  1628.  
  1629. /***************************************************************
  1630.  
  1631.     FUNCTION:       find_loop()
  1632.  
  1633.     DESCRIPTION:    This function searches for a line containing
  1634.             a LOOP statement corresponding to a previous
  1635.             DO statement.
  1636.  
  1637. ***************************************************************/
  1638.  
  1639. #if ANSI_C
  1640. extern struct bwb_line *
  1641. find_loop( struct bwb_line *l )
  1642. #else
  1643. extern struct bwb_line *
  1644. find_loop( l )
  1645.    struct bwb_line *l;
  1646. #endif
  1647.    {
  1648.    struct bwb_line *current;
  1649.    register int w_level;
  1650.    int position;
  1651.  
  1652.    w_level = 1;
  1653.    for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  1654.       {
  1655.       position = 0;
  1656.       if ( current->marked != TRUE )
  1657.      {
  1658.      line_start( current->buffer, &position, &( current->lnpos ),
  1659.         &( current->lnum ),
  1660.         &( current->cmdpos ),
  1661.         &( current->cmdnum ),
  1662.         &( current->startpos ) );
  1663.      }
  1664.       current->position = current->startpos;
  1665.  
  1666.       if ( current->cmdnum > -1 )
  1667.      {
  1668.  
  1669.      if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_do )
  1670.         {
  1671.         ++w_level;
  1672.  
  1673. #if INTENSIVE_DEBUG
  1674.         sprintf( bwb_ebuf, "in find_loop(): found DO at line %d, level %d",
  1675.            current->number, w_level );
  1676.         bwb_debug( bwb_ebuf );
  1677. #endif
  1678.  
  1679.         }
  1680.      else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_loop )
  1681.         {
  1682.         --w_level;
  1683.  
  1684. #if INTENSIVE_DEBUG
  1685.         sprintf( bwb_ebuf, "in fnd_loop(): found LOOP at line %d, level %d",
  1686.            current->number, w_level );
  1687.         bwb_debug( bwb_ebuf );
  1688. #endif
  1689.  
  1690.         if ( w_level == 0 )
  1691.            {
  1692.            return current->next;
  1693.            }
  1694.         }
  1695.      }
  1696.       }
  1697.  
  1698. #if PROG_ERRORS
  1699.    sprintf( bwb_ebuf, "in find_loop(): DO without LOOP" );
  1700.    bwb_error( bwb_ebuf );
  1701. #else
  1702.    bwb_error( err_syntax  );
  1703. #endif
  1704.  
  1705.    return NULL;
  1706.  
  1707.    }
  1708.  
  1709. #endif                          /* STRUCT_CMDS */
  1710.  
  1711. #endif                          /* COMMON_CMDS || STRUCT_CMDS */
  1712.  
  1713. /***    FOR-NEXT ***/
  1714.  
  1715. /***************************************************************
  1716.  
  1717.         FUNCTION:       bwb_for()
  1718.  
  1719.         DESCRIPTION:    This function handles the BASIC FOR
  1720.                         statement.
  1721.  
  1722.     SYNTAX:        FOR counter = start TO finish [STEP increment]
  1723.  
  1724. ***************************************************************/
  1725.  
  1726. #if ANSI_C
  1727. struct bwb_line *
  1728. bwb_for( struct bwb_line *l )
  1729. #else
  1730. struct bwb_line *
  1731. bwb_for( l )
  1732.    struct bwb_line *l;
  1733. #endif
  1734.    {
  1735.    register int n;
  1736.    int e, loop;
  1737.    int to, step, p;
  1738.    int for_step, for_target;
  1739.    struct exp_ese *exp;
  1740.    struct bwb_variable *v;
  1741.    char tbuf[ MAXSTRINGSIZE + 1 ];
  1742.  
  1743.    /* get the variable name */
  1744.  
  1745.    exp_getvfname( &( l->buffer[ l->position ] ), tbuf );
  1746.    l->position += strlen( tbuf );
  1747.    v = var_find( tbuf );
  1748.  
  1749. #if INTENSIVE_DEBUG
  1750.    sprintf( bwb_ebuf, "in bwb_for(): variable name <%s>.", v->name );
  1751.    bwb_debug( bwb_ebuf );
  1752. #endif
  1753.  
  1754.    /* at this point one should find an equals sign ('=') */
  1755.  
  1756.    adv_ws( l->buffer, &( l->position ) );
  1757.  
  1758.    if ( l->buffer[ l->position ] != '=' )
  1759.       {
  1760. #if PROG_ERRORS
  1761.       sprintf( bwb_ebuf, "in bwb_for(): failed to find equals sign, buf <%s>",
  1762.          &( l->buffer[ l->position ] ) );
  1763.       bwb_error( bwb_ebuf );
  1764. #else
  1765.       bwb_error( err_syntax );
  1766. #endif
  1767.       return bwb_zline( l );
  1768.       }
  1769.    else
  1770.       {
  1771.       ++( l->position );
  1772.       }
  1773.  
  1774.    /* Find the TO and STEP statements */
  1775.  
  1776.    cnd_tostep( l->buffer, l->position, &to, &step );
  1777.  
  1778.    /* if there is no TO statement, then an error has ocurred */
  1779.  
  1780.    if ( to < 1 )
  1781.       {
  1782. #if PROG_ERRORS
  1783.       sprintf( bwb_ebuf, "FOR statement without TO" );
  1784.       bwb_error( bwb_ebuf );
  1785. #else
  1786.       bwb_error( err_syntax  );
  1787. #endif
  1788.       return bwb_zline( l );
  1789.       }
  1790.  
  1791.    /* copy initial value to buffer and evaluate it */
  1792.  
  1793.    tbuf[ 0 ] = '¥0';
  1794.    p = 0;
  1795.    for ( n = l->position; n < to; ++n )
  1796.       {
  1797.       tbuf[ p ] = l->buffer[ n ];
  1798.       ++p;
  1799.       ++l->position;
  1800.       tbuf[ p ] = '¥0';
  1801.       }
  1802.  
  1803. #if INTENSIVE_DEBUG
  1804.    sprintf( bwb_ebuf, "in bwb_for(): initial value string <%s>",
  1805.       tbuf );
  1806.    bwb_debug( bwb_ebuf );
  1807. #endif
  1808.  
  1809.    p = 0;
  1810.    exp = bwb_exp( tbuf, FALSE, &p );
  1811.    var_setnval( v, exp_getnval( exp ) );
  1812.  
  1813. #if INTENSIVE_DEBUG
  1814.    sprintf( bwb_ebuf, "in bwb_for(): initial value <%d> pos <%d>",
  1815.       exp_getnval( exp ), l->position );
  1816.    bwb_debug( bwb_ebuf );
  1817. #endif
  1818.  
  1819.    /* copy target value to small buffer and evaluate it */
  1820.  
  1821.    tbuf[ 0 ] = '¥0';
  1822.    p = 0;
  1823.    l->position = to + 2;
  1824.    if ( step < 1 )
  1825.       {
  1826.       e = strlen( l->buffer );
  1827.       }
  1828.    else
  1829.       {
  1830.       e = step - 1;
  1831.       }
  1832.  
  1833.    loop = TRUE;
  1834.    n = l->position;
  1835.    while( loop == TRUE )
  1836.       {
  1837.       tbuf[ p ] = l->buffer[ n ];
  1838.       ++p;
  1839.       ++l->position;
  1840.       tbuf[ p ] = '¥0';
  1841.  
  1842.       if ( n >= e )
  1843.           {
  1844.           loop = FALSE;
  1845.           }
  1846.  
  1847.       ++n;
  1848.  
  1849.       if ( l->buffer[ n ] == ':' )
  1850.          {
  1851.          loop = FALSE;
  1852.          }
  1853.  
  1854.       }
  1855.  
  1856. #if INTENSIVE_DEBUG
  1857.    sprintf( bwb_ebuf, "in bwb_for(): target value string <%s>",
  1858.       tbuf );
  1859.    bwb_debug( bwb_ebuf );
  1860. #endif
  1861.  
  1862.    p = 0;
  1863.    exp = bwb_exp( tbuf, FALSE, &p );
  1864.    for_target = (int) exp_getnval( exp );
  1865.  
  1866. #if INTENSIVE_DEBUG
  1867.    sprintf( bwb_ebuf, "in bwb_for(): target value <%d> pos <%d>",
  1868.       exp_getnval( exp ), l->position );
  1869.    bwb_debug( bwb_ebuf );
  1870. #endif
  1871.  
  1872.    /* If there is a STEP statement, copy it to a buffer
  1873.       and evaluate it */
  1874.  
  1875.    if ( step > 1 )
  1876.       {
  1877.       tbuf[ 0 ] = '¥0';
  1878.       p = 0;
  1879.       l->position = step + 4;
  1880.  
  1881.       for ( n = l->position; n < (int) strlen( l->buffer ); ++n )
  1882.          {
  1883.          tbuf[ p ] = l->buffer[ n ];
  1884.          ++p;
  1885.          ++l->position;
  1886.          tbuf[ p ] = '¥0';
  1887.          }
  1888.  
  1889. #if INTENSIVE_DEBUG
  1890.       sprintf( bwb_ebuf, "in bwb_for(): step value string <%s>",
  1891.          tbuf );
  1892.       bwb_debug( bwb_ebuf );
  1893. #endif
  1894.  
  1895.       p = 0;
  1896.       exp = bwb_exp( tbuf, FALSE, &p );
  1897.       for_step = (int) exp_getnval( exp );
  1898.  
  1899.       }
  1900.    else
  1901.       {
  1902.       for_step = 1;
  1903.       }
  1904.  
  1905.  
  1906. #if INTENSIVE_DEBUG
  1907.    sprintf( bwb_ebuf, "in bwb_for(): step value <%d>",
  1908.       for_step );
  1909.    bwb_debug( bwb_ebuf );
  1910. #endif
  1911.  
  1912.    /* set position in current line and increment EXEC counter */
  1913.  
  1914.    /* bwb_setexec( l, l->position, EXEC_NORM ); */  /* WRONG */
  1915.    bwb_incexec();
  1916.  
  1917.    CURTASK excs[ CURTASK exsc ].local_variable  = v;
  1918.    CURTASK excs[ CURTASK exsc ].for_step   = for_step;
  1919.    CURTASK excs[ CURTASK exsc ].for_target = for_target;
  1920.  
  1921.    /* set exit line to be used by EXIT FOR */
  1922.  
  1923. #if STRUCT_CMDS
  1924.    CURTASK excs[ CURTASK exsc ].wend_line  = find_next( l );
  1925. #endif
  1926.  
  1927.    /* set top line and position to be used in multisegmented FOR-NEXT loop */
  1928.  
  1929. #if MULTISEG_LINES
  1930.    CURTASK excs[ CURTASK exsc ].for_line     = l;
  1931.    CURTASK excs[ CURTASK exsc ].for_position = l->position;
  1932. #endif
  1933.  
  1934. #if INTENSIVE_DEBUG
  1935.    sprintf( bwb_ebuf, "in bwb_for(): setting code to EXEC_FOR",
  1936.       l->position );
  1937.    bwb_debug( bwb_ebuf );
  1938. #endif
  1939.  
  1940.    bwb_setexec( l, l->position, EXEC_FOR );
  1941.  
  1942. #if INTENSIVE_DEBUG
  1943.    sprintf( bwb_ebuf, "in bwb_for(): ready to exit, position <%d>",
  1944.       l->position );
  1945.    bwb_debug( bwb_ebuf );
  1946. #endif
  1947.  
  1948.    /* proceed with processing */
  1949.  
  1950.    return bwb_zline( l );
  1951.  
  1952.    }
  1953.  
  1954. /***************************************************************
  1955.  
  1956.         FUNCTION:       bwb_next()
  1957.  
  1958.         DESCRIPTION:    This function handles the BASIC NEXT
  1959.                         statement.
  1960.  
  1961.     SYNTAX:        NEXT counter
  1962.  
  1963. ***************************************************************/
  1964.  
  1965. #if ANSI_C
  1966. struct bwb_line *
  1967. bwb_next( struct bwb_line *l )
  1968. #else
  1969. struct bwb_line *
  1970. bwb_next( l )
  1971.    struct bwb_line *l;
  1972. #endif
  1973.    {
  1974.    char tbuf[ MAXSTRINGSIZE + 1 ];
  1975. #if INTENSIVE_DEBUG
  1976.    struct bwb_variable *v;
  1977. #endif
  1978.  
  1979. #if INTENSIVE_DEBUG
  1980.    sprintf( bwb_ebuf, "in bwb_next(): entered function, cmdnum <%d> exsc level <%d> code <%d>",
  1981.       l->cmdnum, CURTASK exsc, CURTASK excs[ CURTASK exsc ].code );
  1982.    bwb_debug( bwb_ebuf );
  1983. #endif
  1984.  
  1985.    /* Check the integrity of the FOR statement */
  1986.  
  1987.    if ( CURTASK excs[ CURTASK exsc ].code != EXEC_FOR )
  1988.       {
  1989. #if PROG_ERRORS
  1990.       sprintf( bwb_ebuf, "in bwb_next(): NEXT without FOR; code is <%d> instead of <%d>",
  1991.      CURTASK excs[ CURTASK exsc ].code, EXEC_FOR );
  1992.       bwb_error( bwb_ebuf );
  1993. #else
  1994.       bwb_error( err_syntax );
  1995. #endif
  1996.       }
  1997.  
  1998.    /* read the argument, if there is one */
  1999.  
  2000. #if MULTISEG_LINES                   /* not currently needed otherwise */
  2001.  
  2002.    exp_getvfname( &( l->buffer[ l->position ] ), tbuf );
  2003.    l->position += strlen( tbuf );
  2004.  
  2005. #if INTENSIVE_DEBUG
  2006.    v = var_find( tbuf );
  2007.    sprintf( bwb_ebuf, "in bwb_next(): variable name detected <%s>.", v->name );
  2008.    bwb_debug( bwb_ebuf );
  2009. #endif
  2010. #endif
  2011.  
  2012.    /* decrement or increment the value */
  2013.  
  2014.    var_setnval( CURTASK excs[ CURTASK exsc ].local_variable,
  2015.       var_getnval( CURTASK excs[ CURTASK exsc ].local_variable )
  2016.       + (bnumber) CURTASK excs[ CURTASK exsc ].for_step );
  2017.  
  2018.    /* check for completion of the loop */
  2019.  
  2020.    if ( CURTASK excs[ CURTASK exsc ].for_step > 0 )            /* if step is positive */
  2021.       {
  2022.       if ( (int) var_getnval( CURTASK excs[ CURTASK exsc ].local_variable )
  2023.          > CURTASK excs[ CURTASK exsc ].for_target )
  2024.          {
  2025.          bwb_decexec();
  2026. #if MULTISEG_LINES
  2027.      bwb_setexec( l, l->position, CURTASK excs[ CURTASK exsc ].code );
  2028. #else
  2029.      bwb_setexec( l->next, 0, CURTASK excs[ CURTASK exsc ].code );
  2030. #endif
  2031.  
  2032. #if INTENSIVE_DEBUG
  2033.      sprintf( bwb_ebuf, "in bwb_next(): end of loop" );
  2034.      bwb_debug( bwb_ebuf );
  2035. #endif
  2036.  
  2037. #ifdef OLD_WAY
  2038.      l->next->position = 0;
  2039.      return l->next;
  2040. #else
  2041.      return bwb_zline( l );
  2042. #endif
  2043.          }
  2044.       }
  2045.    else                                         /* if step is negative */
  2046.       {
  2047.       if ( (int) var_getnval( CURTASK excs[ CURTASK exsc ].local_variable )
  2048.          < CURTASK excs[ CURTASK exsc ].for_target )
  2049.          {
  2050.          bwb_decexec();
  2051.      bwb_setexec( l->next, 0, CURTASK excs[ CURTASK exsc ].code );
  2052.  
  2053. #if INTENSIVE_DEBUG
  2054.      sprintf( bwb_ebuf, "in bwb_next(): end of loop" );
  2055.      bwb_debug( bwb_ebuf );
  2056. #endif
  2057.  
  2058. #ifdef OLD_WAY
  2059.      l->next->position = 0;
  2060.      return l->next;
  2061. #else
  2062.      return bwb_zline( l );
  2063. #endif
  2064.          }
  2065.       }
  2066.  
  2067.    /* Target not reached: return to the top of the FOR loop */
  2068.  
  2069. #if INTENSIVE_DEBUG
  2070.    sprintf( bwb_ebuf, "in bwb_next(): resetting code to EXEC_FOR",
  2071.       l->position );
  2072.    bwb_debug( bwb_ebuf );
  2073. #endif
  2074.  
  2075. #if MULTISEG_LINES
  2076.    CURTASK excs[ CURTASK exsc ].for_line->position
  2077.       = CURTASK excs[ CURTASK exsc ].for_position;
  2078.    bwb_setexec( CURTASK excs[ CURTASK exsc ].for_line,
  2079.       CURTASK excs[ CURTASK exsc ].for_position, EXEC_FOR );
  2080. #else
  2081.    bwb_setexec( CURTASK excs[ CURTASK exsc - 1 ].line,
  2082.       CURTASK excs[ CURTASK exsc - 1 ].position, EXEC_FOR );
  2083. #endif
  2084.  
  2085.    return CURTASK excs[ CURTASK exsc - 1 ].line;
  2086.  
  2087.    }
  2088.  
  2089. #if STRUCT_CMDS
  2090.  
  2091. /***************************************************************
  2092.  
  2093.     FUNCTION:       bwb_exitfor()
  2094.  
  2095.     DESCRIPTION:    This function handles the BASIC EXIT
  2096.             FOR statement.  This is a structured
  2097.             programming command compatible with ANSI
  2098.             BASIC. It is called from the bwb_exit()
  2099.             subroutine.
  2100.  
  2101.     SYNTAX:        EXIT FOR
  2102.             
  2103. ***************************************************************/
  2104.  
  2105. #if ANSI_C
  2106. struct bwb_line *
  2107. bwb_exitfor( struct bwb_line *l )
  2108. #else
  2109. struct bwb_line *
  2110. bwb_exitfor( l )
  2111.    struct bwb_line *l;
  2112. #endif
  2113.    {
  2114.    struct bwb_line *next_line;
  2115.    int found;
  2116.    register int level;
  2117.  
  2118. #if INTENSIVE_DEBUG
  2119.    sprintf( bwb_ebuf, "in bwb_exitfor(): entered subroutine" );
  2120.    bwb_debug( bwb_ebuf );
  2121. #endif
  2122.  
  2123.    /* Check the integrity of the FOR statement */
  2124.  
  2125.    found = FALSE;
  2126.    level = CURTASK exsc;
  2127.    do
  2128.       {
  2129.       if ( CURTASK excs[ level ].code == EXEC_FOR )
  2130.      {
  2131.      next_line = CURTASK excs[ CURTASK level ].wend_line;
  2132.      found = TRUE;
  2133.      }
  2134.       else
  2135.      {
  2136.      --level;
  2137.      }
  2138.       }
  2139.    while ( ( level >= 0 ) && ( found == FALSE ) );
  2140.  
  2141.    if ( found != TRUE )
  2142.       {
  2143.  
  2144. #if PROG_ERRORS
  2145.       sprintf( bwb_ebuf, "in bwb_exitfor(): EXIT FOR without FOR" );
  2146.       bwb_error( bwb_ebuf );
  2147. #else
  2148.       bwb_error( err_syntax );
  2149. #endif
  2150.  
  2151.       return bwb_zline( l );
  2152.  
  2153.       }
  2154.  
  2155. #if INTENSIVE_DEBUG
  2156.    sprintf( bwb_ebuf, "in bwb_exitfor(): level found is <%d>, current <%d>",
  2157.       level, CURTASK exsc );
  2158.    bwb_debug( bwb_ebuf );
  2159. #endif
  2160.  
  2161.    /* decrement below the level of the NEXT statement */
  2162.  
  2163.    while( CURTASK exsc >= level )
  2164.       {
  2165.       bwb_decexec();
  2166.       }
  2167.  
  2168.    /* set the next line in the exec stack */
  2169.  
  2170.    next_line->position = 0;
  2171.    bwb_setexec( next_line, 0, EXEC_NORM );
  2172.  
  2173.    return next_line;
  2174.  
  2175.    }
  2176.  
  2177. /***************************************************************
  2178.  
  2179.     FUNCTION:       find_next()
  2180.  
  2181.     DESCRIPTION:    This function searches for a line containing
  2182.             a NEXT statement corresponding to a previous
  2183.             FOR statement.
  2184.  
  2185. ***************************************************************/
  2186.  
  2187. #if ANSI_C
  2188. static struct bwb_line *
  2189. find_next( struct bwb_line *l )
  2190. #else
  2191. static struct bwb_line *
  2192. find_next( l )
  2193.    struct bwb_line *l;
  2194. #endif
  2195.    {
  2196.    struct bwb_line *current;
  2197.    register int w_level;
  2198.    int position;
  2199.  
  2200.    w_level = 1;
  2201.    for ( current = l->next; current != &CURTASK bwb_end; current = current->next )
  2202.       {
  2203.       position = 0;
  2204.       if ( current->marked != TRUE )
  2205.      {
  2206.      line_start( current->buffer, &position, &( current->lnpos ),
  2207.         &( current->lnum ),
  2208.         &( current->cmdpos ),
  2209.         &( current->cmdnum ),
  2210.         &( current->startpos ) );
  2211.      }
  2212.       current->position = current->startpos;
  2213.  
  2214.       if ( current->cmdnum > -1 )
  2215.      {
  2216.  
  2217.      if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_for )
  2218.         {
  2219.         ++w_level;
  2220.  
  2221. #if INTENSIVE_DEBUG
  2222.         sprintf( bwb_ebuf, "in find_next(): found FOR at line %d, level %d",
  2223.            current->number, w_level );
  2224.         bwb_debug( bwb_ebuf );
  2225. #endif
  2226.  
  2227.         }
  2228.      else if ( bwb_cmdtable[ current->cmdnum ].vector == bwb_next )
  2229.         {
  2230.         --w_level;
  2231.  
  2232. #if INTENSIVE_DEBUG
  2233.         sprintf( bwb_ebuf, "in find_next(): found NEXT at line %d, level %d",
  2234.            current->number, w_level );
  2235.         bwb_debug( bwb_ebuf );
  2236. #endif
  2237.  
  2238.         if ( w_level == 0 )
  2239.            {
  2240.  
  2241. #if INTENSIVE_DEBUG
  2242.            sprintf( bwb_ebuf, "in find_next(): found returning line <%d>",
  2243.           current->next->number );
  2244.            bwb_debug( bwb_ebuf );
  2245. #endif
  2246.  
  2247.            return current->next;
  2248.            }
  2249.         }
  2250.      }
  2251.       }
  2252.  
  2253. #if PROG_ERRORS
  2254.    sprintf( bwb_ebuf, "FOR without NEXT" );
  2255.    bwb_error( bwb_ebuf );
  2256. #else
  2257.    bwb_error( err_syntax  );
  2258. #endif
  2259.  
  2260.    return NULL;
  2261.  
  2262.    }
  2263.  
  2264. #endif                /* STRUCT_CMDS for EXIT FOR */
  2265.  
  2266. /***************************************************************
  2267.  
  2268.     FUNCTION:    cnd_tostep()
  2269.  
  2270.     DESCRIPTION:    This function searches through the
  2271.             <buffer> beginning at point <position>
  2272.             and attempts to find positions of TO
  2273.             and STEP statements.
  2274.  
  2275. ***************************************************************/
  2276.  
  2277. #if ANSI_C
  2278. static int
  2279. cnd_tostep( char *buffer, int position, int *to, int *step )
  2280. #else
  2281. static int
  2282. cnd_tostep( buffer, position, to, step )
  2283.    char *buffer;
  2284.    int position;
  2285.    int *to;
  2286.    int *step;
  2287. #endif
  2288.    {
  2289.    int loop, t_pos, b_pos, p_word;
  2290.    char tbuf[ MAXSTRINGSIZE + 1 ];
  2291.  
  2292.    /* set then and els to FALSE initially */
  2293.  
  2294.    *to = *step = FALSE;
  2295.  
  2296.    /* loop to find words */
  2297.  
  2298.    p_word = b_pos = position;
  2299.    t_pos = 0;
  2300.    tbuf[ 0 ] = '¥0';
  2301.    loop = TRUE;
  2302.    while ( loop == TRUE )
  2303.       {
  2304.  
  2305.       switch( buffer[ b_pos ] )
  2306.          {
  2307.          case '¥0':                     /* end of string */
  2308.          case ':':            /* end of line segment */
  2309.             return TRUE;
  2310.          case ' ':                      /* whitespace = end of word */
  2311.          case '¥t':
  2312.  
  2313. #if INTENSIVE_DEBUG
  2314.             sprintf( bwb_ebuf, "in cnd_tostep(): word is <%s>", tbuf );
  2315.             bwb_debug( bwb_ebuf );
  2316. #endif
  2317.  
  2318.             if ( strncmp( tbuf, CMD_TO, (size_t) strlen( CMD_TO ) ) == 0 )
  2319.                {
  2320.  
  2321. #if INTENSIVE_DEBUG
  2322.                sprintf( bwb_ebuf, "in cnd_tostep(): TO found at position <%d>.",
  2323.                   p_word );
  2324.                bwb_debug( bwb_ebuf );
  2325. #endif
  2326.  
  2327.                *to = p_word;
  2328.                }
  2329.             else if ( strncmp( tbuf, CMD_STEP, (size_t) strlen( CMD_STEP ) ) == 0 )
  2330.                {
  2331.  
  2332. #if INTENSIVE_DEBUG
  2333.                sprintf( bwb_ebuf, "in cnd_tostep(): STEP found at position <%d>.",
  2334.                   p_word );
  2335.                bwb_debug( bwb_ebuf );
  2336. #endif
  2337.  
  2338.                *step = p_word;
  2339.                }
  2340.             ++b_pos;
  2341.             p_word = b_pos;
  2342.             t_pos = 0;
  2343.             tbuf[ 0 ] = '¥0';
  2344.             break;
  2345.  
  2346.          default:
  2347.             if ( islower( buffer[ b_pos ] ) != FALSE )
  2348.                {
  2349.                tbuf[ t_pos ] = (char) toupper( buffer[ b_pos ] );
  2350.                }
  2351.             else
  2352.                {
  2353.                tbuf[ t_pos ] = buffer[ b_pos ];
  2354.                }
  2355.             ++b_pos;
  2356.             ++t_pos;
  2357.             tbuf[ t_pos ] = '¥0';
  2358.             break;
  2359.          }
  2360.  
  2361.       }
  2362.  
  2363.    return TRUE;
  2364.  
  2365.    }
  2366.  
  2367. /***************************************************************
  2368.  
  2369.     FUNCTION:       var_setnval()
  2370.  
  2371.     DESCRIPTION:    This function sets the value of numerical
  2372.             variable v to the value of i.
  2373.  
  2374. ***************************************************************/
  2375.  
  2376. #if ANSI_C
  2377. extern int
  2378. var_setnval( struct bwb_variable *v, bnumber i )
  2379. #else
  2380. int
  2381. var_setnval( v, i )
  2382.    struct bwb_variable *v;
  2383.    bnumber i;
  2384. #endif
  2385.    {
  2386.  
  2387.    switch( v->type )
  2388.       {
  2389.       case NUMBER:
  2390.          * var_findnval( v, v->array_pos ) = i;
  2391.          break;
  2392.       default:
  2393. #if INTENSIVE_DEBUG
  2394.          sprintf( bwb_ebuf, "in var_setnval(): variable <%s> is not a number",
  2395.             v->name );
  2396.          bwb_error( bwb_ebuf );
  2397. #else
  2398.          bwb_error( err_mismatch );
  2399. #endif
  2400.       }
  2401.  
  2402.    /* successful assignment */
  2403.  
  2404.    return TRUE;
  2405.  
  2406.    }
  2407.  
  2408.  
  2409.