|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982 |
- /***************************************************************f
-
- bwb_int.c Line Interpretation 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). */
- /* */
- /* Those additionally marked with "DD" were at the suggestion of */
- /* Dale DePriest (daled@cadence.com). */
- /*---------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <ctype.h>
-
- #include "bwbasic.h"
- #include "bwb_mes.h"
-
- /***************************************************************
-
- FUNCTION: adv_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>.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- adv_element( char *buffer, int *pos, char *element )
- #else
- int
- adv_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 ';':
- #if MULTISEG_LINES
- case ':':
- #endif
- case '=':
- case ' ':
- case '\t':
- /* case '\0': */ /* Removed by JBV (found by DD) */
- 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 '\0': /* Added by JBV (found by DD) */
- if ( str_const == TRUE ) /* termination of string constant */
- {
- element[ e_pos ] = '\"';
- element[ ++e_pos ] = '\0';
- }
- 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;
-
- default:
- element[ e_pos ] = buffer[ *pos ];
- ++e_pos;
- ++( *pos );
- element[ e_pos ] = '\0';
- break;
- }
- }
-
- /* This should not happen */
-
- return FALSE;
-
- }
-
- /***************************************************************
-
- FUNCTION: adv_ws()
-
- DESCRIPTION: This function reads characters in <buffer>
- beginning at <pos> and advances past any
- whitespace, incrementing <pos> appropri-
- ately.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- adv_ws( char *buffer, int *pos )
- #else
- int
- adv_ws( buffer, pos )
- char *buffer;
- int *pos;
- #endif
- {
- int loop;
-
- loop = TRUE;
- while ( loop == TRUE )
- {
- switch( buffer[ *pos ] )
- {
- case ' ':
- case '\t':
- ++( *pos );
- break;
- default:
- return TRUE;
- }
- }
-
- /* This should not happen */
-
- return FALSE;
-
- }
-
- /***************************************************************
-
- FUNCTION: adv_eos()
-
- DESCRIPTION: This function reads characters in <buffer>
- beginning at <pos> and advances to the
- end of a segment delimited by ':',
- incrementing <pos> appropriately.
-
- ***************************************************************/
-
- #if MULTISEG_LINES
- #if ANSI_C
- int
- adv_eos( char *buffer, int *pos )
- #else
- int
- adv_eos( buffer, pos )
- char *buffer;
- int *pos;
- #endif
- {
- int loop;
-
- loop = TRUE;
- while ( loop == TRUE )
- {
-
- if ( is_eol( buffer, pos ) == TRUE )
- {
- return FALSE;
- }
-
- switch( buffer[ *pos ] )
- {
- case ':': /* end of segment marker */
- ++( *pos );
- return TRUE;
-
- case '\"': /* begin quoted string */
-
- ++( *pos );
-
- while ( buffer[ *pos ] != '\"' )
- {
- if ( is_eol( buffer, pos ) == TRUE )
- {
- return FALSE;
- }
- else
- {
- ++( *pos );
- }
- }
-
- break;
-
- default:
- ++( *pos );
- }
- }
-
- /* This should not happen */
-
- return FALSE;
-
- }
-
- #endif /* MULTISEG_LINES */
-
- /***************************************************************
-
- FUNCTION: bwb_strtoupper()
-
- DESCRIPTION: This function converts the string in
- <buffer> to upper-case characters.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- bwb_strtoupper( char *buffer )
- #else
- int
- bwb_strtoupper( buffer )
- char *buffer;
- #endif
- {
- char *p;
-
- p = buffer;
- while ( *p != '\0' )
- {
- if ( islower( *p ) != FALSE )
- {
- *p = (char) toupper( *p );
- }
- ++p;
- }
-
- return TRUE;
-
- }
-
- /***************************************************************
-
- FUNCTION: line_start()
-
- DESCRIPTION: This function reads a line buffer in
- <buffer> beginning at the position
- <pos> and attempts to determine (a)
- the position of the line number in the
- buffer (returned in <lnpos>), (b) the
- line number at this position (returned
- in <lnum>), (c) the position of the
- BASIC command in the buffer (returned
- in <cmdpos>), (d) the position of this
- BASIC command in the command table
- (returned in <cmdnum>), and (e) the
- position of the beginning of the rest
- of the line (returned in <startpos>).
- Although <startpos> must be returned
- as a positive integer, the other
- searches may fail, in which case FALSE
- will be returned in their positions.
- <pos> is not incremented.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- line_start( char *buffer, int *pos, int *lnpos, int *lnum, int *cmdpos,
- int *cmdnum, int *startpos )
- #else
- int
- line_start( buffer, pos, lnpos, lnum, cmdpos, cmdnum, startpos )
- char *buffer;
- int *pos;
- int *lnpos;
- int *lnum;
- int *cmdpos;
- int *cmdnum;
- int *startpos;
- #endif
- {
- static int position;
- static char *tbuf;
- static int init = FALSE;
-
- /* get memory for temporary buffer if necessary */
-
- if ( init == FALSE )
- {
- init = TRUE;
-
- /* Revised to CALLOC pass-thru call by JBV */
- if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "line_start")) == NULL )
- {
- #if PROG_ERRORS
- bwb_error( "in line_start(): failed to get memory for tbuf" );
- #else
- bwb_error( err_getmem );
- #endif
- }
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in line_start(): pos <%d> buffer <%s>", *pos,
- buffer );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* set initial values */
-
- *startpos = position = *pos;
- *cmdpos = *lnpos = *pos;
- *cmdnum = *lnum = -1;
-
- /* check for null line */
-
- adv_ws( buffer, &position );
- if ( buffer[ position ] == '\0' )
- {
- #if INTENSIVE_DEBUG
- bwb_debug( "in line_start(): found NULL line" );
- #endif
- *cmdnum = getcmdnum( CMD_REM );
- return TRUE;
- }
-
- /* advance beyond the first element */
-
- *lnpos = position;
- scan_element( buffer, &position, tbuf );
- adv_ws( buffer, &position );
-
- /* test for a line number in the first element */
-
- if ( is_numconst( tbuf ) == TRUE ) /* a line number */
- {
-
- *lnum = atoi( tbuf );
- *startpos = position; /* temp */
- *cmdpos = position;
-
- scan_element( buffer, &position, tbuf ); /* advance past next element */
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in line_start(): new element is <%s>", tbuf );
- bwb_debug( bwb_ebuf );
- #endif
-
- #if STRUCT_CMDS
- if ( is_label( tbuf ) == TRUE )
- {
- *cmdnum = getcmdnum( CMD_LABEL );
- adv_ws( buffer, &position );
- *startpos = position;
- }
-
- else if ( is_cmd( tbuf, cmdnum ) == TRUE )
- #else
- if ( is_cmd( tbuf, cmdnum ) == TRUE )
- #endif
- {
- adv_ws( buffer, &position );
- *startpos = position;
- }
-
- else if ( is_let( &( buffer[ *cmdpos ] ), cmdnum ) == TRUE )
- {
- *cmdpos = -1;
- }
-
- else
- {
- *cmdpos = *cmdnum = -1;
- }
- }
-
- /* not a line number */
-
- else
- {
- *lnum = -1;
- *lnpos = -1;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in line_start(): no line number, element <%s>.",
- tbuf );
- bwb_debug( bwb_ebuf );
- #endif
-
- #if STRUCT_CMDS
- if ( is_label( tbuf ) == TRUE )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in line_start(): label detected <%s>.",
- tbuf );
- bwb_debug( bwb_ebuf );
- #endif
-
- *cmdnum = getcmdnum( CMD_LABEL );
- adv_ws( buffer, &position );
- *startpos = position;
- }
-
- else if ( is_cmd( tbuf, cmdnum ) == TRUE )
- #else
- if ( is_cmd( tbuf, cmdnum ) == TRUE )
- #endif
- {
- adv_ws( buffer, &position );
- *startpos = position;
- }
-
- else if ( is_let( &( buffer[ position ] ), cmdnum ) == TRUE )
- {
- adv_ws( buffer, &position );
- *cmdpos = -1;
- }
-
- else
- {
- *cmdpos = *cmdnum = -1;
- }
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in line_start(): lnpos <%d> lnum <%d>",
- *lnpos, *lnum );
- bwb_debug( bwb_ebuf );
- sprintf( bwb_ebuf, "in line_start(): cmdpos <%d> cmdnum <%d> startpos <%d>",
- *cmdpos, *cmdnum, *startpos );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* return */
-
- return TRUE;
-
- }
-
- /***************************************************************
-
- FUNCTION: is_cmd()
-
- DESCRIPTION: This function determines whether the
- string in 'buffer' is a BASIC command
- statement, returning TRUE or FALSE,
- and if TRUE returning the command number
- in the command lookup table in the
- integer pointed to by 'cmdnum'.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- is_cmd( char *buffer, int *cmdnum )
- #else
- int
- is_cmd( buffer, cmdnum )
- char *buffer;
- int *cmdnum;
- #endif
- {
- register int n;
-
- /* Convert the command name to upper case */
-
- bwb_strtoupper( buffer );
-
- /* Go through the command table and search for a match. */
-
- for ( n = 0; n < COMMANDS; ++n )
- {
- if ( strcmp( bwb_cmdtable[ n ].name, buffer ) == 0 )
- {
- *cmdnum = n;
- return TRUE;
- }
- }
-
- /* No command name was found */
-
- *cmdnum = -1;
- return FALSE;
-
- }
-
- /***************************************************************
-
- FUNCTION: is_let()
-
- DESCRIPTION: This function tries to determine if the
- expression in <buffer> is a LET statement
- without the LET command specified.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- is_let( char *buffer, int *cmdnum )
- #else
- int
- is_let( buffer, cmdnum )
- char *buffer;
- int *cmdnum;
- #endif
- {
- register int n, i;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in is_let(): buffer <%s>", buffer );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* Go through the expression and search for an assignment operator. */
-
- for ( n = 0; buffer[ n ] != '\0'; ++n )
- {
- switch( buffer[ n ] )
- {
- case '\"': /* string constant */
- ++n;
- while( buffer[ n ] != '\"' )
- {
- ++n;
- if ( buffer[ n ] == '\0' )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "Incomplete string constant" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- *cmdnum = -1;
- return FALSE;
- }
- }
- ++n;
- break;
- case '=':
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in is_let(): implied LET found." );
- bwb_debug( bwb_ebuf );
- #endif
-
- for ( i = 0; i < COMMANDS; ++i )
- {
- if ( strncmp( bwb_cmdtable[ i ].name, "LET", (size_t) 3 ) == 0 )
- {
- *cmdnum = i;
- }
- }
- return TRUE;
- }
- }
-
- /* No command name was found */
-
- *cmdnum = -1;
- return FALSE;
-
- }
-
- /***************************************************************
-
- FUNCTION: bwb_stripcr()
-
- DESCRIPTION: This function strips the carriage return
- or line-feed from the end of a string.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- bwb_stripcr( char *s )
- #else
- int
- bwb_stripcr( s )
- char *s;
- #endif
- {
- char *p;
-
- p = s;
- while ( *p != 0 )
- {
- switch( *p )
- {
-
-
- case '\r':
- case '\n':
- *p = 0;
- return TRUE;
- }
- ++p;
- }
- *p = 0;
- return TRUE;
- }
-
- /***************************************************************
-
- FUNCTION: is_numconst()
-
- DESCRIPTION: This function reads the string in <buffer>
- and returns TRUE if it is a numerical
- constant and FALSE if it is not. At
- this point, only decimal (base 10)
- constants are detected.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- is_numconst( char *buffer )
- #else
- int
- is_numconst( buffer )
- char *buffer;
- #endif
- {
- char *p;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in is_numconst(): received string <%s>.", buffer );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* Return FALSE for empty buffer */
-
- if ( buffer[ 0 ] == '\0' )
- {
- return FALSE;
- }
-
- /* else check digits */
-
- p = buffer;
- while( *p != '\0' )
- {
- switch( *p )
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- break;
- default:
- return FALSE;
- }
- ++p;
- }
-
- /* only numerical characters detected */
-
- return TRUE;
-
- }
-
- /***************************************************************
-
- FUNCTION: bwb_numseq()
-
- DESCRIPTION: This function reads in a sequence of
- numbers (e.g., "10-120"), returning
- the first and last numbers in the sequence
- in the integers pointed to by 'start' and
- 'end'.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- bwb_numseq( char *buffer, int *start, int *end )
- #else
- int
- bwb_numseq( buffer, start, end )
- char *buffer;
- int *start;
- int *end;
- #endif
- {
- register int b, n;
- int numbers;
- static char *tbuf;
- static int init = FALSE;
-
- /* get memory for temporary buffer if necessary */
-
- if ( init == FALSE )
- {
- init = TRUE;
-
- /* Revised to CALLOC pass-thru call by JBV */
- if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "bwb_numseq")) == NULL )
- {
- #if PROG_ERRORS
- bwb_error( "in bwb_numseq(): failed to find memory for tbuf" );
- #else
- bwb_error( err_getmem );
- #endif
- }
- }
-
- if ( buffer[ 0 ] == 0 )
- {
- *start = *end = 0;
- return FALSE;
- }
-
- numbers = n = b = 0;
- tbuf[ 0 ] = 0;
- while( TRUE )
- {
- switch( buffer[ b ] )
- {
- case 0: /* end of string */
- case '\n':
- case '\r':
- if ( n > 0 )
- {
- if ( numbers == 0 )
- {
- *end = 0;
- *start = atoi( tbuf );
- ++numbers;
- }
- else
- {
-
- *end = atoi( tbuf );
- return TRUE;
- }
- }
- else
- {
- if ( numbers == 0 )
- {
- *start = *end = 0;
- }
- else if ( numbers == 1 )
- {
- *end = 0;
- }
- else if ( ( numbers == 2 ) && ( tbuf[ 0 ] == 0 ))
- {
- *end = 0;
- }
- }
- return TRUE;
-
- #ifdef ALLOWWHITESPACE
- case ' ': /* whitespace */
- case '\t':
- #endif
-
- case '-': /* or skip to next number */
- if ( n > 0 )
- {
- if ( numbers == 0 )
- {
- *start = atoi( tbuf );
- ++numbers;
- }
- else
- {
- *end = atoi( tbuf );
- return TRUE;
- }
- }
- ++b;
- n = 0;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- tbuf[ n ] = buffer[ b ];
- ++n;
- tbuf[ n ] = 0;
- ++b;
- break;
- default:
- #if PROG_ERRORS
- sprintf( bwb_ebuf,
- "ERROR: character <%c> unexpected in numerical sequence",
- buffer[ b ] );
- ++b;
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- break;
- }
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: bwb_freeline()
-
- DESCRIPTION: This function frees memory associated
- with a program line in memory.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- bwb_freeline( struct bwb_line *l )
- #else
- int
- bwb_freeline( l )
- struct bwb_line *l;
- #endif
- {
-
- /* free arguments if there are any */
-
- /* Revised to FREE pass-thru calls by JBV */
- if (l->buffer != NULL)
- {
- FREE( l->buffer, "bwb_freeline" );
- l->buffer = NULL; /* JBV */
- }
- FREE( l, "bwb_freeline" );
- l = NULL; /* JBV */
-
- return TRUE;
- }
-
- /***************************************************************
-
- FUNCTION: int_qmdstr()
-
- DESCRIPTION: This function returns a string delimited
- by quotation marks.
-
- ***************************************************************/
-
- #if ANSI_C
- int
- int_qmdstr( char *buffer_a, char *buffer_b )
- #else
- int
- int_qmdstr( buffer_a, buffer_b )
- char *buffer_a;
- char *buffer_b;
- #endif
- {
- char *a, *b;
-
- a = buffer_a;
- ++a; /* advance beyond quotation mark */
- b = buffer_b;
-
- while( *a != '\"' )
- {
- *b = *a;
- ++a;
- ++b;
- *b = '\0';
- }
-
- return TRUE;
-
- }
-
- /***************************************************************
-
- FUNCTION: is_eol()
-
- DESCRIPTION: This function determines whether the buffer
- is at the end of a line.
-
- ***************************************************************/
-
- #if ANSI_C
- extern int
- is_eol( char *buffer, int *position )
- #else
- int
- is_eol( buffer, position )
- char *buffer;
- int *position;
- #endif
- {
-
- adv_ws( buffer, position );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in is_eol(): character is <0x%x> = <%c>",
- buffer[ *position ], buffer[ *position ] );
- bwb_debug( bwb_ebuf );
- #endif
-
- switch( buffer[ *position ] )
- {
- case '\0':
- case '\n':
- case '\r':
- #if MULTISEG_LINES
- case ':':
- #endif
- return TRUE;
- default:
- return FALSE;
- }
-
- }
-
|