home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************f
-
- bwb_int.c Line Interpretation Routines
- for Bywater BASIC Interpreter
-
- Copyright (c) 1992, Ted A. Campbell
-
- Bywater Software
- P. O. Box 4023
- Duke Station
- Durham, NC 27706
-
- email: tcamp@acpub.duke.edu
-
- Copyright and Permissions Information:
-
- All U.S. and international copyrights are claimed by the
- author. The author grants permission to use this code
- and software based on it under the following conditions:
- (a) in general, the code and software based upon it may be
- used by individuals and by non-profit organizations; (b) it
- may also be utilized by governmental agencies in any country,
- with the exception of military agencies; (c) the code and/or
- software based upon it may not be sold for a profit without
- an explicit and specific permission from the author, except
- that a minimal fee may be charged for media on which it is
- copied, and for copying and handling; (d) the code must be
- distributed in the form in which it has been released by the
- author; and (e) the code and software based upon it may not
- be used for illegal activities.
-
- ***************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.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>.
-
- ***************************************************************/
-
- int
- adv_element( char *buffer, int *pos, char *element )
- {
- int loop; /* control loop */
- int e_pos; /* position in element buffer */
- int str_const; /* boolean: building a string constant */
-
- /* advance beyond any initial whitespace */
-
- adv_ws( buffer, pos );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in adv_element(): receieved <%s>.", &( buffer[ *pos ] ));
- bwb_debug( bwb_ebuf );
- #endif
-
- /* now loop while building an element and looking for an
- element terminator */
-
- loop = TRUE;
- e_pos = 0;
- element[ e_pos ] = '\0';
- str_const = FALSE;
-
- while ( loop == TRUE )
- {
- switch( buffer[ *pos ] )
- {
- case ',': /* element terminators */
- case ';':
- case ':':
- case '=':
- case ' ':
- case '\t':
- case '\0':
- case '\n':
- case '\r':
- if ( str_const == TRUE )
- {
- element[ e_pos ] = buffer[ *pos ];
- ++e_pos;
- ++( *pos );
- element[ e_pos ] = '\0';
- }
- else
- {
- return TRUE;
- }
- break;
-
- case '\"': /* string constant */
- element[ e_pos ] = buffer[ *pos ];
- ++e_pos;
- ++( *pos );
- element[ e_pos ] = '\0';
- if ( str_const == TRUE ) /* termination of string constant */
- {
- return TRUE;
- }
- else /* beginning of string constant */
- {
- str_const = TRUE;
- }
- break;
-
- 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.
-
- ***************************************************************/
-
- int
- adv_ws( char *buffer, int *pos )
- {
- 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: bwb_strtoupper()
-
- DESCRIPTION: This function converts the string in
- <buffer> to upper-case characters.
-
- ***************************************************************/
-
- int
- bwb_strtoupper( char *buffer )
- {
- char *p;
-
- p = buffer;
- while ( *p != '\0' )
- {
- if ( islower( *p ) != FALSE )
- {
- *p = 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.
-
- ***************************************************************/
-
- int
- line_start( char *buffer, int *pos, int *lnpos, int *lnum, int *cmdpos,
- int *cmdnum, int *startpos )
- {
- static int position;
- register int n;
- static char *tbuf;
- static int init = FALSE;
-
- /* get memory for temporary buffer if necessary */
-
- if ( init == FALSE )
- {
- init = TRUE;
- if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
- {
- bwb_error( err_getmem );
- }
- }
-
- #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( "REM" );
- return TRUE;
- }
-
- /* advance beyond the first element */
-
- *lnpos = position;
- adv_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;
-
- adv_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 ( is_cmd( tbuf, cmdnum ) == TRUE )
- {
- 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 ( is_cmd( tbuf, cmdnum ) == TRUE )
- {
- 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:
-
- ***************************************************************/
-
- int
- is_cmd( char *buffer, int *cmdnum )
- {
- 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 ( strncmp( bwb_cmdtable[ n ].name, buffer,
- strlen( bwb_cmdtable[ n ].name )) == 0 )
- {
- *cmdnum = n;
- #if INTENSIVE_DEBUG
- bwb_debug( "in is_cmd(): command found" );
- #endif
- return TRUE;
- }
- }
-
- /* No command name was found */
-
- #if INTENSIVE_DEBUG
- bwb_debug( "in is_cmd(): command not found" );
- #endif
-
- *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.
-
- ***************************************************************/
-
- int
- is_let( char *buffer, int *cmdnum )
- {
- 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:
-
-
- ***************************************************************/
-
- int
- bwb_stripcr( char *s )
- {
- 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.
-
- ***************************************************************/
-
- int
- is_numconst( char *buffer )
- {
- 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:
-
- ***************************************************************/
-
- int
- bwb_numseq( char *buffer, int *start, int *end )
- {
- 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;
- if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
- {
- bwb_error( err_getmem );
- }
- }
-
- 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:
-
- ***************************************************************/
-
- int
- bwb_freeline( struct bwb_line *l )
- {
- register int n;
-
- /* free arguments if there are any */
-
- free( l );
-
- return TRUE;
- }
-
- /***************************************************************
-
- FUNCTION: int_qmdstr()
-
- DESCRIPTION: This function finds a quotation-mark
- delimited string.
-
- ***************************************************************/
-
- int
- int_qmdstr( char *buffer_a, char *buffer_b )
- {
- char *a, *b;
-
- a = buffer_a;
- ++a; /* advance beyond quotation mark */
- b = buffer_b;
-
- while( *a != '\"' )
- {
- *b = *a;
- ++a;
- ++b;
- *b = '\0';
- }
-
- return TRUE;
-
- }
-