⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bwb_cnd.c

📁 这是一个简易的basic语言解释器, 可供我们学习和改进.
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************        bwb_cnd.c       Conditional Expressions and Commands                        for Bywater BASIC Interpreter                        Copyright (c) 1993, Ted A. Campbell                        Bywater Software                        email: tcamp@delphi.com        Copyright and Permissions Information:        All U.S. and international rights are claimed by the author,        Ted A. Campbell.	This software is released under the terms of the GNU General	Public License (GPL), which is distributed with this software	in the file "COPYING".  The GPL specifies the terms under	which users may copy and use the software in this distribution.	A separate license is available for commercial distribution,	for information on which you should contact the author.***************************************************************//*---------------------------------------------------------------*//* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, *//* 11/1995 (eidetics@cerf.net).                                  *//*                                                               *//* Those additionally marked with "DD" were at the suggestion of *//* Dale DePriest (daled@cadence.com).                            *//*---------------------------------------------------------------*/#include <stdio.h>#include <math.h>#include <ctype.h>#include "bwbasic.h"#include "bwb_mes.h"/* declarations of functions visible to this file only */#if ANSI_Cstatic int cnd_thenels( char *buffer, int position, int *then, int *els );static int cnd_tostep( char *buffer, int position, int *to, int *step );static struct bwb_line *find_wend( struct bwb_line *l );static struct bwb_line *find_endif( struct bwb_line *l,   struct bwb_line **else_line );static int is_endif( struct bwb_line *l );extern int var_setnval( struct bwb_variable *v, bnumber i );static int case_eval( struct exp_ese *expression, struct exp_ese *minval,   struct exp_ese *maxval );static struct bwb_line *find_case( struct bwb_line *l );static struct bwb_line *find_endselect( struct bwb_line *l );static int is_endselect( struct bwb_line *l );static struct bwb_line *bwb_caseif( struct bwb_line *l );#if STRUCT_CMDSstatic struct bwb_line *find_next( struct bwb_line *l );#endif#elsestatic int cnd_thenels();static int cnd_tostep();static struct bwb_line *find_wend();static struct bwb_line *find_endif();static int is_endif();extern int var_setnval();static int case_eval();static struct bwb_line *find_case();static struct bwb_line *find_endselect();static int is_endselect();static struct bwb_line *bwb_caseif();#if STRUCT_CMDSstatic struct bwb_line *find_next();#endif#endif                          /* ANSI_C for prototypes *//***    IF-THEN-ELSE ***//***************************************************************        FUNCTION:       bwb_if()        DESCRIPTION:    This function handles the BASIC IF                        statement.   	SYNTAX:		IF expression THEN [statement [ELSE statement]]***************************************************************/#if ANSI_Cstruct bwb_line *bwb_if( struct bwb_line *l )#elsestruct bwb_line *bwb_if( l )   struct bwb_line *l;#endif   {   int then, els;   struct exp_ese *e;   int glnumber;   int tpos;   static char tbuf[ MAXSTRINGSIZE + 1 ];   static struct bwb_line gline;#if STRUCT_CMDS   static struct bwb_line *else_line;   static struct bwb_line *endif_line;#endif#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_if(): entry, line <%d> buffer <%s>",      l->number, &( l->buffer[ l->position ] ) );   bwb_debug( bwb_ebuf );   getchar();#endif#if INTENSIVE_DEBUG   if ( l == &gline )      {      sprintf( bwb_ebuf, "in bwb_if(): recursive call, l = &gline" );      bwb_debug( bwb_ebuf );      }#endif   /* Call bwb_exp() to evaluate the condition. This should return      with position set to the "THEN" statement */   e = bwb_exp( l->buffer, FALSE, &( l->position ) );#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_if(): line <%d> condition returns <%d>",      l->number, exp_getnval( e ) );   bwb_debug( bwb_ebuf );#endif   /* test for "THEN" and "ELSE" statements */   cnd_thenels( l->buffer, l->position, &then, &els );#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_if(): return from cnd_thenelse, line is <%s>",      l->buffer );   bwb_debug( bwb_ebuf );#endif   /* test for multiline IF statement: this presupposes ANSI-compliant      structured BASIC */#if STRUCT_CMDS   tpos = then + strlen( CMD_THEN ) + 1;   if ( is_eol( l->buffer, &tpos ) == TRUE )      {#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_if(): found multi-line IF statement, line <%d>",         l->number );      bwb_debug( bwb_ebuf );#endif      /* find END IF and possibly ELSE[IF] line(s) */      else_line = NULL;      endif_line = find_endif( l, &else_line );      /* evaluate the expression */      if ( (int) exp_getnval( e ) != FALSE )         {         bwb_incexec();         bwb_setexec( l->next, 0, EXEC_IFTRUE );#if MULTISEG_LINES         adv_eos( l->buffer, &( l->position ));#endif         return bwb_zline( l );         }      else if ( else_line != NULL )         {         bwb_incexec();         bwb_setexec( else_line, 0, EXEC_IFFALSE );         else_line->position = 0;         return else_line;         }      else         {         /* Following line incorrect, replaced by next two (bug found by DD) */         /* bwb_setexec( endif_line, 0, CURTASK excs[ CURTASK exsc ].code ); */         bwb_incexec(); /* JBV */         bwb_setexec( endif_line, 0, EXEC_IFFALSE ); /* JBV */         endif_line->position = 0;         return endif_line;         }      }#endif			/* STRUCT_CMDS for Multi-line IF...THEN */   /* Not a Multi-line IF...THEN: test for THEN line-number */#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_if(): not multi-line; line is <%s>",      l->buffer );   bwb_debug( bwb_ebuf );#endif   /* evaluate and execute */   if ( (int) exp_getnval( e ) != FALSE )      {#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_if(): expression is TRUE" );      bwb_debug( bwb_ebuf );#endif      if ( then == FALSE )         {#if PROG_ERRORS	 sprintf( bwb_ebuf, "in bwb_if(): IF without THEN" );         bwb_error( bwb_ebuf );#else         bwb_error( err_syntax );#endif         }      else         {	 /* check for THEN followed by literal line number */	 tpos = then + strlen( CMD_THEN ) + 1;	 adv_element( l->buffer, &tpos, tbuf );	 if ( isdigit( tbuf[ 0 ] ) != 0 )	    {	    glnumber = atoi( tbuf );#if INTENSIVE_DEBUG	    sprintf( bwb_ebuf, "Detected THEN followed by line number <%d>",	       glnumber );	    bwb_debug( bwb_ebuf );#endif	    sprintf( tbuf, "%s %d", CMD_GOTO, glnumber );	    gline.buffer = tbuf;	    gline.marked = FALSE;	    gline.position = 0;	    gline.next = l->next;	    bwb_setexec( &gline, 0, CURTASK excs[ CURTASK exsc ].code );	    return &gline;	    }	 /* form is not THEN followed by line number */	 else	    {	    bwb_setexec( l, then, CURTASK excs[ CURTASK exsc ].code );	    l->position = then + strlen( CMD_THEN ) + 1;	    }	 return l;	 }      }   else      {#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_if(): expression is FALSE" );      bwb_debug( bwb_ebuf );#endif      if ( els != FALSE )         {         l->position = els + strlen( CMD_ELSE ) + 1;         /* bwb_setexec( l, els, EXEC_NORM ); */ /* Nope (JBV) */         bwb_setexec( l, els, CURTASK excs[ CURTASK exsc ].code ); /* JBV */	 return l;	 }      }   /* if neither then nor else were found, advance to next line */   /* DO NOT advance to next segment (only if TRUE should we do that) */   l->next->position = 0;   return l->next;   }/***************************************************************        FUNCTION:       cnd_thenelse()        DESCRIPTION:    This function searches through the                        <buffer> beginning at point <position>                        and attempts to find positions of THEN                        and ELSE statements.***************************************************************/#if ANSI_Cstatic intcnd_thenels( char *buffer, int position, int *then, int *els )#elsestatic intcnd_thenels( buffer, position, then, els )   char *buffer;   int position;   int *then;   int *els;#endif   {   int loop, t_pos, b_pos, p_word;   char tbuf[ MAXSTRINGSIZE + 1 ];#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in cnd_thenels(): entry, line is <%s>",      &( buffer[ position ] ) );   bwb_debug( bwb_ebuf );#endif   /* set then and els to 0 initially */   *then = *els = 0;   /* loop to find words */   p_word = b_pos = position;   t_pos = 0;   tbuf[ 0 ] = '\0';   loop = TRUE;   while( loop == TRUE )      {      switch( buffer[ b_pos ] )         {         case '\0':                     /* end of string */         case ' ':                      /* whitespace = end of word */         case '\t':#if INTENSIVE_DEBUG            sprintf( bwb_ebuf, "in cnd_thenels(): word is <%s>", tbuf );            bwb_debug( bwb_ebuf );#endif            if ( strncmp( tbuf, CMD_THEN, (size_t) strlen( CMD_THEN ) ) == 0 )               {#if INTENSIVE_DEBUG               sprintf( bwb_ebuf, "in cnd_thenels(): THEN found at position <%d>.",                  p_word );               bwb_debug( bwb_ebuf );               sprintf( bwb_ebuf, "in cnd_thenelse(): after THEN, line is <%s>", buffer );               bwb_debug( bwb_ebuf );#endif               *then = p_word;               }            else if ( strncmp( tbuf, CMD_ELSE, (size_t) strlen( CMD_ELSE ) ) == 0 )               {#if INTENSIVE_DEBUG               sprintf( bwb_ebuf, "in cnd_thenels(): ELSE found at position <%d>.",                  p_word );               bwb_debug( bwb_ebuf );               sprintf( bwb_ebuf, "in cnd_thenelse(): after ELSE, line is <%s>", buffer );               bwb_debug( bwb_ebuf );#endif               *els = p_word;               }            /* check for end of the line */            if ( buffer[ b_pos ] == '\0' )               {#if INTENSIVE_DEBUG               sprintf( bwb_ebuf, "in cnd_thenels(): return: end of string" );               bwb_debug( bwb_ebuf );#endif               return TRUE;               }            ++b_pos;            p_word = b_pos;            t_pos = 0;            tbuf[ 0 ] = '\0';            break;         default:            if ( islower( buffer[ b_pos ] ) != FALSE )               {               tbuf[ t_pos ] = (char) toupper( buffer[ b_pos ] );               }            else               {               tbuf[ t_pos ] = buffer[ b_pos ];               }            ++b_pos;            ++t_pos;            tbuf[ t_pos ] = '\0';            break;         }      }#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in cnd_thenelse(): exit, line is <%s>", buffer );   bwb_debug( bwb_ebuf );#endif   return FALSE;   }#if STRUCT_CMDS/***************************************************************        FUNCTION:       bwb_else()        DESCRIPTION:    This function handles the BASIC ELSE                        statement.   	SYNTAX:		ELSE***************************************************************/#if ANSI_Cstruct bwb_line *bwb_else( struct bwb_line *l )#elsestruct bwb_line *bwb_else( l )   struct bwb_line *l;#endif   {   struct bwb_line *endif_line;   struct bwb_line *else_line;#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_else(): entered function" );   bwb_debug( bwb_ebuf );#endif   /* If the code is EXEC_NORM, then this is a continuation of a single-      line IF...THEN...ELSE... statement and we should return */   /*----------------------------------------------------------------------*/   /* Well, not really... better to check for EXEC_IFTRUE or EXEC_IFFALSE, */   /* and if not equal, then blow entirely out of current line (JBV)       */   /*----------------------------------------------------------------------*/   /* Section removed by JBV */   /* if ( CURTASK excs[ CURTASK exsc ].code == EXEC_NORM )      {#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_else(): detected EXEC_NORM" );      bwb_debug( bwb_ebuf );#endif      return bwb_zline( l );      } */   /* Section added by JBV */   if (( CURTASK excs[ CURTASK exsc ].code != EXEC_IFTRUE ) &&   ( CURTASK excs[ CURTASK exsc ].code != EXEC_IFFALSE ))      {#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_else(): no EXEC_IFTRUE or EXEC_IFFALSE" );      bwb_debug( bwb_ebuf );#endif      l->next->position = 0;      return l->next;      }   endif_line = find_endif( l, &else_line );   if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFTRUE )      {      endif_line->position = 0;      return endif_line;      }   else if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFFALSE )      {      return bwb_zline( l );      }#if PROG_ERRORS   sprintf( bwb_ebuf, "in bwb_else(): ELSE without IF" );   bwb_error( bwb_ebuf );#else   bwb_error( err_syntax );#endif   return bwb_zline( l );   }/***************************************************************        FUNCTION:       bwb_elseif()        DESCRIPTION:    This function handles the BASIC ELSEIF                        statement.	SYNTAX:		ELSEIF***************************************************************/#if ANSI_Cstruct bwb_line *bwb_elseif( struct bwb_line *l )#elsestruct bwb_line *bwb_elseif( l )   struct bwb_line *l;#endif   {   struct bwb_line *endif_line;   struct bwb_line *else_line;   struct exp_ese *e;#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_elseif(): entered function" );   bwb_debug( bwb_ebuf );#endif   else_line = NULL;   endif_line = find_endif( l, &else_line );   if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFTRUE )      {      endif_line->position = 0;      return endif_line;      }   else if ( CURTASK excs[ CURTASK exsc ].code == EXEC_IFFALSE )      {      /* Call bwb_exp() to evaluate the condition. This should return         with position set to the "THEN" statement */      e = bwb_exp( l->buffer, FALSE, &( l->position ) );      if ( (int) exp_getnval( e ) == TRUE )         {         /* ELSEIF condition is TRUE: proceed to the next line */         CURTASK excs[ CURTASK exsc ].code = EXEC_IFTRUE;#if MULTISEG_LINES         adv_eos( l->buffer, &( l->position ));#endif         return bwb_zline( l );         }      /* ELSEIF condition FALSE: proceed to next ELSE line if there is one */      else if ( else_line != NULL )         {         bwb_setexec( else_line, 0, EXEC_IFFALSE );         else_line->position = 0;         return else_line;         }      /* ELSEIF condition is FALSE and no more ELSExx lines: proceed to END IF */      else         {         bwb_setexec( endif_line, 0, CURTASK excs[ CURTASK exsc ].code );         endif_line->position = 0;         return endif_line;         }      }#if PROG_ERRORS   sprintf( bwb_ebuf, "in bwb_elseif(): ELSEIF without IF" );   bwb_error( bwb_ebuf );#else   bwb_error( err_syntax );#endif#if MULTISEG_LINES   adv_eos( l->buffer, &( l->position ));#endif   return bwb_zline( l );   }/***************************************************************        FUNCTION:       bwb_endif()        DESCRIPTION:    This function handles the BASIC END IF                        statement.	SYNTAX:		END IF***************************************************************/#if ANSI_Cstruct bwb_line *bwb_endif( struct bwb_line *l )#else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -