home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-03 | 59.6 KB | 2,078 lines |
- Newsgroups: comp.sources.misc
- From: tcamp@acpub.duke.edu (Ted A. Campbell)
- Subject: v33i042: bwbasic - Bywater BASIC interpreter version 1.10, Part06/11
- Message-ID: <1992Nov5.035946.17726@sparky.imd.sterling.com>
- X-Md4-Signature: c722602896b74bad0a1249f3582b3abd
- Date: Thu, 5 Nov 1992 03:59:46 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: tcamp@acpub.duke.edu (Ted A. Campbell)
- Posting-number: Volume 33, Issue 42
- Archive-name: bwbasic/part06
- Environment: ANSI-C
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: bwb_exp.c bwbasic.doc
- # Wrapped by kent@sparky on Wed Nov 4 21:34:25 1992
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 6 (of 11)."'
- if test -f 'bwb_exp.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bwb_exp.c'\"
- else
- echo shar: Extracting \"'bwb_exp.c'\" \(40302 characters\)
- sed "s/^X//" >'bwb_exp.c' <<'END_OF_FILE'
- X/****************************************************************
- X
- X bwb_exp.c Expression Parser
- X for Bywater BASIC Interpreter
- X
- X Copyright (c) 1992, Ted A. Campbell
- X
- X Bywater Software
- X P. O. Box 4023
- X Duke Station
- X Durham, NC 27706
- X
- X email: tcamp@acpub.duke.edu
- X
- X Copyright and Permissions Information:
- X
- X All U.S. and international copyrights are claimed by the
- X author. The author grants permission to use this code
- X and software based on it under the following conditions:
- X (a) in general, the code and software based upon it may be
- X used by individuals and by non-profit organizations; (b) it
- X may also be utilized by governmental agencies in any country,
- X with the exception of military agencies; (c) the code and/or
- X software based upon it may not be sold for a profit without
- X an explicit and specific permission from the author, except
- X that a minimal fee may be charged for media on which it is
- X copied, and for copying and handling; (d) the code must be
- X distributed in the form in which it has been released by the
- X author; and (e) the code and software based upon it may not
- X be used for illegal activities.
- X
- X****************************************************************/
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <ctype.h>
- X#include <math.h>
- X
- X#include "bwbasic.h"
- X#include "bwb_mes.h"
- X
- Xint exp_esc = 0; /* expression stack counter */
- X
- X/***************************************************************
- X
- X FUNCTION: bwb_exp()
- X
- X DESCRIPTION: This is the function by which the expression
- X parser is called.
- X
- X***************************************************************/
- X
- Xstruct exp_ese *
- Xbwb_exp( char *expression, int assignment, int *position )
- X {
- X struct exp_ese *rval; /* return value */
- X int entry_level, main_loop, adv_loop, err_condition;
- X char *e; /* pointer to current string */
- X int r; /* return value from functions */
- X register int c; /* quick counter */
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): expression <%s> assignment <%d> level <%d>",
- X & ( expression[ *position ] ), assignment, exp_esc );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* save the entry level of the expression stack in order to
- X check it at the end of this function */
- X
- X entry_level = exp_esc;
- X err_condition = FALSE;
- X
- X /* advance past whitespace or beginningg of line segment */
- X
- X if ( expression[ *position ] == ':' )
- X {
- X ++( *position );
- X }
- X adv_ws( expression, position );
- X if ( expression[ *position ] == ':' )
- X {
- X ++( *position );
- X adv_ws( expression, position );
- X }
- X
- X /* increment the expression stack counter to get a new level */
- X
- X inc_esc();
- X
- X /* check to be sure there is a legitimate expression
- X and set initial parameters for the main loop */
- X
- X adv_loop = TRUE;
- X while( adv_loop == TRUE )
- X {
- X switch( expression[ *position ] )
- X {
- X case ' ': /* whitespace */
- X case '\t':
- X ++(*position);
- X break;
- X case '\0': /* end of string */
- X case '\r':
- X case '\n':
- X main_loop = adv_loop = FALSE; /* break out of loop */
- X break;
- X default:
- X adv_loop = FALSE;
- X main_loop = TRUE;
- X exp_es[ exp_esc ].pos_adv = 0;
- X break;
- X }
- X }
- X
- X /* main parsing loop */
- X
- X while ( main_loop == TRUE )
- X {
- X
- X /* set variable <e> to the start of the expression */
- X
- X e = &( expression[ *position ] );
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): main loop, level <%d> element <%s> ",
- X exp_esc, e );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* detect the operation required at this level */
- X
- X exp_es[ exp_esc ].operation = exp_findop( e );
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): exp_findop() returned <%d>",
- X exp_es[ exp_esc ].operation );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* perform actions specific to the operation */
- X
- X switch( exp_es[ exp_esc ].operation )
- X {
- X case OP_ERROR:
- X main_loop = FALSE;
- X err_condition = TRUE;
- X break;
- X case OP_TERMINATE:
- X main_loop = FALSE;
- X /* *position += 1; */
- X dec_esc();
- X break;
- X case OP_STRJOIN: /* string join or tab */
- X case OP_STRTAB:
- X main_loop = FALSE;
- X dec_esc();
- X break;
- X case OP_ADD: /* in the case of any numerical operation, */
- X case OP_SUBTRACT:
- X case OP_MULTIPLY:
- X case OP_DIVIDE:
- X case OP_MODULUS:
- X case OP_EXPONENT:
- X case OP_INTDIVISION:
- X case OP_GREATERTHAN:
- X case OP_LESSTHAN:
- X case OP_GTEQ:
- X case OP_LTEQ:
- X case OP_NOTEQUAL:
- X case OP_NOT:
- X case OP_AND:
- X case OP_OR:
- X case OP_XOR:
- X case OP_IMPLIES:
- X case OP_EQUIV:
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): operator detected." );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X exp_es[ exp_esc ].pos_adv = -1; /* set to strange number */
- X
- X /* cycle through operator table to find match */
- X
- X for ( c = 0; c < N_OPERATORS; ++c )
- X {
- X if ( exp_ops[ c ].operation == exp_es[ exp_esc ].operation )
- X {
- X exp_es[ exp_esc ].pos_adv = strlen( exp_ops[ c ].symbol );
- X }
- X }
- X
- X if ( exp_es[ exp_esc ].pos_adv == -1 ) /* was a match found? */
- X {
- X exp_es[ exp_esc ].pos_adv = 0; /* no -- set to 0 */
- X }
- X break; /* and move on */
- X
- X case OP_EQUALS:
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): equal sign detected." );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X if ( assignment == TRUE )
- X {
- X exp_es[ exp_esc ].operation = OP_ASSIGN;
- X }
- X exp_es[ exp_esc ].pos_adv = 1;
- X break;
- X
- X case PARENTHESIS:
- X r = exp_paren( e );
- X break;
- X case CONST_STRING:
- X r = exp_strconst( e );
- X break;
- X case CONST_NUMERICAL:
- X r = exp_numconst( e );
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): return from exp_numconst(), r = <%d>",
- X r );
- X bwb_debug( bwb_ebuf );
- X #endif
- X break;
- X
- X case FUNCTION:
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): calling exp_function(), expression <%s>",
- X e );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X r = exp_function( e );
- X break;
- X
- X case VARIABLE:
- X r = exp_variable( e );
- X break;
- X default:
- X err_condition = TRUE;
- X main_loop = FALSE;
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in bwb_exp.c:bwb_exp(): unidentified operation (%d).",
- X exp_es[ exp_esc ].operation );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X break;
- X }
- X
- X /* increment *position counter based on previous actions */
- X
- X *position += exp_es[ exp_esc ].pos_adv;
- X exp_es[ exp_esc ].pos_adv = 0; /* reset advance counter */
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): advanced position; r <%d> err_c <%d>",
- X r, err_condition );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X #if INTENSIVE_DEBUG
- X if ( exp_es[ exp_esc ].operation == OP_EQUALS )
- X {
- X sprintf( bwb_ebuf, "in bwb_exp(): with OP_EQUALS: finished case" );
- X bwb_debug( bwb_ebuf );
- X }
- X #endif
- X
- X /* check for end of string */
- X
- X adv_loop = TRUE;
- X while( adv_loop == TRUE )
- X {
- X switch( expression[ *position ] )
- X {
- X case ' ': /* whitespace */
- X case '\t':
- X ++(*position);
- X break;
- X case '\0': /* end of string */
- X case '\r':
- X case '\n':
- X case ':':
- X main_loop = adv_loop = FALSE; /* break out of loop */
- X break;
- X default:
- X adv_loop = FALSE;
- X break;
- X }
- X }
- X
- X /* get a new stack level before looping */
- X
- X if ( main_loop == TRUE )
- X {
- X r = inc_esc();
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): increment esc, r <%d>, err_c <%d>",
- X r, err_condition );
- X bwb_debug( bwb_ebuf );
- X #endif
- X }
- X
- X /* check for error return */
- X
- X if ( r == OP_ERROR )
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): found r == OP_ERROR." );
- X bwb_debug( bwb_ebuf );
- X #endif
- X main_loop = FALSE;
- X err_condition = TRUE;
- X }
- X else
- X {
- X r = TRUE;
- X }
- X
- X } /* end of main parsing loop */
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): breakout from main parsing loop, r <%d> err_c <%d>",
- X r, err_condition );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* check error condition */
- X
- X if ( err_condition == TRUE )
- X {
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "ERROR: error detected in expression parser" );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* decrement the expression stack counter until it matches entry_level */
- X
- X while( exp_esc > entry_level )
- X {
- X dec_esc();
- X }
- X
- X }
- X
- X /* no error; normal exit from function */
- X
- X else
- X {
- X
- X /* are any more operations needed? if we are still at entry level,
- X then they are not */
- X
- X /* try operations */
- X
- X exp_operation( entry_level );
- X
- X /* see what is on top of the stack */
- X
- X if ( exp_esc > ( entry_level + 1 ))
- X {
- X switch( exp_es[ exp_esc ].operation )
- X {
- X case OP_STRJOIN:
- X if ( exp_esc != ( entry_level + 2 ))
- X {
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in bwb_exp(): OP_STRJOIN in wrong position." );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X }
- X break;
- X default:
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in bwb_exp(): incomplete expression." );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X break;
- X }
- X
- X /* decrement the expression stack counter */
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in bwb_exp(): before dec_esc type is <%c>",
- X exp_es[ exp_esc ].type );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X dec_esc();
- X
- X }
- X
- X /* assign rvar to the variable for the current level */
- X
- X rval = &( exp_es[ exp_esc ] );
- X
- X /* decrement the expression stack counter */
- X
- X dec_esc();
- X
- X /* check the current level before exit */
- X
- X if ( entry_level != exp_esc )
- X {
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in bwb_exp(): exit stack level (%d) does not match entry stack level (%d)",
- X exp_esc, entry_level );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_overflow );
- X #endif
- X }
- X
- X }
- X
- X /* return a pointer to the last stack level */
- X
- X return rval;
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_findop()
- X
- X DESCRIPTION: This function reads the expression to find
- X what operation is required at its stack level.
- X
- X***************************************************************/
- X
- Xint
- Xexp_findop( char *expression )
- X {
- X char *pointer; /* pointer to start of string */
- X register int c; /* character counter */
- X int carry_on; /* boolean: control while loop */
- X int rval; /* return value */
- X char tbuf[ MAXSTRINGSIZE + 1 ];
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_findop(): received <%s>", expression );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* set return value to OP_NULL initially */
- X
- X rval = OP_NULL;
- X
- X /* assign local pointer to expression to begin reading */
- X
- X pointer = expression;
- X
- X /* advance to the first significant character */
- X
- X carry_on = TRUE;
- X while ( carry_on == TRUE )
- X {
- X switch( *pointer )
- X {
- X case ' ': /* whitespace */
- X case '\t':
- X ++pointer; /* increment the pointer */
- X break; /* and move on */
- X default:
- X carry_on = FALSE; /* break out of while loop */
- X break;
- X }
- X }
- X
- X /* we now have the first significant character and can begin parsing */
- X
- X /* check the first character for an indication of a parenthetical
- X expression, a string constant, or a numerical constant that begins
- X with a digit (numerical constants beginning with a plus or minus
- X sign or hex/octal/binary constants will have to be detected by
- X exp_isnc() */
- X
- X carry_on = TRUE;
- X switch ( *pointer )
- X {
- X case '\"': /* this should indicate a string constant */
- X rval = CONST_STRING;
- X break;
- X case '(': /* this will indicate a simple parenthetical expression */
- X rval = PARENTHESIS;
- X break;
- X case ':': /* terminate processing */
- X rval = OP_TERMINATE;
- X break;
- X case '0': /* these will indicate a numerical constant */
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X case '7':
- X case '8':
- X case '9':
- X case '.':
- X case '&': /* designator for hex or octal constant */
- X rval = CONST_NUMERICAL;
- X break;
- X }
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_findop(): rval pos 1 is <%d>", rval );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* string constants, numerical constants, open parentheses, and
- X the plus and minus operators have been checked at this point;
- X but if the return value is still OP_NULL, other possibilities
- X must be checked, namely, other operators, function names, and
- X variable names */
- X
- X /* get a character string to be interpreted */
- X
- X if ( rval == OP_NULL )
- X {
- X
- X carry_on = TRUE;
- X c = 0;
- X tbuf[ c ] = *pointer;
- X ++c;
- X tbuf[ c ] = '\0';
- X while( carry_on == TRUE )
- X {
- X switch( pointer[ c ] )
- X {
- X case ' ': /* whitespace */
- X case '\t':
- X case '(':
- X case ')':
- X case ',':
- X case ';':
- X case '\0':
- X case '\n':
- X case '\r':
- X carry_on = FALSE;
- X break;
- X default:
- X tbuf[ c ] = pointer[ c ];
- X ++c;
- X tbuf[ c ] = '\0';
- X break;
- X }
- X }
- X
- X }
- X
- X /* check for a BASIC command */
- X
- X if ( rval == OP_NULL )
- X {
- X rval = exp_iscmd( tbuf );
- X }
- X
- X /* check for numerical constant */
- X
- X if ( rval == OP_NULL )
- X {
- X rval = exp_isnc( tbuf );
- X }
- X
- X /* check for other operators */
- X
- X if ( rval == OP_NULL )
- X {
- X rval = exp_isop( tbuf );
- X }
- X
- X /* check for function name */
- X
- X if ( rval == OP_NULL )
- X {
- X rval = exp_isfn( tbuf );
- X }
- X
- X /* last: check for variable name, and assign it if there
- X is not already one */
- X
- X if ( rval == OP_NULL )
- X {
- X rval = exp_isvn( tbuf );
- X }
- X
- X /* return the value assigned (or OP_NULL if none assigned) */
- X
- X return rval;
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_isnc()
- X
- X DESCRIPTION: This function reads the expression to find
- X if a logical or mathematical operation is required at
- X this point.
- X
- X***************************************************************/
- X
- Xint
- Xexp_isnc( char *expression )
- X {
- X
- X switch( expression[ 0 ] )
- X {
- X case '0': /* these will indicate a numerical constant */
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X case '7':
- X case '8':
- X case '9':
- X case '&': /* indicator for hex or octal constant */
- X return CONST_NUMERICAL;
- X case '+':
- X case '-':
- X
- X /* if the previous stack level was a numerical value or a string,
- X then this is certainly not one; return OP_NULL here
- X and let the next function call to exp_isop() determine
- X the (plus or minus) operator */
- X
- X if ( ( exp_es[ exp_esc - 1 ].operation == NUMBER )
- X || ( exp_es[ exp_esc - 1 ].operation == VARIABLE )
- X || ( exp_es[ exp_esc - 1 ].operation == CONST_STRING ) )
- X {
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_isnc(): previous function is a number or string" );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X return OP_NULL;
- X }
- X
- X /* similarly, if the previous stack level was a variable
- X with a numerical value (not a string), then this level
- X must be an operator, not a numerical constant */
- X
- X if ( ( exp_es[ exp_esc - 1 ].operation == VARIABLE )
- X && ( exp_es[ exp_esc - 1 ].type != STRING ))
- X {
- X return OP_NULL;
- X }
- X
- X /* failing these tests, the argument must be a numerical
- X constant preceded by a plus or minus sign */
- X
- X return CONST_NUMERICAL;
- X
- X default:
- X return OP_NULL;
- X }
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_isop()
- X
- X DESCRIPTION: This function reads the expression to find
- X if a logical or mathematical operation is required at
- X this point.
- X
- X This function presupposes that a numerical constant with
- X affixed plus or minus sign has been ruled out.
- X
- X***************************************************************/
- X
- Xint
- Xexp_isop( char *expression )
- X {
- X register int c; /* counter */
- X char tbuf[ MAXSTRINGSIZE + 1 ];
- X
- X /* first convert the expression to upper-case so that comparisons
- X will work */
- X
- X for ( c = 0; expression[ c ] != '\0'; ++c )
- X {
- X if ( islower( expression[ c ] ))
- X {
- X tbuf[ c ] = toupper( expression[ c ] );
- X }
- X else
- X {
- X tbuf[ c ] = expression[ c ];
- X }
- X tbuf[ c + 1 ] = '\0';
- X }
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_isop(): expression is <%s>", tbuf );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* compare the initial characters of the string with the table
- X of operators */
- X
- X for ( c = 0; c < N_OPERATORS; ++c )
- X {
- X if ( strncmp( tbuf, exp_ops[ c ].symbol,
- X (size_t) strlen( exp_ops[ c ].symbol ) ) == 0 )
- X {
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_isop(): match <%s>, number <%d>.",
- X exp_ops[ c ].symbol, c );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X return exp_ops[ c ].operation;
- X }
- X }
- X
- X /* search failed; return OP_NULL */
- X
- X return OP_NULL;
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_iscmd()
- X
- X DESCRIPTION: This function reads the expression to find
- X if a BASIC command name is present; if so, it returns
- X OP_TERMINATE to terminate expression parsing. This is
- X critical, for example, in parsing a conditional following
- X IF where THEN, ELSE, and other BASIC commands may follow.
- X
- X***************************************************************/
- X
- Xint
- Xexp_iscmd( char *expression )
- X {
- X register int n;
- X char tbuf[ MAXSTRINGSIZE + 1 ];
- X
- X /* capitalize the expression */
- X
- X for ( n = 0; expression[ n ] != '\0'; ++n )
- X {
- X if ( n >= MAXARGSIZE )
- X {
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "Maximum arguments size exceeded." );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_overflow );
- X #endif
- X }
- X if ( islower( expression[ n ] ) != FALSE )
- X {
- X tbuf[ n ] = toupper( expression[ n ] );
- X }
- X else
- X {
- X tbuf[ n ] = expression[ n ];
- X }
- X tbuf[ n + 1 ] = '\0';
- X }
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_iscmd(): expression received <%s>, converted <%s>.",
- X expression, tbuf );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* first check for THEN or ELSE statements */
- X
- X if ( strcmp( tbuf, "THEN" ) == 0 )
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
- X tbuf );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return OP_TERMINATE;
- X }
- X
- X if ( strcmp( tbuf, "ELSE" ) == 0 )
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
- X tbuf );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return OP_TERMINATE;
- X }
- X
- X /* run through the command table and search for a match */
- X
- X for ( n = 0; n < COMMANDS; ++n )
- X {
- X if ( strcmp( tbuf, bwb_cmdtable[ n ].name ) == 0 )
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
- X tbuf );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return OP_TERMINATE;
- X }
- X #if INTENSIVE_DEBUG
- X else
- X {
- X sprintf( bwb_ebuf, "in exp_iscmd(): No match, <%s> and <%s>; returns %d",
- X tbuf, bwb_cmdtable[ n ].name,
- X strcmp( tbuf, bwb_cmdtable[ n ].name ) );
- X bwb_debug( bwb_ebuf );
- X }
- X #endif
- X }
- X
- X /* search failed, return NULL */
- X
- X return OP_NULL;
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_isfn()
- X
- X DESCRIPTION: This function reads the expression to find
- X if a function name is present at this point.
- X
- X***************************************************************/
- X
- Xint
- Xexp_isfn( char *expression )
- X {
- X
- X if ( fnc_find( expression ) == NULL )
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_isfn(): failed to find function <%s>",
- X expression );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return OP_NULL;
- X }
- X else
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_isfn(): found function <%s>",
- X expression );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return FUNCTION;
- X }
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_isvn()
- X
- X DESCRIPTION: This function reads the expression to find
- X if a variable name at this point.
- X
- X***************************************************************/
- X
- Xint
- Xexp_isvn( char *expression )
- X {
- X
- X exp_getvfname( expression, exp_es[ exp_esc ].string );
- X
- X if ( var_find( exp_es[ exp_esc ].string ) == NULL )
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_isvn(): failed to find variable <%s>",
- X expression );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return OP_NULL;
- X }
- X else
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_isvn(): found variable <%s>",
- X exp_es[ exp_esc ].string );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return VARIABLE;
- X }
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_getvfname()
- X
- X DESCRIPTION: This function reads the expression to find
- X a variable or function name at this point.
- X
- X***************************************************************/
- X
- Xint
- Xexp_getvfname( char *source, char *destination )
- X {
- X int s_pos, d_pos; /* source, destination positions */
- X
- X s_pos = d_pos = 0;
- X destination[ 0 ] = '\0';
- X while( source[ s_pos ] != '\0' )
- X {
- X
- X /* all aphabetical characters are acceptable */
- X
- X if ( isalpha( source[ s_pos ] ) != 0 )
- X
- X {
- X destination[ d_pos ] = source[ s_pos ];
- X
- X ++d_pos;
- X ++s_pos;
- X destination[ d_pos ] = '\0';
- X }
- X
- X /* numerical characters are acceptable but not in the first position */
- X
- X else if (( isdigit( source[ s_pos ] ) != 0 ) && ( d_pos != 0 ))
- X {
- X destination[ d_pos ] = source[ s_pos ];
- X ++d_pos;
- X ++s_pos;
- X destination[ d_pos ] = '\0';
- X }
- X
- X /* other characters will have to be tried on their own merits */
- X
- X else
- X {
- X switch( source[ s_pos ] )
- X {
- X
- X case '.': /* tolerated non-alphabetical characters */
- X
- X case '_':
- X destination[ d_pos ] = source[ s_pos ];
- X ++d_pos;
- X ++s_pos;
- X destination[ d_pos ] = '\0';
- X break;
- X
- X case STRING: /* terminating characters */
- X case SINGLE:
- X case DOUBLE:
- X case INTEGER:
- X destination[ d_pos ] = source[ s_pos ];
- X ++d_pos;
- X ++s_pos;
- X destination[ d_pos ] = '\0';
- X
- X return TRUE;
- X default: /* anything else is non-tolerated */
- X return FALSE;
- X }
- X }
- X }
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_getvfname(): found name <%s>", destination );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X return TRUE; /* exit after coming to the end */
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_validarg()
- X
- X DESCRIPTION: This function reads the expression to
- X determine whether it is a valid argument (to be
- X read recursively by bwb_exp() and passed to a
- X function.
- X
- X***************************************************************/
- X
- Xint
- Xexp_validarg( char *expression )
- X {
- X register int c;
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_validarg(): expression <%s>.",
- X expression );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X c = 0;
- X while ( TRUE )
- X {
- X switch( expression[ c ] )
- X {
- X case ' ':
- X case '\t':
- X ++c;
- X break;
- X case '\0':
- X return FALSE;
- X default:
- X return TRUE;
- X }
- X }
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_getdval()
- X
- X DESCRIPTION:
- X
- X***************************************************************/
- X
- Xdouble
- Xexp_getdval( struct exp_ese *e )
- X {
- X
- X /* check for variable */
- X
- X if ( e->operation == VARIABLE )
- X {
- X switch( e->type )
- X {
- X case DOUBLE:
- X return (* var_finddval( e->xvar, e->array_pos ));
- X case SINGLE:
- X return (double) (* var_findfval( e->xvar, e->array_pos ));
- X case INTEGER:
- X return (double) (* var_findival( e->xvar, e->array_pos ));
- X default:
- X bwb_error( err_mismatch );
- X return (double) 0.0;
- X }
- X }
- X
- X /* must be a numerical value */
- X
- X if ( e->operation != NUMBER )
- X {
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_getdval(): operation <%d> is not a number",
- X e->operation );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return (double) 0.0;
- X }
- X
- X /* return specific values */
- X
- X switch( e->type )
- X {
- X case SINGLE:
- X return (double) e->fval;
- X case INTEGER:
- X return (double) e->ival;
- X case DOUBLE:
- X return e->dval;
- X default:
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_getdval(): type is <%c>",
- X e->type );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return (double) 0.0;
- X }
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_getfval()
- X
- X DESCRIPTION:
- X
- X***************************************************************/
- X
- Xfloat
- Xexp_getfval( struct exp_ese *e )
- X {
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_getfval(): entry" );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* check for variable */
- X
- X if ( e->operation == VARIABLE )
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_getfval(): returning variable" );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X switch( e->type )
- X {
- X case DOUBLE:
- X return (float) (* var_finddval( e->xvar, e->array_pos ));
- X case SINGLE:
- X return (* var_findfval( e->xvar, e->array_pos ));
- X case INTEGER:
- X return (float) (* var_findival( e->xvar, e->array_pos ));
- X default:
- X bwb_error( err_mismatch );
- X return (float) 0.0;
- X }
- X }
- X
- X /* must be a numerical value */
- X
- X if ( e->operation != NUMBER )
- X {
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_getfval(): operation <%d> is not a number",
- X e->operation );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return (float) 0.0;
- X }
- X
- X /* return specific values */
- X
- X switch( e->type )
- X {
- X case SINGLE:
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_getfval(): returning from SINGLE, val <%f>",
- X e->fval );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return e->fval;
- X case INTEGER:
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_getfval(): returning from INTEGER, val <%d>",
- X e->ival );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return (float) e->ival;
- X case DOUBLE:
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_getfval(): returning from DOUBLE, val <%lf>",
- X e->dval );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return (float) e->dval;
- X default:
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_getfval(): type is <%c>",
- X e->type );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return (float) 0.0;
- X }
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_getival()
- X
- X DESCRIPTION:
- X
- X***************************************************************/
- X
- Xint
- Xexp_getival( struct exp_ese *e )
- X {
- X
- X /* check for variable */
- X
- X if ( e->operation == VARIABLE )
- X {
- X switch( e->type )
- X {
- X case DOUBLE:
- X return (int) (* var_finddval( e->xvar, e->array_pos ));
- X case SINGLE:
- X return (int) (* var_findfval( e->xvar, e->array_pos ));
- X case INTEGER:
- X return (* var_findival( e->xvar, e->array_pos ));
- X default:
- X bwb_error( err_mismatch );
- X return 0;
- X }
- X }
- X
- X /* must be a numerical value */
- X
- X if ( e->operation != NUMBER )
- X {
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_getival(): operation <%d> is not a number",
- X e->operation );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return 0;
- X }
- X
- X /* return specific values */
- X
- X switch( e->type )
- X {
- X case SINGLE:
- X return (int) e->fval;
- X case INTEGER:
- X return e->ival;
- X case DOUBLE:
- X return (int) e->dval;
- X default:
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_getival(): type is <%c>",
- X e->type );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return 0;
- X }
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_getsval()
- X
- X DESCRIPTION:
- X
- X***************************************************************/
- X
- Xbstring *
- Xexp_getsval( struct exp_ese *e )
- X {
- X static bstring b;
- X #if TEST_BSTRING
- X static int init = FALSE;
- X
- X if ( init == FALSE )
- X {
- X sprintf( b.name, "<exp_getsval() bstring>" );
- X }
- X #endif
- X
- X b.rab = FALSE;
- X
- X /* return based on operation type */
- X
- X switch( e->operation )
- X {
- X case CONST_STRING:
- X case OP_STRJOIN:
- X return &( e->sval );
- X case VARIABLE:
- X switch( e->type )
- X {
- X case STRING:
- X return var_findsval( e->xvar, e->array_pos );
- X case DOUBLE:
- X sprintf( bwb_ebuf, "%lf ", exp_getdval( e ) );
- X str_ctob( &b, bwb_ebuf );
- X return &b;
- X case SINGLE:
- X sprintf( bwb_ebuf, "%f ", exp_getfval( e ) );
- X str_ctob( &b, bwb_ebuf );
- X return &b;
- X case INTEGER:
- X sprintf( bwb_ebuf, "%d ", exp_getival( e ) );
- X str_ctob( &b, bwb_ebuf );
- X return &b;
- X default:
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
- X e->type );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return NULL;
- X }
- X break;
- X
- X case NUMBER:
- X switch( e->type )
- X {
- X case DOUBLE:
- X sprintf( bwb_ebuf, "%lf ", exp_getdval( e ) );
- X str_ctob( &b, bwb_ebuf );
- X return &b;
- X case SINGLE:
- X sprintf( bwb_ebuf, "%f ", exp_getfval( e ) );
- X str_ctob( &b, bwb_ebuf );
- X return &b;
- X case INTEGER:
- X sprintf( bwb_ebuf, "%d ", exp_getival( e ) );
- X str_ctob( &b, bwb_ebuf );
- X return &b;
- X default:
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
- X e->type );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return NULL;
- X }
- X break;
- X default:
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_getsval(): operation <%d> inappropriate",
- X e->operation );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return NULL;
- X }
- X
- X /* this point may not be reached */
- X
- X return NULL;
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_findfval()
- X
- X DESCRIPTION:
- X
- X***************************************************************/
- X
- X#ifdef NO_LONGER_IMPLEMENTED
- Xfloat *
- Xexp_findfval( struct exp_ese *e )
- X {
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_findfval(): entry" );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* check for variable */
- X
- X if ( e->operation == VARIABLE )
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_getfval(): returning variable" );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return var_findfval( e->xvar, e->xvar->array_pos );
- X }
- X
- X /* must be a numerical value */
- X
- X if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
- X {
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_findfval(): operation is not a single-precision number" );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return NULL;
- X }
- X
- X /* return specific value */
- X
- X return &( e->fval );
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_finddval()
- X
- X DESCRIPTION:
- X
- X***************************************************************/
- X
- Xdouble *
- Xexp_finddval( struct exp_ese *e )
- X {
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_finddval(): entry" );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* check for variable */
- X
- X if ( e->operation == VARIABLE )
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_getdval(): returning variable" );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return var_finddval( e->xvar, e->xvar->array_pos );
- X }
- X
- X /* must be a numerical value */
- X
- X if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
- X {
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_finddval(): operation is not a double-precision number" );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return NULL;
- X }
- X
- X /* return specific value */
- X
- X return &( e->dval );
- X
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: exp_findival()
- X
- X DESCRIPTION:
- X
- X***************************************************************/
- X
- Xint *
- Xexp_findival( struct exp_ese *e )
- X {
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_findival(): entry" );
- X bwb_debug( bwb_ebuf );
- X #endif
- X
- X /* check for variable */
- X
- X if ( e->operation == VARIABLE )
- X {
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in exp_getival(): returning variable" );
- X bwb_debug( bwb_ebuf );
- X #endif
- X return var_findival( e->xvar, e->xvar->array_pos );
- X }
- X
- X /* must be a numerical value */
- X
- X if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
- X {
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in exp_findival(): operation is not an integer number" );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_syntax );
- X #endif
- X return NULL;
- X }
- X
- X /* return specific value */
- X
- X return &( e->ival );
- X
- X }
- X#endif
- X
- X/***************************************************************
- X
- X FUNCTION: inc_esc()
- X
- X DESCRIPTION: This function increments the expression
- X stack counter.
- X
- X***************************************************************/
- X
- Xint
- Xinc_esc( void )
- X {
- X
- X #if INTENSIVE_DEBUG
- X sprintf( bwb_ebuf, "in inc_esc(): prev level <%d>",
- X exp_esc );
- X bwb_debug ( bwb_ebuf );
- X #endif
- X
- X ++exp_esc;
- X if ( exp_esc >= ESTACKSIZE )
- X {
- X --exp_esc;
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in inc_esc(): Maximum expression stack exceeded <%d>",
- X exp_esc );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_overflow );
- X #endif
- X return OP_NULL;
- X }
- X
- X #if INTENSIVE_DEBUG
- X sprintf( exp_es[ exp_esc ].string, "New Expression Stack Level %d", exp_esc );
- X #endif
- X
- X exp_es[ exp_esc ].type = INTEGER;
- X exp_es[ exp_esc ].operation = OP_NULL;
- X exp_es[ exp_esc ].pos_adv = 0;
- X
- X return TRUE;
- X }
- X
- X/***************************************************************
- X
- X FUNCTION: dec_esc()
- X
- X DESCRIPTION: This function decrements the expression
- X stack counter.
- X
- X***************************************************************/
- X
- Xint
- Xdec_esc( void )
- X {
- X --exp_esc;
- X if ( exp_esc < 0 )
- X {
- X exp_esc = 0;
- X #if PROG_ERRORS
- X sprintf( bwb_ebuf, "in dec_esc(): Expression stack counter < 0." );
- X bwb_error( bwb_ebuf );
- X #else
- X bwb_error( err_overflow );
- X #endif
- X return OP_NULL;
- X }
- X
- X return TRUE;
- X }
- END_OF_FILE
- if test 40302 -ne `wc -c <'bwb_exp.c'`; then
- echo shar: \"'bwb_exp.c'\" unpacked with wrong size!
- fi
- # end of 'bwb_exp.c'
- fi
- if test -f 'bwbasic.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bwbasic.doc'\"
- else
- echo shar: Extracting \"'bwbasic.doc'\" \(16562 characters\)
- sed "s/^X//" >'bwbasic.doc' <<'END_OF_FILE'
- X
- X
- X
- X
- X Bywater BASIC Interpreter/Shell, version 1.10
- X ---------------------------------------------
- X
- X Copyright (c) 1992, Ted A. Campbell
- X for bwBASIC version 1.10, 1 November 1992
- X
- X
- XCONTENTS:
- X
- X 1. DESCRIPTION
- X 2. TERMS OF USE
- X 3. COMMANDS AND FUNCTIONS IMPLEMENTED
- X 4. SOME NOTES ON USAGE
- X 5. UNIMPLEMENTED COMMANDS AND FUNCTIONS
- X 6. SOME NOTES ON COMPILATION
- X 7. THE STORY OF BYWATER BASIC
- X 8. COMMUNICATIONS
- X
- X
- X1. DESCRIPTION
- X
- X The Bywater BASIC Interpreter (bwBASIC) implements a large
- X superset of the ANSI Standard for Minimal BASIC (X3.60-1978)
- X in ANSI C and offers shell program facilities as an extension
- X of BASIC.
- X
- X The set of BASIC commands and functions implemented is fairly
- X limited (see section three below), although more commands and
- X functions are implemented than appear in the specification
- X for Minimal BASIC. There are no commands that are terminal- or
- X hardware specific. (Seriously -- CLS may work under bwBASIC
- X on your DOS-based pc, but that is because bwBASIC shells
- X out to DOS when it does not recognize CLS and executes CLS there.)
- X
- X The interpreter is slow. Whenever faced with a choice between
- X conceptual clarity and speed, I have consistently chosen
- X the former. The interpreter is the simplest design available,
- X and utilizes no system of intermediate code, which would speed
- X up considerably its operation. As it is, each line is interpreted
- X afresh as the interpreter comes to it.
- X
- X bwBASIC implements one feature not available in previous BASIC
- X interpreters: a shell command can be entered interactively at the
- X bwBASIC prompt, and the interpreter will execute it under a
- X command shell. For instance, the command "dir *.bas" can be
- X entered in bwBASIC (under DOS, or "ls -l *.bas" under UNIX) and
- X it will be executed as from the operating system command line.
- X Shell commands can also be given on numbered lines in a bwBASIC
- X program, so that bwBASIC can be used as a shell programming
- X language. bwBASIC's implementation of the RMDIR, CHDIR, MKDIR,
- X NAME, KILL, ENVIRON, and ENVIRON$() commands and functions
- X offer further shell-processing capabilities.
- X
- X
- X2. TERMS OF USE:
- X
- X The bwBASIC source code and executables produced from it can be
- X used subject to the following statement which is included in
- X the header to all the source code files:
- X
- X All U.S. and international copyrights are claimed by the
- X author. The author grants permission to use this code
- X and software based on it under the following conditions:
- X (a) in general, the code and software based upon it may be
- X used by individuals and by non-profit organizations; (b) it
- X may also be utilized by governmental agencies in any country,
- X with the exception of military agencies; (c) the code and/or
- X software based upon it may not be sold for a profit without
- X an explicit and specific permission from the author, except
- X that a minimal fee may be charged for media on which it is
- X copied, and for copying and handling; (d) the code must be
- X distributed in the form in which it has been released by the
- X author; and (e) the code and software based upon it may not
- X be used for illegal activities.
- X
- X
- X3. BASIC COMMANDS AND FUNCTIONS IMPLEMENTED:
- X
- X ABS( number )
- X ASC( string$ )
- X ATN( number )
- X CHAIN [MERGE] file-name [, line-number] [, ALL]
- X CHR$( number )
- X CINT( number )
- X CLEAR
- X CLOSE [[#]file-number]...
- X COMMON variable [, variable...]
- X COS( number )
- X CSNG( number )
- X CVD( string$ )
- X CVI( string$ )
- X CVS( string$ )
- X DATA constant[,constant]...
- X DATE$
- X DEF FNname(arg...)] = expression
- X DEFDBL letter[-letter](, letter[-letter])...
- X DEFINT letter[-letter](, letter[-letter])...
- X DEFSNG letter[-letter](, letter[-letter])...
- X DEFSTR letter[-letter](, letter[-letter])...
- X DELETE line[-line]
- X DIM variable(elements...)[variable(elements...)]...
- X END
- X ENVIRON variable-string = string
- X ENVIRON$( variable-string )
- X EOF( device-number )
- X ERASE variable[, variable]...
- X ERL
- X ERR
- X ERROR number
- X EXP( number )
- X FIELD [#] device-number, number AS string-variable [, number AS string-variable...]
- X FOR counter = start TO finish [STEP increment]
- X GET [#] device-number [, record-number]
- X GOSUB line
- X GOTO line
- X HEX$( number )
- X IF expression THEN statement [ELSE statement]
- X INPUT [# device-number]|[;]["prompt string";]list of variables
- X INSTR( [start-position,] string-searched$, string-pattern$ )
- X INT( number )
- X KILL file-name
- X LEFT$( string$, number-of-spaces )
- X LEN( string$ )
- X LET variable = expression
- X LINE INPUT [[#] device-number,]["prompt string";] string-variable$
- X LIST line[-line]
- X LOAD file-name
- X LOC( device-number )
- X LOF( device-number )
- X LOG( number )
- X LSET string-variable$ = expression
- X MERGE file-name
- X MID$( string$, start-position-in-string[, number-of-spaces ] )
- X MKD$( double-value# )
- X MKI$( integer-value% )
- X MKS$( single-value! )
- X NAME old-file-name AS new-file-name
- X NEW
- X NEXT counter
- X OCT$( number )
- X ON variable GOTO|GOSUB line[,line,line,...]
- X ON ERROR GOSUB line
- X OPEN O|I|R, [#]device-number, file-name [,record length]
- X file-name FOR INPUT|OUTPUT|APPEND AS [#]device-number [LEN = record-length]
- X OPTION BASE number
- X POS
- X PRINT [# device-number,][USING format-string$;] expressions...
- X PUT [#] device-number [, record-number]
- X RANDOMIZE number
- X READ variable[, variable]...
- X REM string
- X RESTORE line
- X RETURN
- X RIGHT$( string$, number-of-spaces )
- X RND( number )
- X RSET string-variable$ = expression
- X RUN [line][file-name]
- X SAVE file-name
- X SGN( number )
- X SIN( number )
- X SPACE$( number )
- X SPC( number )
- X SQR( number )
- X STOP
- X STR$( number )
- X STRING$( number, ascii-value|string$ )
- X SWAP variable, variable
- X SYSTEM
- X TAB( number )
- X TAN( number )
- X TIME$
- X TIMER
- X TROFF
- X TRON
- X VAL( string$ )
- X WEND
- X WHILE expression
- X WIDTH [# device-number,] number
- X WRITE [# device-number,] element [, element ]....
- X
- X If DIRECTORY_CMDS is set to TRUE when the program is compiled,
- X then the following commands will be available:
- X
- X CHDIR pathname
- X MKDIR pathname
- X RMDIR pathname
- X
- X If DEBUG is set to TRUE when the program is compiled then
- X the following debugging commands (unique to bwBASIC) will
- X be available:
- X
- X VARS (prints a list of all variables)
- X CMDS (prints a list of all commands)
- X FNCS (prints a list of all functions)
- X
- X If COMMAND_SHELL is set to TRUE when the program is compiled,
- X then the user may enter a shell command at the bwBASIC prompt.
- X
- X
- X4. SOME NOTES ON USAGE:
- X
- X An interactive environment is provided, so that a line with a
- X line number can be entered at the bwBASIC prompt and it will be
- X added to the program in memory.
- X
- X Line numbers are not strictly required, but are useful if the
- X interactive enviroment is used for programming. For longer
- X program entry one might prefer to use an ASCII text editor, and
- X in this case lines can be entered without numbers. In this case,
- X however, one will not be able to alter the numberless lines
- X within the interactive environment.
- X
- X Command names and function names are not case sensitive,
- X so that "Run" and "RUN" and "run" are equivalent and "abs()"
- X and "ABS()" and "Abs()" are equivalent. HOWEVER: variable
- X names ARE case sensitive in bwbASIC, so that "d$" and "D$"
- X are different variables. This differs from some BASIC
- X implementations where variable names are not case sensitive.
- X
- X A filename can be specified on the command line and will be
- X LOADed and RUN immediately, so that the command line
- X
- X bwbasic prog.bas
- X
- X will load and execute "prog.bas".
- X
- X All programs are stored as ASCII text files.
- X
- X TRUE is defined as -1 and FALSE is defined as 0 in the default
- X distribution of bwBASIC. These definitions can be changed by
- X those compiling bwBASIC (see file BWBASIC.H).
- X
- X Assignment must be made to variables. This differs from some
- X implementations of BASIC where assignment can be made to a
- X function. Implication: "INSTR( 3, x$, y$ ) = z$" will not
- X work under bwBASIC.
- X
- X Notes on the implementation of specific commands:
- X
- X CVI(), CVD(), CVS(), MKI$(), MKD$(), MKS$(): These functions
- X are implemented, but are dependent on a) the sizes for integer,
- X float, and double values on particular systems, and b) how
- X particular versions of C store these numerical values. The
- X implication is that data files created using these functions
- X on a DOS-based microcomputer may not be translated correctly
- X by bwBASIC running on a Unix-based computer. Similarly, data
- X files created by bwBASIC compiled by one version of C may not be
- X readable by bwBASIC compiled by another version of C (even under
- X the same operating system). So be careful with these.
- X
- X ENVIRON: The ENVIRON command requires BASIC strings on either
- X side of the equals sign. Thus:
- X
- X environ "PATH" = "/usr/bin"
- X
- X It might be noted that this differs from the implementation
- X of ENVIRON in some versions of BASIC, but bwBASIC's ENVIRON
- X allows BASIC variables to be used on either side of the equals
- X sign. Note that the function ENVIRON$() is different from the
- X command, and be aware of the fact that in some operating systems
- X an environment variable set within a program will not be passed
- X to its parent shell.
- X
- X ERR: Note that if PROG_ERRORS has been defined when bwBASIC is
- X compiled, the ERR variable will not be set correctly upon
- X errors. It only works when standard error messages are used.
- X
- X FOR and NEXT: In this implementation of bwBASIC, a NEXT
- X statement must appear in the first position in a program
- X line; it cannot appear in a line segment beyond a colon.
- X
- X INPUT: bwBASIC cannot support the optional feature of INPUT
- X that suppresses the carriage-return and line-feed at the end
- X of the input. This is because ANSI C does not provide for any
- X means of input other than CR-LF-terminated strings.
- X
- X
- X5. UNIMPLEMENTED COMMANDS AND FUNCTIONS
- X
- X There are a few items not implemented that have been so long
- X a part of standard BASICs that their absence will seem surprising.
- X In each case, though, their implementation would require opera-
- X ting-system-specific functions or terminal-specific functions
- X that ANSI C cannot provide. Some specific examples:
- X
- X CALL In some versions of BASIC, CALL is used to call a
- X machine language subroutine, but machine language
- X routines are highly system-specific. In other
- X BASICs (conforming to the more complete ANSI
- X definition of BASIC), CALL is used to call a
- X named subroutine. Although it's possible that
- X bwBASIC could develop as a numberless BASIC
- X with named subroutine calls, these features
- X are not implemented in this earliest released
- X version.
- X
- X CLOAD See CALL above (machine language subroutines).
- X
- X CONT See RESUME below (programmer ignorance?).
- X
- X DEF USR See CALL above (machine language subroutines).
- X
- X EDIT EDIT would be especially nice, but requires some
- X specific knowledge of how particular computers
- X handle interaction between the screen and the
- X keyboard. This knowledge isn't available within
- X the bounds of ANSI C alone ("innerhalb die Grenzen
- X der reinen Vernunft," with apologies to Immanuel
- X Kant).
- X
- X FRE() The ability to report the amount of free memory
- X remaining is system-specific due to varying patterns
- X of memory allocation and access; consequently this
- X ability is not present in ANSI C and this function
- X is not available in bwBASIC.
- X
- X FILES The FILES command requires a list of files conforming
- X to a specifier; ANSI C does not provide this. When
- X COMMAND_SHELL is defined as TRUE, users might want
- X to issue operating-system commands such as "DIR"
- X (DOS) or "ls -l" (Unix) to get a list of files.
- X
- X INKEY$ This function requires a keyboard scan to indicate
- X whether a key is pending. Although this facility
- X is easily available on microcomputers (it is part
- X of the minimal CP/M Operating System), it is not
- X easily available on some more complex systems.
- X Consequently, it's not part of the C standard and
- X bwBASIC has not implemented INKEY$.
- X
- X INPUT$() Similar to INKEY$ above, ANSI C by itself is not
- X able to read unechoed keyboard input, and can read
- X keyboard input only after a Carriage-Return has
- X been entered.
- X
- X INP Calls to hardware ports, like machine-language
- X routines, are highly system-specific and cannot
- X be implemented in ANSI C alone.
- X
- X LLIST See LPRINT below.
- X
- X LPOS See LPRINT below.
- X
- X LPRINT and LLIST, etc., require access to a printer device,
- X and this varies from one system to another. Users
- X might try OPENing the printer device on their own
- X operating system (e.g., "/dev/lp" on Unix systems,
- X or "PRN" under DOS) and see if printing can be done
- X from bwBASIC in this way.
- X
- X NULL In this case, I am convinced that NULL is no longer
- X necessary, since very few printers now require NULLs
- X at the end of lines.
- X
- X OUT See INP above (calls to hardware ports).
- X
- X PEEK() PEEK and POKE enabled earlier BASICs to address
- X particular memory locations. Although bwBASIC
- X could possibly implement this command (POKE) and
- X this function (PEEK()), the limitation would be
- X highly limited by the different systems for
- X memory access in different systems.
- X
- X POKE see PEEK() above.
- X
- X RENUM Since unnumbered lines can be entered and
- X executed under bwBASIC, it would not be
- X possible to implement a RENUM routine.
- X
- X RESUME Is this possible under ANSI C? If so, I
- X simply have failed to figure it out yet.
- X Mea culpa (but not maxima).
- X
- X USR See CALL and DEF USR above (machine language
- X subroutines).
- X
- X VARPTR See PEEK and POKE above.
- X
- X WAIT See INP and OUT above.
- X
- X
- X6. SOME NOTES ON COMPILATION
- X
- X bwBASIC is written in ANSI C and takes advantage of some of the
- X enhancements of ANSI C over the older K&R standard. The program
- X expects to find standard ANSI C include files (such as <stddef.h>).
- X Because there is nothing terminal- or hardware-specific about it,
- X I should hope that it would compile correctly under any ANSI C
- X compiler, but you may have to construct your own makefile.
- X
- X Two makefiles are currently provided: "makefile.qcl" will compile
- X the program utilizing the Microsoft QuickC (tm) line-oriented
- X compiler on DOS-based p.c.'s, and "makefile.gcc" will compile
- X the program utilizing the ANSI option of Gnu C++. I have also
- X compiled the program utilizing Borland's Turbo C++ (tm) on DOS-
- X based machines.
- X
- X No alterations to flags are necessary for varied environments,
- X but the beginning of file <bwbasic.h> allows the user to set
- X some debugging flags and to control some program defaults.
- X The file <bwb_mes.h> has a number of language-specific message
- X sets that can be controlled by setting the appropriate language
- X flag.
- X
- X
- X7. THE STORY OF BYWATER BASIC
- X
- X This program was originally begun in 1982 by my grandmother, Mrs.
- X Verda Spell of Beaumont, TX. She was writing the program using
- X an ANSI C compiler on an Osborne I CP/M computer and although my
- X grandfather (Lockwood Spell) had bought an IBM PC with 256k of
- X RAM my grandmother would not use it, paraphrasing George Herbert
- X to the effect that "He who cannot in 64k program, cannot in 512k."
- X She had used Microsoft BASIC and although she had nothing against
- X it she said repeatedly that she didn't understand why Digital
- X Research didn't "sue the socks off of Microsoft" for version 1.0
- X of MSDOS and so I reckon that she hoped to undercut Microsoft's
- X entire market and eventually build a new software empire on
- X the North End of Beaumont. Her programming efforts were cut
- X tragically short when she was thrown from a Beaumont to Port
- X Arthur commuter train in the summer of 1986. I found the source
- X code to bwBASIC on a single-density Osborne diskette in her knitting
- X bag and eventually managed to have it all copied over to a PC
- X diskette. I have revised it slightly prior to this release. You
- X should know, though, that I myself am an historian, not a programmer.
- X
- X
- X8. COMMUNICATIONS:
- X
- X Ted A. Campbell
- X Bywater Software
- X P.O. Box 4023
- X Duke Station
- X Durham, NC 27706
- X USA
- X
- X email: tcamp@acpub.duke.edu
- END_OF_FILE
- if test 16562 -ne `wc -c <'bwbasic.doc'`; then
- echo shar: \"'bwbasic.doc'\" unpacked with wrong size!
- fi
- # end of 'bwbasic.doc'
- fi
- echo shar: End of archive 6 \(of 11\).
- cp /dev/null ark6isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 11 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-