home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
POLYEDIT.LZH
/
ML
/
EXEC2.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-16
|
9KB
|
486 lines
/*
* 実行処理
*
* 1994.5.22 T.Kobayashi
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "exec.h"
#include "err.h"
#include "inlib.h"
static int CallFunctionSub( FuncBuffer*, int, int, DataStruct* );
static void ReturnValue( DataStruct* );
static void DataArrayAlloc( DataStruct*, int, int* );
static void Assign( DataStruct*, DataStruct* );
/*
* 関数の実行
*/
void ExecFunction( code )
CodeStruct *code ;
{
int ident, args ;
DataStruct *top ;
assert( code->type == CODE_IDENT && ( code->ident.itype & IDENT_FUNC ) );
ident = code->ident.ident ;
GotoNextCode();
top = StackTop() ;
args = top->id.i ;
/*StackPop();*/
CallFunctionLocal( ident, args, top - args );
/*StackRelease( top - args );*/
}
int CallFunctionLocal( ident, args, arg )
int ident, args ;
DataStruct *arg ;
{
int class ;
FuncBuffer *func ;
if ( arg->type == TYPE_OBJECT )
{
class = arg->od.ptr->type ;
while( class != 0 && ClassList[class].func[ident].type == FUNC_NO )
{
class = ClassList[class].parent ;
}
func = ClassList[class].func ;
}
else
func = ClassList[0].func ;
return CallFunctionSub( func, ident, args, arg );
}
int CallFunctionLocalParent( cls, ident, args, arg )
int cls, ident, args ;
DataStruct *arg ;
{
FuncBuffer *func ;
assert( cls > 0 );
cls = ClassList[cls].parent ;
while( cls != 0 && ClassList[cls].func[ident].type == FUNC_NO )
{
cls = ClassList[cls].parent ;
}
func = ClassList[cls].func ;
return CallFunctionSub( func, ident, args, arg );
}
static int CallFunctionSub( func, ident, args, arg )
FuncBuffer *func ;
int ident, args ;
DataStruct *arg ;
{
if ( func[ident].type == FUNC_NO )
{
if ( ident < FUNC_START )
{
ExecError( "演算子が定義されていません。" );
}
else
{
ExecError( "関数 %s が定義されていません。", IdentFunction->name[ident] );
}
}
if ( func[ident].type == FUNC_SYS )
{
/* 組み込み関数 */
int (*sysfunc)(int ident, int args, DataStruct *buf);
sysfunc = func[ident].ptr ;
assert( sysfunc != NULL );
if ( (*sysfunc)( ident, args, arg ) == RETURN_RETURN )
{
ReturnValue( arg );
return RETURN_RETURN ;
}
else
{
StackRelease( arg );
return RETURN_VOID ;
}
}
else
{
/* ユーザ定義関数 */
int ret ;
int vars, frame ;
DataStruct *curlocal ;
CodeStruct *curptr ;
CodeStruct *usrfunc ;
usrfunc = func[ident].ptr ;
vars = usrfunc->c.data.id.i ;
/* 実行アドレス、ベースポインタの退避 */
curptr = ExecPtr ;
curlocal = DataLocalVar ;
/* 実行 */
ExecPtr = usrfunc ;
GotoNextCode();
assert( ExecPtr->c.data.type == TYPE_INT );
#if 0
if ( args > vars )
ExecError( "引数の数が多すぎます" );
#endif
frame = StackTop() - arg + 1 ; /* 確保しているスタックフレーム */
vars = ExecPtr->c.data.id.i ; /* ローカル変数 */
if ( frame < vars )
StackAlloc( vars - frame );
DataLocalVar = arg ;
GotoNextCode();
ret = ExecSentense();
if ( ret == RETURN_RETURN )
ReturnValue( arg );
else
StackRelease( arg );
/* 実行アドレス、ベースポインタの復帰 */
ExecPtr = curptr ;
DataLocalVar = curlocal ;
return ret ;
}
}
/* 戻り値を引数先頭アドレスにコピーする */
static void ReturnValue( arg )
DataStruct *arg ;
{
DataStruct *top ;
top = StackTop();
if ( arg == top )
return ;
if ( arg->type == TYPE_OBJECT )
ObjectFree( arg->od.ptr );
if ( top->type == TYPE_OBJECT )
{
arg->type = TYPE_OBJECT ;
arg->od.ptr = ObjectCopy( top->od.ptr );
}
else
*arg = *top ;
StackRelease( arg );
}
/*
* return 文の実行
*/
int ExecReturn()
{
GotoNextCode();
ExecExpression();
return RETURN_RETURN ;
}
/*
* 変数宣言の実行
*/
void ExecVar()
{
int i, no, dim ;
int *dimary ;
CodeStruct *code ;
DataStruct *top ;
DataStruct *buf ;
GotoNextCode();
code = ExecPtr ;
while( code->type != CODE_OPERATOR || code->ope.otype != OPE_EXP_END )
{
assert( code->type == CODE_IDENT );
no = code->ident.ident ; /* 識別子コード */
if ( code->ident.itype & ( IDENT_ARY ) )
{
/* 配列の次数の計算 */
GotoNextCode();
ExecExpression();
/* 次数 */
top = StackTop();
assert( top->type == TYPE_INT );
dim = top->id.i ;
assert( dim >= 1 );
StackPop();
dimary = _alloca( sizeof( int ) * dim );
for( i = dim - 1 ; i >= 0 ; i-- )
{
top = StackTop();
assert( top->type == TYPE_INT );
dimary[i] = top->id.i ;
StackPop();
}
switch( code->ident.itype & (IDENT_VAR|IDENT_ARY) )
{
case IDENT_GLOBAL|IDENT_ARY:
buf = & DataGlobalVar[no] ;
break ;
case IDENT_LOCAL|IDENT_ARY:
buf = & DataLocalVar[no] ;
break ;
default:
assert( FALSE );
}
if ( buf->type & TYPE_ARRAY )
ExecError( "配列を2度宣言しようとしました。" );
DataArrayAlloc( buf, dim, dimary );
}
else
{
buf = ExecRefVar();
ExecExpression();
Assign( buf, StackTop() );
StackPop();
}
code = ExecPtr ;
}
GotoNextCode();
}
/* 配列バッファの確保 */
static void DataArrayAlloc( buf, dim, dimary )
DataStruct *buf ;
int dim ;
int *dimary ;
{
int i, n ;
n = dimary[0] ;
if ( n < 0 || 0xFFFF < n )
ExecError( "配列のサイズが不正です" );
buf->type = TYPE_ARRAY ;
buf->ad.size = n ;
buf->ad.ary = StackAlloc( n );
if ( dim > 1 )
{
buf = buf->ad.ary ;
for( i = 0 ; i < n ; i++ )
{
DataArrayAlloc( buf, dim-1, dimary+1 );
buf++ ;
}
}
}
/*
* 代入文の実行
*/
void ExecAssign( stype )
int stype ;
{
DataStruct *buf, *top = StackTop();
/* 識別子 */
GotoNextCode();
buf = ExecRefVar();
/* 式 */
ExecExpression();
Assign( buf, StackTop() );
StackRelease( top );
}
/*
* 演算子付き代入文の実行
*/
void ExecAssignOpe( stype )
int stype ;
{
int ope ;
DataStruct *buf, *top ;
/* 識別子 */
GotoNextCode();
buf = ExecRefVar();
StackPush( buf );
top = StackTop();
/* 式 */
ExecExpression();
switch( stype )
{
case SENT_ASN_PLUS:
ope = OPE_PLUS ;
break ;
case SENT_ASN_MINUS:
ope = OPE_MINUS ;
break ;
case SENT_ASN_MULT:
ope = OPE_MULT ;
break ;
case SENT_ASN_DIVIDE:
ope = OPE_DIVIDE ;
break ;
case SENT_ASN_AND:
ope = OPE_AND ;
break ;
case SENT_ASN_OR:
ope = OPE_OR ;
break ;
default:
assert( FALSE );
}
ExecOpe( ope, 2, top );
Assign( buf, top );
StackRelease( top - 1 );
}
/*
* インクリメント代入文の実行
*/
void ExecAssignInc( stype )
int stype ;
{
int ope ;
DataStruct *buf, *top ;
/* 識別子 */
GotoNextCode();
buf = ExecRefVar();
StackPush( buf );
top = StackTop();
switch( stype )
{
case SENT_ASN_INC:
ope = OPE_INC ;
break ;
case SENT_ASN_DEC:
ope = OPE_DEC ;
break ;
default:
assert( FALSE );
}
ExecOpe( ope, 1, top );
GotoNextCode();
Assign( buf, top );
StackRelease( top - 1 );
}
/* 代入 */
static void Assign( buf, top )
DataStruct *buf, *top ;
{
if ( buf->type & TYPE_OBJECT )
ObjectFree( buf->od.ptr );
if ( top->type & ( TYPE_BOOLEAN|TYPE_INT|TYPE_REAL|TYPE_TYPE|TYPE_FUNC ) )
{
*buf = *top ;
}
else if ( top->type & TYPE_ARRAY )
{
if ( buf->type & TYPE_ARRAY )
{
int i, size ;
if ( buf->ad.size != top->ad.size )
ExecError( "大きさの異なる配列は代入できません。" );
size = buf->ad.size ;
buf = buf->ad.ary ;
top = top->ad.ary ;
for( i = 0 ; i < size ; i++ )
{
Assign( buf, top );
top++ ;
buf++ ;
}
}
else
*buf = *top ;
}
else if ( top->type & TYPE_OBJECT )
{
buf->type = TYPE_OBJECT ;
buf->od.ptr = ObjectCopy( top->od.ptr );
}
}
/*
* 変数の参照
*/
DataStruct *ExecRefVar()
{
int no, dim, i, n ;
DataStruct *top ;
DataStruct *buf ;
CodeStruct *code = ExecPtr ;
no = code->ident.ident ; /* 識別子コード */
if ( code->ident.itype & IDENT_ARY )
{
/* 配列 */
GotoNextCode();
ExecExpression();
top = StackTop();
assert( top->type == TYPE_INT );
dim = top->id.i ; /* 次数 */
assert( dim >= 1 );
StackPop();
switch( code->ident.itype & (IDENT_VAR|IDENT_ARY) )
{
case IDENT_GLOBAL|IDENT_ARY:
buf = & DataGlobalVar[no] ;
break ;
case IDENT_LOCAL|IDENT_ARY:
buf = & DataLocalVar[no] ;
break ;
default:
assert( FALSE );
}
top = StackTop() - dim + 1 ;
for( i = 0 ; i < dim ; i++ )
{
if ( ( top->type & (TYPE_INT|TYPE_BOOLEAN) ) == 0 )
ExecError( "配列の添え字の型が不正です" );
n = top->id.i ;
if ( n < 0 || buf->ad.size <= n )
ExecError( "配列の添え字が不正です" );
buf = (DataStruct*)(buf->ad.ary) + n ;
top ++ ;
}
StackRelease( StackTop() - dim );
}
else
{
switch( code->ident.itype & IDENT_VAR )
{
case IDENT_GLOBAL :
buf = & DataGlobalVar[no] ;
break ;
case IDENT_LOCAL :
buf = & DataLocalVar[no] ;
break ;
default:
assert( FALSE );
}
GotoNextCode();
}
return buf ;
}