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

📄 bwb_stc.c

📁 这是一个简易的basic语言解释器, 可供我们学习和改进.
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************        bwb_stc.c       Commands Related to Structured Programming                        for Bywater BASIC Interpreter                        Commands:	CALL					SUB					FUNCTION					END SUB					END FUNCTION                        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).                                  *//*---------------------------------------------------------------*/#include <stdio.h>#include <ctype.h>#include "bwbasic.h"#include "bwb_mes.h"/* prototypes */#if ANSI_Cstatic int fslt_clear( void );static int fslt_add( struct bwb_line *line, int *position, int code );static struct bwb_line *fslt_findl( char *buffer );static struct fslte    *fslt_findf( char *buffer );static int scan_getcmd( struct bwb_line *line, int *position );static int scan_readargs( struct fslte *f,   struct bwb_line *line, int *position );static int call_readargs( struct fslte *f,   char *expression, int *position );static int is_endsub( struct bwb_line *l );static struct bwb_line *find_endsub( struct bwb_line *l );static struct bwb_line *bwb_loopuntil( struct bwb_line *l );struct bwb_variable *bwb_vtov( struct bwb_variable *dst, struct bwb_variable *src );struct bwb_variable *bwb_etov( struct bwb_variable *dst, struct exp_ese *src );struct bwb_variable *var_pos( struct bwb_variable *firstvar, int p );int fslt_addcallvar( struct bwb_variable *v );int fslt_addlocalvar( struct fslte *f, struct bwb_variable *v );#elsestatic int fslt_clear();static int fslt_add();static struct bwb_line *fslt_findl();static struct fslte    *fslt_findf();static int scan_getcmd();static int scan_readargs();static int call_readargs();static int is_endsub();static struct bwb_line *find_endsub();static struct bwb_line *bwb_loopuntil();struct bwb_variable *bwb_vtov();struct bwb_variable *bwb_etov();struct bwb_variable *var_pos();int fslt_addcallvar();int fslt_addlocalvar();#endif				/* ANSI_C for prototypes *//***************************************************************        FUNCTION:       bwb_scan()        DESCRIPTION:	This function scans all lines of the        		program in memory and creates a FUNCTION-        		SUB lookup table (fslt) for the program.***************************************************************/#if ANSI_Cintbwb_scan( void )#elseintbwb_scan()#endif   {   struct bwb_line *current;   int position;   int c;#if PROG_ERRORS   if ( CURTASK rescan != TRUE )      {      bwb_error( "in bwb_scan(): call to scan while CURTASK rescan != TRUE" );      return FALSE;      }#endif#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_scan(): beginning scan..." );   bwb_debug( bwb_ebuf );#endif   /* first run through the FUNCTION - SUB loopkup table      and free any existing memory */   fslt_clear();   /* run through the list of lines and identify SUB and FUNCTION statements */   for ( current = CURTASK bwb_start.next; current != &CURTASK bwb_end; current = current->next )      {#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_scan(): scanning line <%d>", current->number );      bwb_debug( bwb_ebuf );#endif      c = scan_getcmd( current, &position );      if ( c == getcmdnum( CMD_SUB ))         {         fslt_add( current, &position, EXEC_CALLSUB );         }      else if ( c == getcmdnum( CMD_FUNCTION ))         {         fslt_add( current, &position, EXEC_FUNCTION );         }      else if ( c == getcmdnum( CMD_DEF ))         {         fslt_add( current, &position, EXEC_FUNCTION );         }#if STRUCT_CMDS      else if ( c == getcmdnum( CMD_LABEL ))         {         fslt_add( current, &position, EXEC_LABEL );         }#endif      }   /* return */   CURTASK rescan = FALSE;   return TRUE;   }/***************************************************************        FUNCTION:       fslt_clear()        DESCRIPTION:	This C function clears all existing memory        		in the FUNCTION-SUB lookup table.***************************************************************/#if ANSI_Cstatic intfslt_clear( void )#elsestatic intfslt_clear()#endif   {   struct fslte *current, *next;   struct bwb_variable *c, *n;   /* run through table and clear memory */   next = CURTASK fslt_start.next;   for ( current = CURTASK fslt_start.next; current != &CURTASK fslt_end;      current = next )      {      /* check for local variables and free them */      c = current->local_variable;      while ( c != NULL )         {         n = c->next;         /* Revised to FREE pass-thru call by JBV */         FREE( c, "fslt_clear" );         c = n;         }      next = current->next;      /* Revised to FREE pass-thru calls by JBV */      if (current->name != NULL)      {          FREE( current->name, "fslt_clear" ); /* JBV */          current->name = NULL; /* JBV */      }      FREE( current, "fslt_clear" );      current = NULL; /* JBV */      }   /* reset linkage */   CURTASK fslt_start.next = &CURTASK fslt_end;   return TRUE;   }/***************************************************************        FUNCTION:       scan_getcmd()        DESCRIPTION:	This command returns the command number        		for the first BASIC command word encountered        		in a line.***************************************************************/#if ANSI_Cstatic intscan_getcmd( struct bwb_line *line, int *position )#elsestatic intscan_getcmd( line, position )   struct bwb_line *line;   int *position;#endif   {   char tbuf[ MAXSTRINGSIZE + 1 ];   *position = 0;   adv_ws( line->buffer, position );   /* check for NULL line */   if ( line->buffer[ *position ] == '\0' )      {      return -1;      }   /* check for line number and advance beyond it */   if ( isdigit( line->buffer[ *position ] ))      {      scan_element( line->buffer, position, tbuf );      }   /* get the command element in the buffer */   scan_element( line->buffer, position, tbuf );#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in scan_getcmd(): scanning element <%s>", tbuf );   bwb_debug( bwb_ebuf );#endif#if STRUCT_CMDS   if ( is_label( tbuf ) == TRUE )      {#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in scan_getcmd(): found label <%s>", tbuf );      bwb_debug( bwb_ebuf );#endif      return getcmdnum( CMD_LABEL );      }#endif   bwb_strtoupper( tbuf );   /* return command number */   return getcmdnum( tbuf );   }/***************************************************************	FUNCTION:       scan_element()        DESCRIPTION:    This function reads characters in <buffer>                        beginning at <pos> and advances past a                        line element, incrementing <pos> appropri-                        ately and returning the line element in			<element>.			This function is almost identical to adv_element(),			but it will not stop at a full colon.  This is			necessary to detect a label in the first element			position.  If MULTISEG_LINES is defined as TRUE,			adv_element() will stop at the colon, interpreting			it as the end-of-segment marker.***************************************************************/#if ANSI_Cextern intscan_element( char *buffer, int *pos, char *element )#elseintscan_element( buffer, pos, element )   char *buffer;   int *pos;   char *element;#endif   {   int loop;                                    /* control loop */   int e_pos;                                   /* position in element buffer */   int str_const;                               /* boolean: building a string constant */   /* advance beyond any initial whitespace */   adv_ws( buffer, pos );#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in adv_element(): receieved <%s>.", &( buffer[ *pos ] ));   bwb_debug( bwb_ebuf );#endif   /* now loop while building an element and looking for an      element terminator */   loop = TRUE;   e_pos = 0;   element[ e_pos ] = '\0';   str_const = FALSE;   while ( loop == TRUE )      {      switch( buffer[ *pos ] )         {         case ',':                      /* element terminators */         case ';':	 case '=':	 case ' ':         case '\t':         case '\0':         case '\n':         case '\r':            if ( str_const == TRUE )               {               element[ e_pos ] = buffer[ *pos ];               ++e_pos;               ++( *pos );               element[ e_pos ] = '\0';               }            else               {               return TRUE;               }            break;         case '\"':                     /* string constant */            element[ e_pos ] = buffer[ *pos ];            ++e_pos;            ++( *pos );            element[ e_pos ] = '\0';            if ( str_const == TRUE )    /* termination of string constant */               {               return TRUE;               }            else                        /* beginning of string constant */               {               str_const = TRUE;               }            break;         case '(':                     /* MID$ command termination (JBV) */            /* If MID$ is here, get out */            if (strcmp(element, CMD_MID) == 0)               return TRUE;            /* else add it to the accumulation element */            element[ e_pos ] = buffer[ *pos ];            ++e_pos;            ++( *pos );            element[ e_pos ] = '\0';            break;         default:            element[ e_pos ] = buffer[ *pos ];            ++e_pos;            ++( *pos );            element[ e_pos ] = '\0';            break;         }      }   /* This should not happen */   return FALSE;   }/***************************************************************        FUNCTION:       fslt_add()        DESCRIPTION:	This C function adds an entry to the        		FUNCTION-SUB lookup table.***************************************************************/#if ANSI_Cstatic intfslt_add( struct bwb_line *line, int *position, int code )#elsestatic intfslt_add( line, position, code )   struct bwb_line *line;   int *position;   int code;#endif   {   char tbuf[ MAXSTRINGSIZE + 1 ];   char *name;   struct bwb_variable *v;   struct fslte *f, *n;   int p;   /* get the element for name */   if ( code == EXEC_LABEL )      {      p = 0;      scan_element( line->buffer, &p, tbuf );      if ( isdigit( tbuf[ 0 ] ))         {	 scan_element( line->buffer, &p, tbuf );         }      tbuf[ strlen( tbuf ) - 1 ] = '\0';      }   else      {      adv_ws( line->buffer, position );      exp_getvfname( &( line->buffer[ *position ] ), tbuf );      *position += strlen( tbuf );      }#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in fslt_add(): adding SUB/FUNCTION/LABEL code <%d> name <%s>",      code, tbuf );   bwb_debug( bwb_ebuf );#endif   /* get memory for name buffer */   /* Revised to CALLOC pass-thru call by JBV */   if ( ( name = CALLOC( 1, strlen( tbuf ) + 1, "fslt_add" ) ) == NULL )      {#if PROG_ERRORS      bwb_error( "in fslt_add(): failed to get memory for name buffer" );#else      bwb_error( err_getmem );#endif      return FALSE;      }   strcpy( name, tbuf );   /* get memory for fslt structure */   if ( ( f = CALLOC( 1, sizeof( struct fslte ), "fslt_add" ) ) == NULL )      {#if PROG_ERRORS      bwb_error( "in fslt_add(): failed to get memory for fslt structure" );#else      bwb_error( err_getmem );#endif      return FALSE;      }   /* fill in structure */   f->line = line;   f->name = name;   f->code = code;   f->local_variable = NULL;#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in fslt_add(): current buffer <%s>",      &( line->buffer[ *position ] ) );   bwb_debug( bwb_ebuf );#endif   /* read arguments */   adv_ws( line->buffer, position );   if ( line->buffer[ *position ] == '(' )      {      scan_readargs( f, line, position );      }   /* if function, add one more local variable expressing the name      of the function */   if ( code == EXEC_FUNCTION )      {      v = var_new( tbuf );      fslt_addlocalvar( f, v );#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in fslt_add(): added function-name variable <%s>",         v->name );      bwb_debug( bwb_ebuf );      getchar();#endif      }   /* establish linkages */   n = CURTASK fslt_start.next;   CURTASK fslt_start.next = f;   f->next = n;   return TRUE;   }/***************************************************************        FUNCTION:       scan_readargs()        DESCRIPTION:	This C function reads arguments (variable        		names for an entry added to the FUNCTION-			SUB lookup table.***************************************************************/#if ANSI_Cstatic intscan_readargs( struct fslte *f, struct bwb_line *line, int *position )#elsestatic intscan_readargs( f, line, position )   struct fslte *f;   struct bwb_line *line;   int *position;#endif   {   int control_loop;   struct bwb_variable *v;   char tbuf[ MAXSTRINGSIZE + 1 ];#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in scan_readargs(): reading arguments, buffer <%s>",      &( line->buffer[ *position ] ) );   bwb_debug( bwb_ebuf );#endif   /* if we are at begin paren, advance */   if ( line->buffer[ *position ] == '(' )      {      ++( *position );      }   /* loop through looking for arguments */   control_loop = TRUE;   adv_ws( line->buffer, position );   while ( control_loop == TRUE )      {      switch( line->buffer[ *position ] )

⌨️ 快捷键说明

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