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

📄 bwb_dio.c

📁 这是一个简易的basic语言解释器, 可供我们学习和改进.
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************        bwb_dio.c       Device Input/Output Routines                        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).                                  *//*---------------------------------------------------------------*/#include <stdio.h>#include "bwbasic.h"#include "bwb_mes.h"#if HAVE_SYSSTAT#include <sys/stat.h>#endif#ifndef SEEK_SET#define	SEEK_SET	0#endif#if INTENSIVE_DEBUG#define RANDOM_FILLCHAR		'X'#else#define RANDOM_FILLCHAR		' '#endif#if COMMON_CMDSstruct dev_element *dev_table;          /* table of devices */#endifstatic struct bwb_variable *v;static int pos;static int req_devnumber;static int rlen;static int mode;#if ANSI_Cstatic struct bwb_line *dio_lrset( struct bwb_line *l, int rset );static int dio_flush( int dev_number );#elsestatic struct bwb_line *dio_lrset();static int dio_flush();#endif#if COMMON_CMDS/***************************************************************        FUNCTION:       bwb_open()	DESCRIPTION:    This function implements the BASIC OPEN			command to open a stream for device input/output.        SYNTAX: 1. OPEN "I"|"O"|"R", [#]n, filename [,rlen]                2. OPEN filename [FOR INPUT|OUTPUT|APPEND|] AS [#]n [LEN=n]***************************************************************/#if ANSI_Cstruct bwb_line *bwb_open( struct bwb_line *l )#elsestruct bwb_line *bwb_open( l )   struct bwb_line *l;#endif   {   FILE *fp;   struct exp_ese *e;   int previous_buffer;   char atbuf[ MAXSTRINGSIZE + 1 ];   char first[ MAXSTRINGSIZE + 1 ];   char devname[ MAXSTRINGSIZE + 1 ];   /* initialize */   mode = req_devnumber = rlen = -1;   previous_buffer = FALSE;   /* get the first expression element up to comma or whitespace */   adv_element( l->buffer, &( l->position ), atbuf );   /* parse the first expression element */   pos = 0;   e = bwb_exp( atbuf, FALSE, &pos );   str_btoc( first, exp_getsval( e ) );#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_open(): first element is <%s>",      first );   bwb_debug( bwb_ebuf );#endif   /* test for syntactical form: if a comma follows the first element,      then the syntax is form 1 (the old CP/M BASIC format); otherwise we      presume form 2 */   adv_ws( l->buffer, &( l->position ) );   /* Parse syntax Form 1 (OPEN "x",#n, devname...) */   if ( l->buffer[ l->position ] == ',' )      {      /* parse the next element to get the device number */      ++( l->position );                        /* advance beyond comma */      adv_ws( l->buffer, &( l->position ) );      if ( l->buffer[ l->position ] == '#' )         {         ++( l->position );         adv_ws( l->buffer, &( l->position ) );         }      adv_element( l->buffer, &( l->position ), atbuf );      pos = 0;      e = bwb_exp( atbuf, FALSE, &pos );      if ( e->type == STRING )         {#if PROG_ERRORS	 bwb_error( "String where number was expected for device number" );#else	 bwb_error( err_syntax );#endif         return bwb_zline( l );         }      req_devnumber = (int) exp_getnval( e );#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_open(): syntax 1, req dev number is %d",         req_devnumber );      bwb_debug( bwb_ebuf );#endif      /* parse the next element to get the devname */      adv_ws( l->buffer, &( l->position ) );    /* advance past whitespace */      ++( l->position );                        /* advance past comma */      adv_element( l->buffer, &( l->position ), atbuf );      pos = 0;      e = bwb_exp( atbuf, FALSE, &pos );      if ( e->type != STRING )         {#if PROG_ERRORS	 bwb_error( "in bwb_open(): number where string was expected for devname" );#else	 bwb_error( err_syntax );#endif         return bwb_zline( l );         }      str_btoc( devname, exp_getsval( e ) );#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_open(): syntax 1, devname <%s>",         devname  );      bwb_debug( bwb_ebuf );#endif      /* see if there is another element; if so, parse it to get the         record length */      adv_ws( l->buffer, &( l->position ) );      if ( l->buffer[ l->position ] == ',' )         {         ++( l->position );                     /* advance beyond comma */         adv_element( l->buffer, &( l->position ), atbuf );         pos = 0;         e = bwb_exp( atbuf, FALSE, &pos );         if ( e->type == STRING )            {#if PROG_ERRORS            bwb_error( "String where number was expected for record length" );#else            bwb_error( err_syntax );#endif            return bwb_zline( l );            }         rlen = (int) exp_getnval( e );#if INTENSIVE_DEBUG         sprintf( bwb_ebuf, "in bwb_open(): syntax 1, record length is %d",            rlen );         bwb_debug( bwb_ebuf );#endif         }      /* the first letter of the first should indicate the         type of file opening requested: test this letter,         then parse accordingly */      /* open file for sequential INPUT */      if ( ( first[ 0 ] == 'i' ) || ( first[ 0 ] == 'I' ))         {         mode = DEVMODE_INPUT;         }      /* open file for sequential OUTPUT */      else if ( ( first[ 0 ] == 'o' ) || ( first[ 0 ] == 'O' ))         {         mode = DEVMODE_OUTPUT;         }      /* open file for RANDOM access input and output */      else if ( ( first[ 0 ] == 'r' ) || ( first[ 0 ] == 'R' ))         {         mode = DEVMODE_RANDOM;         }      /* error: none of the appropriate modes found */      else         {#if PROG_ERRORS	 sprintf( bwb_ebuf, "in bwb_open(): invalid mode" );	 bwb_error( bwb_ebuf );#else	 bwb_error( err_syntax );#endif         }#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_open(): syntax 1, mode is %d", mode );      bwb_debug( bwb_ebuf );#endif      }   /* Parse syntax Form 2 (OPEN devname FOR mode AS#n ... ) */   else      {      /* save the devname from first */      strcpy( devname, first );#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_open(): syntax 2, devname <%s>",         devname );      bwb_debug( bwb_ebuf );#endif      /* get the next element */      adv_element( l->buffer, &( l->position ), atbuf );      /* check for "FOR mode" statement */      bwb_strtoupper( atbuf );      if ( strcmp( atbuf, "FOR" ) == 0 )         {         adv_element( l->buffer, &( l->position ), atbuf );         bwb_strtoupper( atbuf );         if ( strcmp( atbuf, "INPUT" ) == 0 )            {            mode = DEVMODE_INPUT;            }         else if ( strcmp( atbuf, "OUTPUT" ) == 0 )            {            mode = DEVMODE_OUTPUT;            }         else if ( strcmp( atbuf, "APPEND" ) == 0 )            {            mode = DEVMODE_RANDOM;            }         else            {#if PROG_ERRORS            bwb_error( "in bwb_open(): Invalid device i/o mode specified" );#else            bwb_error( err_syntax );#endif            return bwb_zline( l );            }         /* get the next element */         adv_element( l->buffer, &( l->position ), atbuf );         }      else         {         mode = DEVMODE_RANDOM;         }#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_open(): syntax 2, mode is %d", mode );      bwb_debug( bwb_ebuf );#endif      /* This leaves us with the next element in the atbuf: it         should read "AS" */      bwb_strtoupper( atbuf );      if ( strcmp( atbuf, "AS" ) != 0 )         {#if PROG_ERRORS         bwb_error( "in bwb_open(): expected AS statement" );#else         bwb_error( err_syntax );#endif         return bwb_zline( l );         }      /* get the next element */      adv_ws( l->buffer, &( l->position ) );      if ( l->buffer[ l->position ] == '#' )         {         ++( l->position );         }      adv_element( l->buffer, &( l->position ), atbuf );#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_open(): string to parse for req dev number <%s>",         atbuf );      bwb_debug( bwb_ebuf );#endif      pos = 0;      e = bwb_exp( atbuf, FALSE, &pos );      if ( e->type == STRING )         {#if PROG_ERRORS         bwb_error( "String where number was expected for dev number" );#else         bwb_error( err_syntax );#endif         return bwb_zline( l );         }      req_devnumber = (int) exp_getnval( e );#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_open(): syntax 2, req dev number is %d",         req_devnumber );      bwb_debug( bwb_ebuf );#endif      /* Check for LEN = n statement */      adv_element( l->buffer, &( l->position ), atbuf );      bwb_strtoupper( atbuf );      if ( strncmp( atbuf, "LEN", (size_t) 3 ) == 0 )         {         pos = l->position - strlen( atbuf );         while( ( l->buffer[ pos ] != '=' ) && ( l->buffer[ pos ] != '\0' ))            {            ++pos;            }         if ( l->buffer[ pos ] == '\0' )            {#if PROG_ERRORS            bwb_error( "Failed to find equals sign after LEN element" );#else            bwb_error( err_syntax );#endif            return bwb_zline( l );            }         ++pos;         /* advance past equal sign */         e = bwb_exp( l->buffer, FALSE, &pos );         if ( e->type == STRING )            {#if PROG_ERRORS            bwb_error( "String where number was expected for record length" );#else            bwb_error( err_syntax );#endif            return bwb_zline( l );            }         rlen = (int) exp_getnval( e );#if INTENSIVE_DEBUG         sprintf( bwb_ebuf, "in bwb_open(): syntax 2, record length is %d",            rlen );         bwb_debug( bwb_ebuf );#endif         }      }                                 /* end of syntax 2 */   /* check for valid requested device number */   if ( ( req_devnumber < 0 ) || ( req_devnumber >= DEF_DEVICES ))      {#if PROG_ERRORS      bwb_error( "in bwb_open(): Requested device number is out of range." );#else      bwb_error( err_devnum );#endif      return bwb_zline( l );      }   if ( dev_table[ req_devnumber ].mode == DEVMODE_CLOSED )      {#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_open(): using previously closed file (and buffer)" );      bwb_debug( bwb_ebuf );#endif      previous_buffer = TRUE;      }   if ( ( dev_table[ req_devnumber ].mode != DEVMODE_CLOSED ) &&      ( dev_table[ req_devnumber ].mode != DEVMODE_AVAILABLE ) )      {#if PROG_ERRORS      bwb_error( "in bwb_open(): Requested device number is already in use." );#else      bwb_error( err_devnum );#endif      return bwb_zline( l );      }#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_open(): ready to open device <%s> mode <%d>",      devname, mode );   bwb_debug( bwb_ebuf );#endif   /* attempt to open the file */   switch( mode )      {      case DEVMODE_OUTPUT:         fp = fopen( devname, "w" );         break;      case DEVMODE_INPUT:         fp = fopen( devname, "r" );         break;      case DEVMODE_APPEND:         fp = fopen( devname, "a" );         break;      case DEVMODE_RANDOM:         fp = fopen( devname, "r+" );         if ( fp == NULL )            {            fp = fopen( devname, "w" );            fclose( fp );            fp = fopen( devname, "r+" );            }         break;      }   /* check for valid file opening */   if ( fp == NULL )      {#if PROG_ERRORS      sprintf( bwb_ebuf, "Failed to open device <%s>", devname );      bwb_error( bwb_ebuf );#else      bwb_error( err_dev );#endif      return bwb_zline( l );      }   /* assign values to device table */   /* Random mode has a default record length (JBV) */   if (mode == DEVMODE_RANDOM && rlen == -1) rlen = 128;   dev_table[ req_devnumber ].mode = mode;   dev_table[ req_devnumber ].cfp = fp;   dev_table[ req_devnumber ].reclen = rlen;   dev_table[ req_devnumber ].next_record = 1;   dev_table[ req_devnumber ].loc = 0;   strcpy( dev_table[ req_devnumber ].filename, devname );   /* File length finding routine, added by JBV */   fseek( dev_table[ req_devnumber ].cfp, 0, SEEK_END );   dev_table[ req_devnumber ].lof = ftell( dev_table[ req_devnumber ].cfp );   fseek( dev_table[ req_devnumber ].cfp, 0, SEEK_SET );   /* allocate a character buffer for random access */   if (( mode == DEVMODE_RANDOM ) && ( previous_buffer != TRUE ))      {      /* Revised to CALLOC pass-thru call by JBV */      if ( ( dev_table[ req_devnumber ].buffer = CALLOC( rlen + 1, 1, "bwb_open" )) == NULL )	 {#if PROG_ERRORS	 bwb_error( "in bwb_open(): failed to find memory for device buffer" );#else	 bwb_error( err_getmem );#endif	 return bwb_zline( l );	 }      dio_flush( req_devnumber );#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_open(): allocated new random-access buffer" );      bwb_debug( bwb_ebuf );#endif      }#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_open(): file is open now; end of function" );   bwb_debug( bwb_ebuf );#endif   /* return next line number in sequence */   return bwb_zline( l );   }/***************************************************************        FUNCTION:       bwb_close()	DESCRIPTION:    This function implements the BASIC CLOSE			command to close a stream for device input/output.        SYNTAX:         CLOSE [#]n [,[#]n...]***************************************************************/#if ANSI_Cstruct bwb_line *bwb_close( struct bwb_line *l )#elsestruct bwb_line *bwb_close( l )   struct bwb_line *l;#endif   {   struct exp_ese *e;   char atbuf[ MAXSTRINGSIZE + 1 ];   int blanket_close; /* JBV */   register int n; /* JBV */   blanket_close = -1; /* JBV */   req_devnumber = 0; /* JBV */   /* loop to get device numbers to close */   do      {      if ( l->buffer[ l->position ] == ',' && blanket_close == 0)         ++( l->position); /* JBV */      adv_ws( l->buffer, &( l->position ) );      if ( l->buffer[ l->position ] == '#')         {         ++( l->position );         }      adv_element( l->buffer, &( l->position ), atbuf );      pos = 0;      e = bwb_exp( atbuf, FALSE, &pos );      if ( e->type == STRING )         {#if PROG_ERRORS         bwb_error( "String where number was expected for device number" );#else         bwb_error( err_syntax );#endif         return bwb_zline( l );         }      /*-------------------------------------------------------------*/      /* Added the following section for blanket close feature (JBV) */      /*-------------------------------------------------------------*/      if (blanket_close == -1)      if (strlen(atbuf) != 0) blanket_close = 0;      else blanket_close = 1;      if (blanket_close == 0) req_devnumber = (int) exp_getnval( e );      else      {          ++req_devnumber;          /* Find the next device in use */          for (n = req_devnumber; n < DEF_DEVICES; ++n)          {              req_devnumber = -1;              if (( dev_table[ n ].mode != DEVMODE_CLOSED ) &&                 ( dev_table[ n ].mode != DEVMODE_AVAILABLE ) )              {                  req_devnumber = n;                  break;              }          }          if (req_devnumber == -1) break; /* Skidoo if no more to close */      }#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_close(): requested device number <%d>",         req_devnumber );      bwb_debug( bwb_ebuf );

⌨️ 快捷键说明

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