📄 bwbasic.c
字号:
/*************************************************************** bwbasic.c Main Program File for Bywater BASIC Interpreter Copyright (c) 1993, Ted A. Campbell Bywater Software "I was no programmer, neither was I a programmer's son; but I was an herdman and a gatherer of sycomore fruit." - Amos 7:14b AV, slightly adapted 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 <math.h>#include "bwbasic.h"#include "bwb_mes.h"#if HAVE_SIGNAL#include <signal.h>#endif#if HAVE_LONGJUMP#include <setjmp.h>#endifchar *bwb_ebuf; /* error buffer */static char *read_line;int bwb_trace = FALSE;FILE *errfdevice = stderr; /* output device for error messages */#if HAVE_LONGJUMPjmp_buf mark;#endifstatic int program_run = 0; /* has the command-line program been run? */int bwb_curtask = 0; /* current task */struct bwb_variable *ed; /* BWB.EDITOR$ variable */struct bwb_variable *fi; /* BWB.FILES$ variable */struct bwb_variable *pr; /* BWB.PROMPT$ variable */struct bwb_variable *im; /* BWB.IMPLEMENTATION$ variable */struct bwb_variable *co; /* BWB.COLORS variable */#if PARACTstruct bwb_task *bwb_tasks[ TASKS ]; /* table of task pointers */#elsechar progfile[ MAXARGSIZE ]; /* program file */int rescan = TRUE; /* program needs to be rescanned */int number = 0; /* current line number */struct bwb_line *bwb_l; /* current line pointer */struct bwb_line bwb_start; /* starting line marker */struct bwb_line bwb_end; /* ending line marker */struct bwb_line *data_line; /* current line to read data */int data_pos = 0; /* position in data_line */struct bwb_variable var_start; /* variable list start marker */struct bwb_variable var_end; /* variable list end marker */struct bwb_function fnc_start; /* function list start marker */struct bwb_function fnc_end; /* function list end marker */struct fslte fslt_start; /* function-sub-label lookup table start marker */struct fslte fslt_end; /* function-sub-label lookup table end marker */int exsc = -1; /* EXEC stack counter */int expsc = 0; /* expression stack counter */int xtxtsc = 0; /* eXecute TeXT stack counter */struct exse *excs; /* EXEC stack */struct exp_ese *exps; /* Expression stack */struct xtxtsl *xtxts; /* Execute Text stack */#endif/* Prototypes for functions visible only to this file */#if ANSI_Cextern int is_ln( char *buffer );#elseextern int is_ln();#endif/*************************************************************** FUNCTION: bwb_init() DESCRIPTION: This function initializes bwBASIC.***************************************************************/void#if ANSI_Cbwb_init( int argc, char **argv )#elsebwb_init( argc, argv ) int argc; char **argv;#endif { static FILE *input = NULL; register int n;#if PROFILE struct bwb_variable *v;#endif#if REDIRECT_STDERR FILE *newerr;#endif#if PROFILE FILE *profile;#endif#if PARACT#else static char start_buf[] = "\0"; static char end_buf[] = "\0";#endif#if INTENSIVE_DEBUG prn_xprintf( stderr, "Memory Allocation Statistics:\n" ); prn_xprintf( stderr, "----------------------------\n" );#if PARACT sprintf( bwb_ebuf, "task structure: %ld bytes\n", (long) sizeof( struct bwb_task ) ); prn_xprintf( stderr, bwb_ebuf ); getchar();#endif#endif /* set all task pointers to NULL */#if PARACT for ( n = 0; n < TASKS; ++n ) { bwb_tasks[ n ] = NULL; }#else /* Memory allocation */ /* eXecute TeXT stack */ /* Revised to CALLOC pass-thru call by JBV */ if ( ( xtxts = CALLOC( XTXTSTACKSIZE, sizeof( struct xtxtsl ), "bwb_init") ) == NULL ) {#if PROG_ERRORS bwb_error( "in bwb_init(): failed to find memory for xtxts" );#else bwb_error( err_getmem );#endif } /* expression stack */ /* Revised to CALLOC pass-thru call by JBV */ if ( ( exps = CALLOC( ESTACKSIZE, sizeof( struct exp_ese ), "bwb_init") ) == NULL ) {#if PROG_ERRORS bwb_error( "in bwb_init(): failed to find memory for exps" );#else bwb_error( err_getmem );#endif } /* EXEC stack */ /* Revised to CALLOC pass-thru call by JBV */ if ( ( excs = CALLOC( EXECLEVELS, sizeof( struct exse ), "bwb_init") ) == NULL ) {#if PROG_ERRORS bwb_error( "in bwb_init(): failed to find memory for excs" );#else bwb_error( err_getmem );#endif } /* initialize tables of variables, functions */ bwb_start.number = 0; bwb_start.next = &bwb_end; bwb_end.number = MAXLINENO + 1; bwb_end.next = &bwb_end; bwb_start.buffer = start_buf; bwb_end.buffer = end_buf; data_line = &bwb_start; data_pos = 0; exsc = -1; expsc = 0; xtxtsc = 0; bwb_start.position = 0; bwb_l = &bwb_start; var_init( 0 ); fnc_init( 0 ); fslt_init( 0 );#endif /* character buffers */ /* Revised to CALLOC pass-thru call by JBV */ if ( ( bwb_ebuf = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_init") ) == NULL ) {#if PROG_ERRORS bwb_error( "in bwb_init(): failed to find memory for bwb_ebuf" );#else bwb_error( err_getmem );#endif } /* Revised to CALLOC pass-thru call by JBV */ if ( ( read_line = CALLOC( MAXREADLINESIZE + 1, sizeof(char), "bwb_init") ) == NULL ) {#if PROG_ERRORS bwb_error( "in bwb_init(): failed to find memory for read_line" );#else bwb_error( err_getmem );#endif }#if PARACT /* request task 0 as current (base) task */ bwb_curtask = bwb_newtask( 0 ); if ( bwb_curtask == -1 ) { return; /* error message has already been called*/ }#endif#if TEST_BSTRING for ( n = 0; n < ESTACKSIZE; ++n ) { sprintf( CURTASK exps[ n ].sval.name, "<Exp stack bstring %d>", n ); }#endif /* assign memory for the device table */#if COMMON_CMDS /* Revised to CALLOC pass-thru call by JBV */ if ( ( dev_table = CALLOC( DEF_DEVICES, sizeof( struct dev_element ), "bwb_init") ) == NULL ) {#if PROG_ERRORS bwb_error( "in bwb_init(): failed to find memory for dev_table" );#else bwb_error( err_getmem );#endif bwx_terminate(); } /* initialize all devices to DEVMODE_AVAILABLE */ for ( n = 0; n < DEF_DEVICES; ++n ) { dev_table[ n ].mode = DEVMODE_AVAILABLE; dev_table[ n ].reclen = -1; dev_table[ n ].cfp = NULL; dev_table[ n ].buffer = NULL; dev_table[ n ].width = DEF_WIDTH; dev_table[ n ].col = 1; }#endif /* COMMON_CMDS */ /* initialize preset variables */ ed = var_find( DEFVNAME_EDITOR ); ed->preset = TRUE; ed->common = TRUE; str_ctob( var_findsval( ed, ed->array_pos ), DEF_EDITOR ); fi = var_find( DEFVNAME_FILES ); fi->preset = TRUE; fi->common = TRUE; str_ctob( var_findsval( fi, fi->array_pos ), DEF_FILES ); pr = var_find( DEFVNAME_PROMPT ); pr->preset = TRUE; pr->common = TRUE; str_ctob( var_findsval( pr, pr->array_pos ), PROMPT ); im = var_find( DEFVNAME_IMPL ); im->preset = TRUE; im->common = TRUE; str_ctob( var_findsval( im, im->array_pos ), IMP_IDSTRING ); co = var_find( DEFVNAME_COLORS ); co->preset = TRUE; co->common = TRUE; * var_findnval( co, co->array_pos ) = (bnumber) DEF_COLORS; /* Signon message */ bwx_signon(); /* Redirect stderr if specified */#if REDIRECT_STDERR newerr = freopen( ERRFILE, "w", stderr ); if ( newerr == NULL ) { sprintf( bwb_ebuf, "Failed to redirect error messages to file <%s>\n", ERRFILE ); errfdevice = stdout; prn_xprintf( errfdevice, bwb_ebuf ); } else { sprintf( bwb_ebuf, "NOTE: Error messages are redirected to file <%s>\n", ERRFILE ); prn_xprintf( errfdevice, bwb_ebuf ); errfdevice = stderr; }#else errfdevice = stdout;#endif /* if there is a profile.bas, execute it */#if PROFILE if ( ( profile = fopen( PROFILENAME, "r" )) != NULL ) { bwb_fload( profile ); /* load profile */ bwb_run( &CURTASK bwb_start ); /* run profile */ /* profile must be run immediately, not by scheduler */ while ( CURTASK exsc > -1 ) { bwb_execline(); } /* mark all profiled variables as preset */ for ( v = CURTASK var_start.next; v != &CURTASK var_end; v = v->next ) {#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in bwb_init(): marked variable <%s> preset TRUE", v->name ); bwb_debug( bwb_ebuf );#endif v->preset = TRUE; } bwb_new( &CURTASK bwb_start ); /* remove profile from memory */ }#endif#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in main(): Ready to save jump MARKER" ); bwb_debug( bwb_ebuf );#endif /* set a buffer for jump: program execution returns to this point in case of a jump (error, interrupt, or finish program) */#if INTERACTIVE#if HAVE_SIGNAL signal( SIGINT, break_mes );#endif#if HAVE_LONGJUMP setjmp( mark );#endif#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in bwb_init(): Return from jump MARKER, program run <%d>", program_run + 1 ); bwb_debug( bwb_ebuf ); getchar();#endif /* if INTERACTIVE is FALSE, then we must have a program file */#else if ( argc < 2 ) { bwb_error( err_noprogfile ); }#endif /* INTERACTIVE */ /* check to see if there is a program file: but do this only the first time around! */ ++program_run; if (( argc > 1 ) && ( program_run == 1 )) { strcpy( CURTASK progfile, argv[ 1 ] ); /* JBV */ if ( ( input = fopen( CURTASK progfile, "r" )) == NULL ) /* JBV */ { strcat( CURTASK progfile, ".bas" ); if ( ( input = fopen( CURTASK progfile, "r" )) == NULL ) { CURTASK progfile[ 0 ] = 0; sprintf( bwb_ebuf, err_openfile, argv[ 1 ] ); bwb_error( bwb_ebuf ); } } if ( input != NULL ) { /* strcpy( CURTASK progfile, argv[ 1 ] ); */ /* Removed by JBV */#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in main(): progfile is <%s>.", CURTASK progfile ); bwb_debug( bwb_ebuf );#endif bwb_fload( input ); bwb_run( &CURTASK bwb_start ); } } }/*************************************************************** FUNCTION: bwb_interact() DESCRIPTION: This function gets a line from the user and processes it.***************************************************************/#if INTERACTIVEint#if ANSI_Cbwb_interact( void )#elsebwb_interact()#endif { char tbuf[ MAXSTRINGSIZE + 1 ]; /* JBV */#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in bwb_interact(): ready to read from keyboard" ); bwb_debug( bwb_ebuf );#endif /* take input from keyboard */ bwb_gets( read_line ); bwb_stripcr( read_line ); /* JBV */ /* If there is no line number, execute the line as received */ if ( is_ln( read_line ) == FALSE ) { bwb_xtxtline( read_line ); } /*-----------------------------------------------------------------*/ /* Another possibility: if read_line is a numeric constant, delete */ /* the indicated line number (JBV) */ /*-----------------------------------------------------------------*/ else if ( is_numconst( read_line ) == TRUE ) { strcpy(tbuf, read_line); sprintf(read_line, "delete %s\0", tbuf); bwb_xtxtline( read_line ); } /* If there is a line number, add the line to the file in memory */ else { bwb_ladd( read_line, TRUE );#if INTENSIVE_DEBUG bwb_debug( "Return from bwb_ladd()" );#endif } return TRUE; }#endif /* INTERACTIVE == TRUE *//*************************************************************** FUNCTION: bwb_fload() DESCRIPTION: This function loads a BASIC program file into memory given a FILE pointer.***************************************************************/int#if ANSI_Cbwb_fload( FILE *file )#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -