int load_program( char* p,char* fname );
void label_init();
int get_next_label( char* s );
void fpush( struct for_stack i );
void gpush( char* s );
int look_up( char* s );
void get_exp( int* result );
//void level1( int* result );
void assignment();
void level2( int* result );
void level3( int* result );
void level4( int* result );
void level5( int* result );
void level6( int* result );
void primitive( int* result );
void arith( char o,int* r,int* h );
void unary( char o,int* r );
void putback();
void serror( int error );
void get_token();
int iswhite( char c );
int isdelim( char c );
int find_var( char* s );
// Load the program to execute.
if( !load_program( p_buf,argv[ 1 ] ) ) {
free( p_buf );
printf( "Can not load the program %s to execute!\r\n",argv[ 1 ] );
exit( 1 );
}
// Initialize the long jump buffer.
if( setjmp( e_buf ) ) {
free( p_buf );
printf( "\r\n* * * BAD JOB! * * *\r\n" );
exit( 1 );
}
prog = p_buf;
scan_labels();
ftos = 0;
gtos = 0;
do {
//token_type = get_token();
get_token();
// Check for assignment statement.
if( token_type == VARIABLE ) {
putback(); // Return the variable to the input stream.
assignment(); // Must be assignment statement.
}
// Is command.
else {
switch( tok ) {
case PRINT:
print();
break;
case GOTO:
exec_goto();
break;
case IF:
exec_if();
break;
case FOR:
exec_for();
break;
case NEXT:
exec_next();
break;
case INPUT:
input();
break;
case GOSUB:
gosub();
break;
case RETURN:
greturn();
break;
case END:
free( p_buf );
printf( "\r\n* * * GOOD JOB! * * *\r\n" );
exit( 0 );
}
}
} while( tok != FINISHED );
return 0;
}
int load_program( char* p,char* fname )
{
FILE* fp;
int i;
if( !( fp = fopen( fname,"rb" ) ) ) return 0;
i = 0;
do {
*p = getc( fp );
p++;
i++;
} while( !feof( fp ) && i < PROG_SIZE );
*( p - 2 ) = '\0'; // Null terminate the program.
*( p - 1 ) = '\0';
fclose( fp );
return 1;
}
void assignment()
{
int var;
int value;
// Get the variable name.
get_token();
if( !isalpha( *token ) ) {
serror( 4 );
return;
}
// Find all labels.
void scan_labels()
{
int addr;
char* temp;
// Zero all labels.
label_init();
// Save pointer to top of program.
temp = prog;
// If the first token in the file is label.
get_token();
if( token_type == NUMBER ) {
strcpy( label_table[ 0 ].name,token );
label_table[ 0 ].p = prog;
}
find_eol();
do {
get_token();
if( token_type == NUMBER ) {
addr = get_next_label( token );
if( addr == -1 || addr == -2 ) {
addr == -1 ? serror( 5 ) : serror( 6 );
}
strcpy( label_table[ addr ].name,token );
label_table[ addr ].p = prog;
}
// If not on a blank line,find next line.
if( tok != EOL ) find_eol();
} while( tok != FINISHED );
prog = temp;
}
// Find the start of the next line.
void find_eol()
{
while( *prog != '\n' && *prog != '\0' ) ++prog;
if( *prog ) prog++;
}
// Return index of next free position in label arrary.
// -1: is returned if the array is full;
// -2: is returned when duplicate label is found.
int get_next_label( char* s )
{
int t;
for( t = 0; t < NUM_LAB; ++t ) {
if( label_table[ t ].name[ 0 ] == 0 ) return t;
if( !strcmp( label_table[ t ].name,s ) ) return -2;
}
return -1;
}
// Find location of given label.A null is returned if label is not found;otherwise a pointer to
// the position of label is returned.
char* find_label( char* s )
{
int t;
for( t = 0; t < NUM_LAB; ++t ) {
if( !strcmp( label_table[ t ].name,s ) ) return label_table[ t ].p;
}
return 0;
}
// Execute a GOTO command.
void exec_goto()
{
char* loc;
// Get label to goto.
get_token();
// Find the location of label.
loc = find_label( token );
if( loc == '\0' ) serror( 7 ); // Label not define.
else prog = loc; // Start program running at that loc.
}
// Initilize the array that holds the labels.
// By convention,a null label name indicates that array position is unused.
void label_init()
{
int t;
for( t = 0; t < NUM_LAB; ++t ) label_table[ t ].name[ 0 ] = '\0';
}
// Execute an IF statement.
void exec_if()
{
int x;
int y;
int cond;
char op;
get_exp( &x ); // Get left expression.
get_token(); // Get the operator.
if( !strchr( "=<>",*token ) ) {
serror( 0 );
return;
}
op = *token;
get_exp( &y ); // Get the right expression.
// Determine the outcome.
cond = 0;
switch( op ) {
case '<':
if( x < y ) cond = 1;
break;
case '>':
if( x > y ) cond = 1;
break;
case '=':
if( x == y ) cond = 1;
break;
}
if( cond ) { // Is true so process target of IF.
get_token();
if( tok != THEN ) {
serror( 8 );
return;
} // else program execution starts on next line.
}
else find_eol(); // Find start of next line.
}
// Execute a FOR loop.
void exec_for()
{
struct for_stack i;
int value;
get_token(); // Read the control variable.
if( !isalpha( *token ) ) {
serror( 4 );
return;
}
i.var = toupper( *token ) - 'A'; // Save its index.
get_token();
if( tok != TO ) serror( 9 ); // Read and discard the TO.
get_exp( &i.target ); // Get target value.
// If loop can execute at least once,push info on stack.
if( value >= variables[ i.var ] ) {
i.loc = prog;
fpush( i );
}
// Otherwise,skip loop code altogether.
else {
while( tok != NEXT ) get_token();
}
}
// Execute a NEXT statement.
void exec_next()
{
struct for_stack i;
i = fpop(); // Read the loop info.
variables[ i.var ] ++; // Increment control variable.
if( variables[ i.var ] > i.target ) return; // All down.
fpush( i );
prog = i.loc; // Loop.
}
// Push function for the FOR stack.
void fpush( struct for_stack i )
{
if( ftos > FOR_NEST ) serror( 0 );
fstack[ ftos ] = i;
ftos++;
}
// Pop function for the FOR stack.
struct for_stack fpop()
{
ftos--;
if( ftos < 0 ) serror( 11 );
return( fstack[ ftos ] );
}
// Execute a simple form of the BASIC INPUT command.
void input()
{
char var;
int i;
get_token(); // See if prompt string is present.
if( token_type == QUOTE ) {
printf( token );
// If so,print it and check for comma.
get_token();
if( *token != ',' ) serror( 1 );
get_token();
}
else printf( "?" ); // Otherwise,prompt with "?".
var = toupper( *token ) - 'A'; // Get the input variable.
scanf( "%d",&i ); // Read input.
variables[ var ] = i; // Store it.
}
// Execute a GOSUB statement.
void gosub()
{
char* loc;
get_token();
// Find the label to call.
loc = find_label( token );
if( loc == '\0' ) {
serror( 7 );
}
else {
gpush( prog ); // Save place to return to.
prog = loc; // Start program running at that loc.
}
}
// See if a string is a command or a variable.
if( token_type == STRING ) {
tok = look_up( token );
if( !tok ) token_type = VARIABLE;
else token_type = COMMAND;
}
}
// Look up a token's internal representation in the token table.
int look_up( char* s )
{
int i;
char* p;
p = s;
while( *p ) {
*p = tolower( *p );
p++;
}
for( i = 0; *table[ i ].command; i++ ) {
if( !strcmp( table[ i ].command,s ) ) return table[ i ].tok;
}
return 0;
}
int iswhite( char c )
{
if( c == ' ' || c == 0x9 ) return 1;
return 0;
}
int isdelim( char c )
{
if( strchr( ";,+-< >/*%^=()",c ) || c == 0x9 || c == '\r' || c == 0 ) return 1;
return 0;
}