/*
* Copyright (C) 1995-1997 Christopher D. Granz
*
* This header may not be removed.
*
* Refer to the file "License" included in this package for further
* information and before using any of the following.
*/
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "emi.h"
/*
* Structures
*/
typedef struct _fake_value
{
intt iType;
int iArrayDimensions;
intt iArrayFinalType;
} fake_value;
/*
* Prototypes
*/
static void fake_var_stack_push ( fake_value * );
static void fake_var_stack_pop ( short int );
static bool fake_var_stack_overflow ( void );
static int fake_var_stack_usage ( void );
static void fake_interp_stack_push ( fake_value * );
static void fake_interp_stack_pop ( short int );
static bool fake_interp_stack_overflow ( void );
static int fake_interp_stack_usage ( void );
/*
* Globals
*/
char cErrorBuf[1024];
int iEmError;
jmp_buf jbAbortJump;
static FILE * pUsageFile;
static fake_value * pFakeStack;
static fake_value * pFakeStackEnd;
static fake_value * pFakeInterpStackPos;
static fake_value * pFakeVarStackBegin;
static fake_value * pFakeVarStackPos;
extern int iCurrentFunc;
extern char *** pppSymbolTable;
/*
* Functions
*/
void print_error( void )
{
int i;
for ( i = 0; cErrorBuf[i] != '\0'; i++ )
{
if ( i == 75 )
{
while ( cErrorBuf[i] != ' ' )
{
if ( i == 0 )
{
/* fprintf( stderr, "\nNo spaces in log string.\n" ); */
break;
}
i--;
}
cErrorBuf[i] = '\n';
break;
}
}
fprintf( stderr, "%s\n", cErrorBuf );
}
/*
* Proforms all byte code error checking.
*/
void error_check( void )
{
fake_value fv;
byte *p;
int i;
if ( ppFuncs == NULL )
return;
if ( bReportFuncUsage == TRUE
&& ( pUsageFile = fopen( pUsageFilename, "w" ) ) == NULL )
{
sprintf( cErrorBuf, "Open file: %s: %s.", pUsageFilename,
strerror( errno ) );
print_error( );
bReportFuncUsage = FALSE;
}
/*
* Init the fake stacks.
*/
if ( iInterpStackSize > 0 || iVarStackSize > 0 )
{
pFakeStack = alloc_mem( sizeof( fake_value )
* ( iInterpStackSize
+ iVarStackSize ) );
pFakeStackEnd = ( pFakeStack + iInterpStackSize
+ iVarStackSize - 1 );
pFakeInterpStackPos = pFakeStack;
pFakeVarStackBegin = ( pFakeStack + iInterpStackSize );
pFakeVarStackPos = pFakeVarStackBegin;
}
iEmError = 0;
for ( iCurrentFunc = 0; iCurrentFunc <= siTopFuncIndex;
iCurrentFunc++ )
{
if ( bReportFuncUsage == TRUE )
fprintf( pUsageFile, "%s() uses:\n",
ppFuncs[iCurrentFunc]->pName );
/*
* Push some fake arguments on the fake interpreter stack ;)
*/
for ( i = 0; i < ppFuncs[iCurrentFunc]->iNumArgs; i++ )
{
fv.iType = ppFuncs[iCurrentFunc]->pArgTypes[i];
fv.iArrayDimensions = ppFuncs[iCurrentFunc]->pArgArrayDim[i];
fv.iArrayFinalType = ppFuncs[iCurrentFunc]->pArgArrayTypes[i];
fake_interp_stack_push( &fv );
}
p = ppFuncs[iCurrentFunc]->pInstrStream;
while ( ( p - ppFuncs[iCurrentFunc]->pInstrStream )
< ppFuncs[iCurrentFunc]->ulCodeSize )
{
p = bcec( p );
if ( iEmError < 0 )
{
print_error( );
exit( 1 );
}
}
bcec( p ); /* Validate return arguments. */
if ( iEmError < 0 )
{
print_error( );
exit( 1 );
}
/*
* Free the fake interpreter and variable stacks so they're
* ready for the next function to use.
*/
fake_interp_stack_pop( fake_interp_stack_usage( ) );
fake_var_stack_pop( fake_var_stack_usage( ) );
if ( bReportFuncUsage == TRUE )
putc( '\n', pUsageFile );
}
if ( pFakeStack != NULL )
free_mem( (void **) &pFakeStack );
if ( bReportFuncUsage == TRUE )
fclose( pUsageFile );
}
/*
* Push a new fake variable onto the fake variable stack.
*/
static void fake_var_stack_push( fake_value *p )
{
if ( fake_var_stack_overflow( ) == TRUE )
{
sprintf( cErrorBuf,
"Error checker: Variable stack will overflow in %s().",
ppFuncs[iCurrentFunc]->pName );
iEmError = -1;
return;
}
*pFakeVarStackPos++ = *p;
}
/*
* Pop (delete) a number of fake variables off the fake variable
* stack.
*/
static void fake_var_stack_pop( short int siNumber )
{
while ( siNumber-- > 0 )
--pFakeVarStackPos;
}
/*
* Check for overflow in the fake variable stack.
*/
static bool fake_var_stack_overflow( void )
{
if ( pFakeVarStackPos > pFakeStackEnd )
return ( TRUE );
else
return ( FALSE );
}
/*
* Returns the number of values currently on the fake variable stack.
*/
static int fake_var_stack_usage( void )
{
return ( ( pFakeVarStackPos - pFakeVarStackBegin ) );
}
/*
* Push a new value onto the fake interpreter stack.
*/
static void fake_interp_stack_push( fake_value *p )
{
if ( fake_interp_stack_overflow( ) == TRUE )
{
sprintf( cErrorBuf,
"Error checker: Interpreter stack will overflow in %s().",
ppFuncs[iCurrentFunc]->pName );
iEmError = -2;
return;
}
*pFakeInterpStackPos++ = *p;
}
/*
* Pop a number of values off the fake interpreter stack.
*/
static void fake_interp_stack_pop( short int siNumber )
{
while ( siNumber-- > 0 )
--pFakeInterpStackPos;
}
/*
* Check for overflow in the fake interpreter stack.
*/
static bool fake_interp_stack_overflow( void )
{
if ( pFakeInterpStackPos > pFakeVarStackBegin )
return ( TRUE );
else
return ( FALSE );
}
/*
* Returns the number of values currently on the fake interpreter
* stack.
*/
static int fake_interp_stack_usage( void )
{
return ( ( pFakeInterpStackPos - pFakeStack ) );
}
/*
* Macros for getting values (constants) off an instruction byte stream.
*/
#define GET_INT1( p ) ( *( (byte *) (p) ) )
#define GET_INT2( p ) ( *( (i2 *) (p) ) )
#define GET_INT4( p ) ( *( (i4 *) (p) ) )
#define GET_FLOAT4( p ) ( *( (f4 *) (p) ) )
#define GET_FLOAT8( p ) ( *( (f8 *) (p) ) )
/*
* Macros for moving instruction byte stream pointers.
*/
#define MOVEP_1( p ) ( (p)++ )
#define MOVEP_2( p ) ( (p) += sizeof( i2 ) )
#define MOVEP_4( p ) ( (p) += sizeof( i4 ) )
#define MOVEP_8( p ) ( (p) += sizeof( f8 ) )
/*
* BCEC - Byte Code Error Check
*
* Examines a byte code and finds any errors.
*/
#define p2 ( pFakeInterpStackPos - 1 )
byte *bcec( byte *pInstrStream )
{
fake_value fv = { 0, 0, 0 };
fake_value *p;
long l = 0L;
long l2 = 0L;
long l3 = 0L;
switch ( *pInstrStream++ )
{
case INSTR_END :
if ( fake_interp_stack_usage( )
< ppFuncs[iCurrentFunc]->iNumReturn )
{
sprintf( cErrorBuf, "Error checker: "
"Inconsistent number of return values in %s().",
ppFuncs[iCurrentFunc]->pName );
iEmError = -3;
break;
}
for ( l = 0L; l < ppFuncs[iCurrentFunc]->iNumReturn; l++ )
{
if ( ( pFakeInterpStackPos - ( l + 1 ) )->iType
!= ppFuncs[iCurrentFunc]->pReturnTypes[l] )
{
sprintf( cErrorBuf,
"Error checker: Inconsistent return types in %s().",
ppFuncs[iCurrentFunc]->pName );
iEmError = -3;
break;
}
}
break;
case INSTR_NEW_INT :
fv.iType = TYPE_INT;
fake_var_stack_push( &fv );
break;
case INSTR_NEW_FLOAT :
fv.iType = TYPE_FLOAT;
fake_var_stack_push( &fv );
break;
case INSTR_NEW_STRING :
fv.iType = TYPE_STRING;
fv.iArrayFinalType = TYPE_INT;
fake_var_stack_push( &fv );
break;
case INSTR_NEW_OBJECT :
fv.iType = TYPE_OBJECT;
fake_var_stack_push( &fv );
break;
case INSTR_NEW_ARRAY :
fv.iType = TYPE_ARRAY;
fv.iArrayDimensions = 1;
fv.iArrayFinalType = GET_INT1( pInstrStream );
while ( ( fv.iArrayFinalType = GET_INT1( pInstrStream ) )
== TYPE_ARRAY )
{
MOVEP_1( pInstrStream );
fv.iArrayDimensions++;
}
fake_var_stack_push( &fv );
break;
case INSTR_PUSH_ZERO :
fv.iType = TYPE_INT;
fake_interp_stack_push( &fv );
break;
case INSTR_PUSH_ONE :
fv.iType = TYPE_INT;
fake_interp_stack_push( &fv );
break;
case INSTR_PUSH_INT1 :
fv.iType = TYPE_INT;
MOVEP_1( pInstrStream );
fake_interp_stack_push( &fv );
break;
case INSTR_PUSH_INT2 :
fv.iType = TYPE_INT;
MOVEP_2( pInstrStream );
fake_interp_stack_push( &fv );
break;
case INSTR_PUSH_INT4 :
fv.iType = TYPE_INT;
MOVEP_4( pInstrStream );
fake_interp_stack_push( &fv );
break;
case INSTR_PUSH_FLOAT4 :
fv.iType = TYPE_FLOAT;
MOVEP_4( pInstrStream );
fake_interp_stack_push( &fv );
break;
case INSTR_PUSH_FLOAT8 :
fv.iType = TYPE_FLOAT;
MOVEP_8( pInstrStream );
fake_interp_stack_push( &fv );
break;
case INSTR_PUSH_STRING :
fv.iType = TYPE_STRING;
fv.iArrayFinalType = TYPE_INT;
l = GET_INT1( pInstrStream );
MOVEP_2( pInstrStream );
pInstrStream += l;
fake_interp_stack_push( &fv );
break;
case INSTR_PUSH_LOCAL :
l = GET_INT2( pInstrStream );
MOVEP_2( pInstrStream );
if ( ( fake_var_stack_usage( ) - 1 ) < l )
{
sprintf( cErrorBuf, "Error checker: Reference "
"of non-existent variable at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 3 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -4;
break;
}
p = ( pFakeVarStackBegin + l );
fv.iType = p->iType;
fv.iArrayDimensions = p->iArrayDimensions;
fv.iArrayFinalType = p->iArrayFinalType;
fake_interp_stack_push( &fv );
break;
case INSTR_PUSH_INDEX :
if ( fake_interp_stack_usage( ) < 2 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -5;
break;
}
p = ( pFakeInterpStackPos - 2 );
if ( p->iType != TYPE_STRING && p->iType != TYPE_ARRAY )
{
sprintf( cErrorBuf, "Error checker: "
"Index reference in non-array at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -5;
break;
}
if ( p2->iType != TYPE_INT )
{
sprintf( cErrorBuf, "Error checker: "
"Index reference with wrong type at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -5;
break;
}
if ( p->iType == TYPE_STRING )
{
fv.iType = TYPE_STRING;
fv.iArrayFinalType = p->iArrayFinalType;
}
else if ( p->iArrayDimensions > 1 )
{
fv.iType = TYPE_ARRAY;
fv.iArrayDimensions = ( p->iArrayDimensions - 1 );
fv.iArrayFinalType = p->iArrayFinalType;
}
else
fv.iType = p->iArrayFinalType;
fake_interp_stack_pop( 2 );
fake_interp_stack_push( &fv );
break;
case INSTR_POP :
if ( fake_interp_stack_usage( ) < 1 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -6;
break;
}
fake_interp_stack_pop( 1 );
break;
case INSTR_ASSIGN_LOCAL :
l = GET_INT2( pInstrStream );
MOVEP_2( pInstrStream );
if ( ( fake_var_stack_usage( ) - 1 ) < l )
{
sprintf( cErrorBuf, "Error checker: Reference "
"of non-existent variable at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 3 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -7;
break;
}
p = ( pFakeVarStackBegin + l );
if ( fake_interp_stack_usage( ) < 1 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 3 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -7;
break;
}
if ( p->iType != p2->iType )
{
sprintf( cErrorBuf, "Error checker: Incompatiable types "
"in assignment at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 3 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -7;
break;
}
p->iType = p2->iType;
p->iArrayDimensions = p2->iArrayDimensions;
p->iArrayFinalType = p2->iArrayFinalType;
fake_interp_stack_pop( 1 );
break;
case INSTR_ASSIGN_INDEX :
if ( fake_interp_stack_usage( ) < 3 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -8;
break;
}
p = ( pFakeInterpStackPos - 3 );
if ( p->iType != TYPE_STRING && p->iType != TYPE_ARRAY )
{
sprintf( cErrorBuf, "Error checker: "
"Index reference in non-array at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -8;
break;
}
if ( ( pFakeInterpStackPos - 2 )->iType != TYPE_INT )
{
sprintf( cErrorBuf, "Error checker: "
"Index reference with wrong type at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -8;
break;
}
if ( ( p->iType == TYPE_ARRAY
&& ( p->iArrayDimensions > 1 ? p2->iType != TYPE_ARRAY
: p->iArrayFinalType != p2->iType ) )
|| ( p->iType == TYPE_STRING && p2->iType != TYPE_INT ) )
{
sprintf( cErrorBuf, "Error checker: Incompatiable types "
"in assignment at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -8;
break;
}
fake_interp_stack_pop( 2 );
break;
case INSTR_MULTIPLY :
case INSTR_DIVIDE :
case INSTR_SUBTRACT :
if ( fake_interp_stack_usage( ) < 2 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -9;
break;
}
if ( ( p2->iType != TYPE_INT && p2->iType != TYPE_FLOAT )
|| ( ( pFakeInterpStackPos - 2 )->iType != TYPE_INT
&& ( pFakeInterpStackPos - 2 )->iType != TYPE_FLOAT ) )
{
sprintf( cErrorBuf, "Error checker: Illegal "
"type for math instruction at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -9;
break;
}
if ( p2->iType != ( pFakeInterpStackPos - 2 )->iType )
{
sprintf( cErrorBuf, "Error checker: Incompatiable types "
"in math instruction at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -9;
break;
}
fake_interp_stack_pop( 1 );
break;
case INSTR_MODULUS :
case INSTR_LSHIFT :
case INSTR_RSHIFT :
case INSTR_AND :
case INSTR_XOR :
case INSTR_OR :
if ( fake_interp_stack_usage( ) < 2 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -10;
break;
}
if ( p2->iType != TYPE_INT
|| ( pFakeInterpStackPos - 2 )->iType != TYPE_INT )
{
sprintf( cErrorBuf, "Error checker: Illegal "
"type for math instruction at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -10;
break;
}
fake_interp_stack_pop( 1 );
break;
case INSTR_ADD :
if ( fake_interp_stack_usage( ) < 2 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -11;
break;
}
if ( ( p2->iType != TYPE_INT && p2->iType != TYPE_FLOAT
&& p2->iType != TYPE_STRING )
|| ( ( pFakeInterpStackPos - 2 )->iType != TYPE_INT
&& ( pFakeInterpStackPos - 2 )->iType != TYPE_FLOAT
&& ( pFakeInterpStackPos - 2 )->iType != TYPE_STRING ) )
{
sprintf( cErrorBuf, "Error checker: Illegal "
"type for math instruction at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -11;
break;
}
if ( p2->iType != ( pFakeInterpStackPos - 2 )->iType )
{
sprintf( cErrorBuf, "Error checker: Incompatiable types "
"in math instruction at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -11;
break;
}
fake_interp_stack_pop( 1 );
break;
case INSTR_ONES_COMPLEMENT :
if ( fake_interp_stack_usage( ) < 1 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -12;
break;
}
if ( p2->iType != TYPE_INT )
{
sprintf( cErrorBuf, "Error checker: Illegal "
"type for math instruction at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -12;
break;
}
break;
case INSTR_JUMP :
/* We don't do jumps in the error checker. */
l = GET_INT2( pInstrStream );
MOVEP_2( pInstrStream );
if ( l < 0 )
{
if ( -l > ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream ) )
goto jmp_instr_error;
}
else
{
if ( l > ( ppFuncs[iCurrentFunc]->ulCodeSize - 1 ) )
goto jmp_instr_error;
}
break;
jmp_instr_error:
sprintf( cErrorBuf, "Error checker: Jump "
"instruction points out of bounds at offset %ld in %s().",
(long) ( pInstrStream - ppFuncs[iCurrentFunc]->pInstrStream
- 2 ), ppFuncs[iCurrentFunc]->pName );
iEmError = -13;
break;
case INSTR_COMPARE :
if ( fake_interp_stack_usage( ) < 2 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -14;
break;
}
if ( ( pFakeInterpStackPos - 2 )->iType != p2->iType
|| p2->iType == TYPE_ARRAY /* Arrays can't be compared. */ )
{
sprintf( cErrorBuf, "Error checker: Incompatible "
"types for compare instruction at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -14;
break;
}
l = GET_INT2( pInstrStream );
MOVEP_2( pInstrStream );
if ( l < 0 )
goto jmp_instr_error; /* No backward jumps with compare. */
else
{
if ( l > ( ppFuncs[iCurrentFunc]->ulCodeSize - 1 ) )
goto jmp_instr_error;
}
switch ( GET_INT1( pInstrStream ) )
{
case COND_EQUAL :
case COND_NOT_EQUAL : break;
case COND_GREATER :
case COND_LESS :
case COND_GREATER_OR_EQUAL:
case COND_LESS_OR_EQUAL :
if ( p2->iType != TYPE_INT && p2->iType != TYPE_FLOAT )
{
sprintf( cErrorBuf, "Error checker: "
"Illegal conditional type at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 3 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -14;
return ( pInstrStream );
}
break;
default :
sprintf( cErrorBuf, "Error checker: "
"Unknown conditional type at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 3 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -14;
return ( pInstrStream );
}
MOVEP_1( pInstrStream );
{
fake_value *pInterpSav = pFakeInterpStackPos;
fake_value *pVarSav = pFakeVarStackPos;
byte *pInstrSav = pInstrStream;
while ( *pInstrStream != INSTR_END )
pInstrStream = bcec( pInstrStream );
pInstrStream++; /* Skip past END instruction. */
fake_interp_stack_pop( ( pFakeInterpStackPos
- pInterpSav ) );
fake_var_stack_pop( ( pFakeVarStackPos - pVarSav ) );
if ( ( pInstrStream - pInstrSav ) < l )
{
pInterpSav = pFakeInterpStackPos;
pVarSav = pFakeVarStackPos;
while ( *pInstrStream != INSTR_END )
pInstrStream = bcec( pInstrStream );
pInstrStream++; /* Skip past END instruction. */
fake_interp_stack_pop( ( pFakeInterpStackPos
- pInterpSav ) );
fake_var_stack_pop( ( pFakeVarStackPos - pVarSav ) );
}
}
break;
case INSTR_CALL_BUILTIN_FUNC :
if ( fake_interp_stack_usage( ) < 1 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -15;
break;
}
fake_interp_stack_pop( 1 );
l = GET_INT1( pInstrStream );
MOVEP_1( pInstrStream );
if ( fake_interp_stack_usage( ) < l )
{
sprintf( cErrorBuf, "Error checker: Too few arguments "
"in call to builtin function at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 2 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -15;
break;
}
for ( l2 = 2L, l3 = 1L; l > 0L; l--, l2++, l3++ )
{
fv.iArrayDimensions = -1;
fv.iArrayFinalType = 0;
do
{
fv.iType = GET_INT1( pInstrStream );
MOVEP_1( pInstrStream );
l2++;
fv.iArrayDimensions++;
}
while ( fv.iType == TYPE_ARRAY );
switch ( fv.iType )
{
case TYPE_INT :
case TYPE_FLOAT :
case TYPE_STRING:
case TYPE_OBJECT: break;
default :
sprintf( cErrorBuf, "Error checker: "
"Unknown variable type at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - l2 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -15;
return ( pInstrStream );
}
if ( fv.iArrayDimensions > 0 )
{
fv.iArrayFinalType = fv.iType;
fv.iType = TYPE_ARRAY;
}
else if ( fv.iType == TYPE_STRING )
fv.iArrayFinalType = TYPE_INT;
p = ( pFakeInterpStackPos - l3 );
if ( p->iType != fv.iType
|| p->iArrayDimensions != fv.iArrayDimensions
|| p->iArrayFinalType != fv.iArrayFinalType )
{
sprintf( cErrorBuf, "Error checker: Incompatible type "
"in passing to builtin function at offset %ld "
"in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - l2 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -15;
return ( pInstrStream );
}
}
l = 0L;
l = GET_INT1( pInstrStream );
MOVEP_1( pInstrStream );
for ( l2++; l > 0L; l--, l2++ )
{
fv.iArrayDimensions = -1;
fv.iArrayFinalType = 0;
do
{
fv.iType = GET_INT1( pInstrStream );
MOVEP_1( pInstrStream );
l2++;
fv.iArrayDimensions++;
}
while ( fv.iType == TYPE_ARRAY );
switch ( fv.iType )
{
case TYPE_INT :
case TYPE_FLOAT :
case TYPE_STRING:
case TYPE_OBJECT: break;
default :
sprintf( cErrorBuf, "Error checker: "
"Unknown variable type at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - l2 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -15;
return ( pInstrStream );
}
if ( fv.iArrayDimensions > 0 )
{
fv.iArrayFinalType = fv.iType;
fv.iType = TYPE_ARRAY;
}
else if ( fv.iType == TYPE_STRING )
fv.iArrayFinalType = TYPE_INT;
fake_interp_stack_push( &fv );
}
break;
case INSTR_CALL_FUNC :
if ( fake_interp_stack_usage( ) < 1 )
{
sprintf( cErrorBuf, "Error checker: Too few values on "
"interpreter stack for operation at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 1 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -16;
break;
}
fake_interp_stack_pop( 1 );
l = GET_INT1( pInstrStream );
MOVEP_1( pInstrStream );
if ( fake_interp_stack_usage( ) < l )
{
sprintf( cErrorBuf, "Error checker: Too few arguments "
"in call to user function at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - 2 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -16;
break;
}
for ( l2 = 2L, l3 = 1L; l > 0L; l--, l2++, l3++ )
{
fv.iArrayDimensions = -1;
fv.iArrayFinalType = 0;
do
{
fv.iType = GET_INT1( pInstrStream );
MOVEP_1( pInstrStream );
l2++;
fv.iArrayDimensions++;
}
while ( fv.iType == TYPE_ARRAY );
switch ( fv.iType )
{
case TYPE_INT :
case TYPE_FLOAT :
case TYPE_STRING:
case TYPE_OBJECT: break;
default :
sprintf( cErrorBuf, "Error checker: "
"Unknown variable type at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - l2 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -16;
return ( pInstrStream );
}
if ( fv.iArrayDimensions > 0 )
{
fv.iArrayFinalType = fv.iType;
fv.iType = TYPE_ARRAY;
}
else if ( fv.iType == TYPE_STRING )
fv.iArrayFinalType = TYPE_INT;
p = ( pFakeInterpStackPos - l3 );
if ( p->iType != fv.iType
|| p->iArrayDimensions != fv.iArrayDimensions
|| p->iArrayFinalType != fv.iArrayFinalType )
{
sprintf( cErrorBuf, "Error checker: Incompatible type "
"in passing to user function at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - l2 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -16;
return ( pInstrStream );
}
}
l = 0L;
l = GET_INT1( pInstrStream );
MOVEP_1( pInstrStream );
for ( l2++; l > 0L; l--, l2++ )
{
fv.iArrayDimensions = -1;
fv.iArrayFinalType = 0;
do
{
fv.iType = GET_INT1( pInstrStream );
MOVEP_1( pInstrStream );
l2++;
fv.iArrayDimensions++;
}
while ( fv.iType == TYPE_ARRAY );
switch ( fv.iType )
{
case TYPE_INT :
case TYPE_FLOAT :
case TYPE_STRING:
case TYPE_OBJECT: break;
default :
sprintf( cErrorBuf, "Error checker: "
"Unknown variable type at offset %ld in %s().",
(long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream - l2 ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -16;
return ( pInstrStream );
}
if ( fv.iArrayDimensions > 0 )
{
fv.iArrayFinalType = fv.iType;
fv.iType = TYPE_ARRAY;
}
else if ( fv.iType == TYPE_STRING )
fv.iArrayFinalType = TYPE_INT;
fake_interp_stack_push( &fv );
}
break;
case TRANS_BUILTIN_FUNC :
if ( bReportFuncUsage == TRUE )
fprintf( pUsageFile, " Builtin %s();\n",
pppSymbolTable[ppFuncs[iCurrentFunc]->siFileNumber]
[GET_INT2( pInstrStream )] );
MOVEP_2( pInstrStream );
fv.iType = TYPE_INT;
fake_interp_stack_push( &fv );
break;
case TRANS_FUNC :
if ( bReportFuncUsage == TRUE )
fprintf( pUsageFile, " User %s();\n",
pppSymbolTable[ppFuncs[iCurrentFunc]->siFileNumber]
[GET_INT2( pInstrStream )] );
MOVEP_2( pInstrStream );
fv.iType = TYPE_INT;
fake_interp_stack_push( &fv );
break;
default :
sprintf( cErrorBuf, "Error checker: "
"Illegal instruction (0x%.2X) at offset %ld in %s().",
(int) *--pInstrStream, (long) ( pInstrStream
- ppFuncs[iCurrentFunc]->pInstrStream ),
ppFuncs[iCurrentFunc]->pName );
iEmError = -17;
break;
}
return ( pInstrStream );
}
#undef p2
#undef GET_INT1
#undef GET_INT2
#undef GET_INT4
#undef GET_FLOAT4
#undef GET_FLOAT8
#undef MOVEP_1
#undef MOVEP_2
#undef MOVEP_4
#undef MOVEP_8
/*
* End of error.c
*/