/* ----------------------------------------------------------------------
* FILE: rhcompile.c
* PACKAGE: rh - recursive file finder.
* VERSION: 4.0
* DESCRIPTION:
* Contains functions that compile byte-code from a rh source file.
*
* REVISION HISTORY:
* Oct. 27. 1990 - Created.
*
* AUTHOR:
* Ken Stauffer.
* ---------------------------------------------------------------------- */
#include "rh.h"
#include "rhparse.h"
struct object *Program;
static int Progsize;
static int LC; /* location counter */
int beginLC = -1;
int endLC = -1;
int startLC = -1;
static int LC1 = -1;
static int LC2 = -1;
char *malloc(), *realloc();
extern int lineno;
extern struct builtin builtins[];
extern char *rhfilename;
extern char StringStack[];
extern char *sfree;
extern char *mkstr();
extern int rmstr();
comp_num(opcode,operand,type)
short opcode;
long operand;
short type;
{
if( LC >= Progsize ) {
Progsize += PROG_GROW;
Program = (struct object *) realloc(Program,
Progsize*sizeof(struct object));
if( Program == NULL )
error("out of memory");
}
Program[ LC ].opcode = opcode;
Program[ LC ].type = type;
Program[ LC ].val = operand;
LC++;
}
comp_str(opcode,operand,type)
short opcode;
char *operand;
short type;
{
if( LC >= Progsize ) {
Progsize += PROG_GROW;
Program = (struct object *) realloc(Program,
Progsize*sizeof(struct object));
if( Program == NULL )
error("out of memory");
}
Program[ LC ].opcode = opcode;
Program[ LC ].type = type;
Program[ LC ].str = operand;
LC++;
}
comp_obj(opcode,operand,type)
short opcode;
struct object *operand;
short type;
{
if( LC >= Progsize ) {
Progsize += PROG_GROW;
Program = (struct object *) realloc(Program,
Progsize*sizeof(struct object));
if( Program == NULL )
error("out of memory");
}
Program[ LC ].opcode = opcode;
Program[ LC ].type = type;
Program[ LC ].obj = operand;
LC++;
}
struct expr *genstring(s)
char *s;
{
struct expr *e;
e = (struct expr *) malloc( sizeof(struct expr) );
if( e == NULL )
error("out of memory");
e->opcode = OP_STRING;
e->str = s;
e->left = e->right = NULL;
return e;
}
struct expr *gennumber(v)
long v;
{
struct expr *e;
e = (struct expr *) malloc( sizeof(struct expr) );
if( e == NULL )
error("out of memory");
e->opcode = OP_NUMBER;
e->val = v;
e->left = e->right = NULL;
return e;
}
struct expr *genvar(sym,expr)
struct symbol *sym;
struct expr *expr;
{
struct expr *e;
e = (struct expr *) malloc( sizeof(struct expr) );
if( e == NULL )
error("out of memory");
if( expr == NULL ) {
e->opcode = OP_VAR;
e->obj = sym->obj;
e->left = e->right = NULL;
} else {
e->opcode = OP_AVAR;
e->obj = sym->obj;
e->left = NULL;
e->right = expr;
}
return e;
}
struct expr *genident(sym,expr)
struct symbol *sym;
struct expr *expr;
{
struct object *o;
/* check to see if 'sym' is still an identifier,
* because it is possible that another portion of the
* parse consisted of another instance of this IDENTIFIER.
* eg. (foo + foo / foo)
*/
if( sym->type == IDENTIFIER ) {
o = (struct object *) malloc( sizeof(struct object) );
if( o == NULL )
error("out of memory");
o->type = T_NONE;
o->opcode = 0;
o->obj = NULL;
sym->type = VARIABLE;
sym->obj = o;
sym->bvar = 0;
}
return genvar(sym,expr);
}
struct expr *genparam(sym,expr)
struct symbol *sym;
struct expr *expr;
{
struct expr *e;
e = (struct expr *) malloc( sizeof(struct expr) );
if( e == NULL )
error("out of memory");
if( expr == NULL ) {
e->opcode = OP_PARAM;
e->val = sym->val;
e->left = e->right = NULL;
} else {
e->opcode = OP_APARAM;
e->val = sym->val;
e->left = NULL;
e->right = expr;
}
return e;
}
struct expr *genargs(args,expr)
struct expr *args,*expr;
{
struct expr *e;
e = (struct expr *) malloc( sizeof(struct expr) );
if( e == NULL )
error("out of memory");
e->opcode = 0;
if( args == NULL )
e->val = 0;
else
e->val = args->val + 1;
e->left = expr;
e->right = args;
return e;
}
struct expr *genfunc(func,args)
struct symbol *func;
struct expr *args;
{
struct expr *e;
int argcount;
if( args == NULL )
argcount = 0;
else
argcount = args->val+1;
if( argcount > func->val )
error("too many arguments to function %s",func->name);
else if( argcount < func->val )
error("not enough arguments to function %s",func->name);
e = (struct expr *) malloc( sizeof(struct expr) );
if( e == NULL )
error("out of memory");
e->opcode = OP_CALL;
e->type = lineno;
e->val = func->pctr;
e->left = NULL;
e->right = args;
return e;
}
struct expr *genbuiltin(builtin,args)
struct symbol *builtin;
struct expr *args;
{
struct expr *e;
e = (struct expr *) malloc( sizeof(struct expr) );
if( e == NULL )
error("out of memory");
e->opcode = OP_BUILTIN;
e->str = builtin->name;
e->left = NULL;
e->right = args;
return e;
}
struct expr *genbinary(opcode,e1,e2)
struct expr *e1,*e2;
int opcode;
{
struct expr *e;
e = (struct expr *) malloc( sizeof(struct expr) );
if( e == NULL )
error("out of memory");
e->opcode = opcode;
e->left = e1;
e->right = e2;
return e;
}
struct expr *gentrinary(e1,e2,e3)
struct expr *e1,*e2,*e3;
{
struct expr *n1, *n2;
n2 = (struct expr *) malloc( sizeof(struct expr) );
if( e2 == NULL )
error("out of memory");
n2->opcode = 0;
n2->left = e2;
n2->right = e3;
n1 = (struct expr *) malloc( sizeof(struct expr) );
if( n1 == NULL )
error("out of memory");
n1->opcode = OP_IFFALSE;
n1->left = e1;
n1->right = n2;
return n1;
}
func_1(func,args)
struct symbol *func, *args;
{
func->type = FUNCTION;
func->pctr = LC;
func->val = (args) ? args->val+1 : 0;
}
func_2(func,args)
struct symbol *func, *args;
{
struct symbol *p, *q;
int i;
func->param = NULL;
comp_num(OP_RET,func->val,0);
p = args;
while(p) {
q = p->param;
remove(p->name);
p = q;
}
for(i=func->pctr; i<LC; i++) {
if(Program[i].opcode == OP_GOTO && Program[i].type == BREAK ) {
lineno = Program[i].val;
error("illegal context for BREAK statement");
}
if(Program[i].opcode == OP_GOTO &&
Program[i].type == CONTINUE ) {
lineno = Program[i].val;
error("illegal context for CONTINUE statement");
}
}
}
genbeg1()
{
if( beginLC >= 0 )
error("BEGIN action already defined");
beginLC = LC;
}
genbeg2()
{
comp_num(OP_END,0,0);
}
genend1()
{
if( endLC >= 0 )
error("END action already defined");
endLC = LC;
}
genend2()
{
comp_num(OP_END,0,0);
}
gen1match(e)
struct expr *e;
{
if( startLC < 0 )
startLC = LC;
if( LC1 >= 0 )
Program[ LC1 ].val = LC;
if( LC2 >= 0 )
Program[ LC2 ].val = LC;
if( e ) {
gencode(e,T_NONE);
LC1 = LC;
if( e->type == T_NONE )
comp_num(OP_IFFALSE,0,0);
else if( e->type == T_STRING )
comp_num(OP_IFS_FALSE,0,0);
else if( e->type == T_NUMBER )
comp_num(OP_IFN_FALSE,0,0);
free(e);
} else
LC1 = -1;
}
gen2match()
{
LC2 = LC;
comp_num(OP_GOTO,0,0);
}
gendefault()
{
struct symbol *f, *lookup();
f = lookup("ACTION");
if( f == NULL )
error("no function ACTION() has been defined");
comp_num(OP_CALL,f->pctr,0);
comp_str(OP_POP,rhfilename,lineno);
LC2 = LC;
comp_num(OP_GOTO,0,0);
}
comp_builtin(expr,type)
struct expr *expr;
{
struct object stack[30];
struct symbol *s, *lookup();
int fold = 1;
int sp=0, ac;
struct expr *e, *a;
char *err, *dobuiltin(), *allocstr();
s = lookup(expr->str);
ac = (expr->right) ? expr->right->val+1 : 0;
if( ac != s->nargs && s->nargs >= 0)
error("incorrect number of arguments to %s()",s->name);
if( s->rtype & T_FOLD ) {
sfree = StringStack;
a = expr->right;
while(a) {
e = a->left;
if(e->opcode == OP_NUMBER) {
stack[sp].type = T_NUMBER;
stack[sp++].val = e->val;
} else if(e->opcode == OP_STRING) {
stack[sp].type = T_STRING;
stack[sp++].str = mkstr(e->str);
if(stack[sp-1].str == NULL)
error("out of memory");
} else {
fold = 0; break;
}
a = a->right;
}
if( fold && !dobuiltin(s->val,stack,&sp,ac,1) ) {
if( stack[0].type == T_NUMBER ) {
expr->type = T_NUMBER;
expr->val = stack[0].val;
comp_num(OP_NUMBER,stack[0].val,0);
} else {
rmstr(stack[0].str);
expr->type = T_STRING;
expr->str = allocstr(stack[0].str);
if( expr->str == NULL )
error("out of memory");
comp_str(OP_STRING,expr->str,0);
}
a = expr->right;
while(a) {
free(a->left);
e = a->right;
free(a);
a = e;
}
return;
}
}
a = expr->right;
while(a) {
gencode(a->left,T_NONE);
free(a->left);
e = a->right;
free(a);
a = e;
}
expr->type = s->rtype & ~T_FOLD;
comp_num(OP_BUILTIN,s->val,ac);
if( expr->type == T_NONE && type != T_NONE ) {
comp_num(OP_CHKTYPE,type,lineno);
expr->type = type;
} else if( expr->type != T_NONE && type != T_NONE &&
type != expr->type )
error("%s() returns wrong type to be used in this context",
s->name);
}
gen_expr(expr)
struct expr *expr;
{
gencode(expr,T_NONE);
free(expr);
comp_str(OP_POP,rhfilename,lineno);
}
gen_if1(expr)
struct expr *expr;
{
int lc;
gencode(expr,T_NONE);
lc = LC;
if( expr->type == T_NONE )
comp_num(OP_IFFALSE,0,0);
else if( expr->type == T_NUMBER )
comp_num(OP_IFN_FALSE,0,0);
else if( expr->type == T_STRING )
comp_num(OP_IFS_FALSE,0,0);
free(expr);
return(lc);
}
gen_if2(lc1,lc2)
{
if( lc2 < 0 )
Program[ lc1 ].val = LC;
else {
Program[ lc1 ].val = lc2+1;
Program[ lc2 ].val = LC;
}
}
gen_if3()
{
comp_num(OP_GOTO,0,0);
return LC-1;
}
gen1while(expr)
struct expr *expr;
{
int lc;
lc = LC;
gencode(expr,T_NONE);
if( expr->type == T_NONE)
comp_num(OP_IFFALSE,0,BREAK);
else if( expr->type == T_NUMBER)
comp_num(OP_IFN_FALSE,0,BREAK);
else if( expr->type == T_STRING)
comp_num(OP_IFS_FALSE,0,BREAK);
free(expr);
return lc;
}
gen2while(lc)
{
comp_num(OP_GOTO,0,CONTINUE);
backpatch(lc,LC-1,LC,lc);
}
gen_do1()
{
return LC;
}
gen_do2(expr,lc)
struct expr *expr;
{
int lc1;
lc1 = LC;
gencode(expr,T_NONE);
if( expr->type == T_NONE )
comp_num(OP_IFTRUE,lc,0);
else if( expr->type == T_NUMBER )
comp_num(OP_IFN_TRUE,lc,0);
else if( expr->type == T_STRING )
comp_num(OP_IFS_TRUE,lc,0);
backpatch(lc,LC-1,LC,lc1);
free(expr);
}
gen1for(expr1,expr2)
struct expr *expr1, *expr2;
{
int lc;
gencode(expr1,T_NONE);
comp_str(OP_POP,rhfilename,lineno);
free(expr1);
lc = LC;
gencode(expr2,T_NONE);
if( expr2->type == T_NONE )
comp_num(OP_IFFALSE,0,BREAK);
else if( expr2->type == T_NUMBER )
comp_num(OP_IFN_FALSE,0,BREAK);
else if( expr2->type == T_STRING )
comp_num(OP_IFS_FALSE,0,BREAK);
free(expr2);
return lc;
}
gen2for(lc,expr3)
struct expr *expr3;
{
int lc1;
lc1 = LC;
gencode(expr3,T_NONE);
comp_str(OP_POP,rhfilename,lineno);
free(expr3);
comp_num(OP_GOTO,lc,0);
backpatch(lc,LC-1,LC,lc1);
}
/* backpatch -
* Looks at each element Program[from] .. Program[to]
* and changes FLOW CONTROL instructions of type BREAK
* to goto the blabel, and instructions of type CONTINUE
* to goto the clabel.
*/
backpatch(from,to,blabel,clabel)
{
int i;
for(i=from; i<= to; i++) {
switch( Program[i].opcode ) {
case OP_GOTO:
case OP_IFTRUE:
case OP_IFFALSE:
case OP_IFS_TRUE:
case OP_IFS_FALSE:
case OP_IFN_FALSE:
case OP_IFN_TRUE:
if( Program[i].type == BREAK ) {
Program[i].val = blabel;
Program[i].type = 0;
} else if( Program[i].type == CONTINUE ) {
Program[i].val = clabel;
Program[i].type = 0;
}
break;
}
}
}
gen_return(expr,func)
struct expr *expr;
struct symbol *func;
{
if( func == NULL )
error("illegal context for RETURN statement");
gencode(expr,T_NONE);
free(expr);
comp_num(OP_RET,func->val,1);
}
gen_break(l)
{
comp_num(OP_GOTO,l,BREAK);
}
gen_continue(l)
{
comp_num(OP_GOTO,l,CONTINUE);
}
gen_next(f)
struct symbol *f;
{
if( f )
error("illegal context for NEXT statement");
comp_num(OP_END,0,0);
}
char *operator(opcode)
{
switch(opcode){
case OP_NOT: return("!");
case OP_NEG: return("-");
case OP_BNOT: return("~");
case OP_MUL: return("*");
case OP_DIV: return("/");
case OP_MOD: return("%");
case OP_ADD: return("+");
case OP_SUB: return("-");
case OP_BOR: return("|");
case OP_XOR: return("^");
case OP_BAND: return("&");
case OP_GT: return(">");
case OP_GE: return(">=");
case OP_LT: return("<");
case OP_LE: return("<=");
case OP_SHL: return("<<");
case OP_SHR: return(">>");
case OP_ADDOP: return("+=");
case OP_SUBOP: return("-=");
case OP_MULOP: return("*=");
case OP_DIVOP: return("/=");
case OP_MODOP: return("%=");
case OP_OROP: return("|=");
case OP_ANDOP: return("&=");
case OP_LSHOP: return("<<=");
case OP_RSHOP: return(">>=");
case OP_XOROP: return("^=");
default:
error("internal error in operator()");
}
}
relational(expr,op,opnum,opstr,opname)
struct expr *expr;
char *opname;
{
gencode(expr->left,T_NONE);
gencode(expr->right,T_NONE);
if( expr->left->type == T_NONE || expr->right->type == T_NONE )
comp_num(op,0,0);
else
if( expr->left->type & T_NUMBER && expr->right->type & T_NUMBER )
comp_num(opnum,0,0);
else
if( expr->left->type & T_STRING && expr->right->type & T_STRING )
comp_num(opstr,0,0);
else
error("operand of %s must have the same type", opname);
expr->type = T_NUMBER;
free(expr->left);
free(expr->right);
}
/* gencode -
* Traverse an expression tree and generate code.
*/
gencode(expr,type)
struct expr *expr;
{
int lc1,lc2, i;
struct expr *e, *tmp;
switch( expr->opcode ) {
case OP_END:
break;
case OP_NOT:
case OP_NEG:
case OP_BNOT:
gencode(expr->right,T_NUMBER);
if( expr->right->type != T_NUMBER )
error("operand of %s must be an integer",
operator(expr->opcode) );
comp_num(expr->opcode,0,0);
free(expr->right);
expr->type = T_NUMBER;
break;
case OP_MUL:
case OP_DIV:
case OP_MOD:
case OP_ADD:
case OP_SUB:
case OP_BOR:
case OP_XOR:
case OP_BAND:
case OP_SHL:
case OP_SHR:
gencode(expr->left,T_NUMBER);
gencode(expr->right,T_NUMBER);
if( expr->left->type != T_NUMBER ||
expr->right->type != T_NUMBER )
error("operands of %s must be integers",
operator(expr->opcode) );
comp_num(expr->opcode,0,0);
expr->type = T_NUMBER;
free(expr->left);
free(expr->right);
break;
case OP_EQ: relational(expr,OP_EQ,OP_NUMEQ,OP_STREQ,"=="); break;
case OP_NE: relational(expr,OP_NE,OP_NUMNE,OP_STRNE,"!="); break;
case OP_GT: relational(expr,OP_GT,OP_NUMGT,OP_STRGT,">"); break;
case OP_GE: relational(expr,OP_GE,OP_NUMGE,OP_STRGE,">="); break;
case OP_LT: relational(expr,OP_LT,OP_NUMLT,OP_STRLT,"<"); break;
case OP_LE: relational(expr,OP_LE,OP_NUMLE,OP_STRLE,"<="); break;
case OP_AND1:
gencode(expr->left,T_NONE);
lc1 = LC;
if( expr->left->type == T_NONE )
comp_num(OP_AND1,0,0);
else if( expr->left->type == T_NUMBER )
comp_num(OP_A1_NUM,0,0);
else if( expr->left->type == T_STRING )
comp_num(OP_A1_STR,0,0);
gencode(expr->right,T_NONE);
if( expr->right->type == T_NONE )
comp_num(OP_AND2,0,0);
else if( expr->right->type == T_NUMBER )
comp_num(OP_A2_NUM,0,0);
else if( expr->right->type == T_STRING )
comp_num(OP_A2_STR,0,0);
Program[ lc1 ].val = LC;
free(expr->left);
free(expr->right);
expr->type = T_NUMBER;
break;
case OP_AND2:
error("internal error in gencode()");
case OP_OR1:
gencode(expr->left,T_NONE);
lc1 = LC;
if( expr->left->type == T_NONE )
comp_num(OP_OR1,0,0);
else if( expr->left->type == T_NUMBER )
comp_num(OP_OR1_NUM,0,0);
else if( expr->left->type == T_STRING )
comp_num(OP_OR1_STR,0,0);
gencode(expr->right,T_NONE);
if( expr->right->type == T_NONE )
comp_num(OP_OR2,0,0);
else if( expr->right->type == T_NUMBER )
comp_num(OP_OR2_NUM,0,0);
else if( expr->right->type == T_STRING )
comp_num(OP_OR2_STR,0,0);
Program[ lc1 ].val = LC;
free(expr->left);
free(expr->right);
expr->type = T_NUMBER;
break;
case OP_OR2:
error("internal error in gencode()");
case OP_ASSIGN:
gencode(expr->right,T_NONE);
gencode(expr->left,T_LVAL);
if( expr->right->type == T_NONE ) {
comp_num(OP_ASSIGN,0,0);
expr->type = T_NONE;
} else if( expr->right->type == T_NUMBER ) {
comp_num(OP_ASS_NUM,0,0);
expr->type = T_NUMBER;
} else if( expr->right->type == T_STRING ) {
comp_num(OP_ASS_STR,0,0);
expr->type = T_STRING;
}
free(expr->right);
free(expr->left);
break;
case OP_PLUSPLUS:
case OP_MINUSMINUS:
gencode(expr->right,T_LVAL);
free(expr->right);
comp_num(expr->opcode,0,0);
expr->type = T_NUMBER;
break;
case OP_ADDOP:
case OP_SUBOP:
case OP_MULOP:
case OP_DIVOP:
case OP_MODOP:
case OP_OROP:
case OP_ANDOP:
case OP_LSHOP:
case OP_RSHOP:
case OP_XOROP:
gencode(expr->right,T_NUMBER);
if( !(expr->right->type & T_NUMBER) )
error("rhs operand of %s must be an integer",
operator(expr->opcode));
gencode(expr->left,T_LVAL);
comp_num(expr->opcode,0,0);
expr->type = T_NUMBER;
free(expr->right);
free(expr->left);
break;
case OP_BUILTIN:
comp_builtin(expr,type);
break;
case OP_CALL:
e = expr->right;
i = (expr->right) ? expr->right->val + 1 : 0;
while(e) {
gencode(e->left,T_NONE);
free(e->left);
tmp = e;
e = e->right;
free(tmp);
}
comp_num(OP_CALL,expr->val,i);
if( type != T_NONE )
comp_num(OP_CHKTYPE,expr->type,type);
expr->type = type;
break;
case OP_RET:
error("internal error in gencode()");
case OP_GOTO:
error("internal error in gencode()");
case OP_NUMBER:
comp_num(OP_NUMBER,expr->val,0);
expr->type = T_NUMBER;
break;
case OP_STRING:
comp_str(OP_STRING,expr->str,0);
expr->type = T_STRING;
break;
case OP_VAR:
comp_obj(OP_VAR,expr->obj,type);
expr->type = type;
break;
case OP_AVAR:
gencode(expr->right,T_NONE);
comp_obj(OP_AVAR,expr->obj,type);
expr->type = type;
break;
case OP_PARAM:
comp_num(OP_PARAM,expr->val,type);
expr->type = type;
break;
case OP_APARAM:
gencode(expr->right,T_NONE);
comp_num(OP_APARAM,expr->val,type);
expr->type = type;
break;
case OP_CHKTYPE:
case OP_IFTRUE:
error("internal error in gencode()");
case OP_IFFALSE:
gencode(expr->left,T_NONE);
lc1 = LC;
if( expr->left->type == T_NONE )
comp_num(OP_IFFALSE,0,0);
else if( expr->left->type == T_NUMBER )
comp_num(OP_IFN_FALSE,0,0);
else if( expr->left->type == T_STRING )
comp_num(OP_IFS_FALSE,0,0);
else
error("first operand of ?: has an illegal type");
gencode(expr->right->left,type);
if( !(expr->right->left->type & type) )
error("middle operand of ?: has an illegal type");
lc2 = LC;
comp_num(OP_GOTO,0,0);
gencode(expr->right->right,type);
if( !(expr->right->right->type & type) )
error("last operand of ?: has an illegal type");
Program[ lc1 ].val = lc2+1;
Program[ lc2 ].val = LC;
if( expr->right->right->type == T_NONE ||
expr->right->left->type == T_NONE )
expr->type = T_NONE;
else
expr->type = type;
free(expr->left);
free(expr->right->left);
free(expr->right->right);
free(expr->right);
break;
case OP_INFIRST:
error("internal error in gencode()");
case OP_INNEXT:
error("internal error in gencode()");
case OP_ARG:
error("internal error in gencode()");
default:
error("internal error in gencode()");
}
}
char *initcompiler()
{
Program = (struct object *) malloc(PROG_INIT*sizeof(struct object));
Progsize = PROG_INIT;
if( Program == NULL ) return "out of memory";
LC = 0;
return NULL;
}
closecompiler()
{
if( LC1 >= 0 )
Program[ LC1 ].val = LC;
if( LC2 >= 0 )
Program[ LC2 ].val = LC;
comp_num(OP_END,0,0);
comp_str(OP_POP,rhfilename,lineno);
}
#ifdef DEBUG
char *dt(type) {
static char buf[ SMALLBUF ];
switch(type) {
case 0: return("no type");
case T_NONE: return("unknown/any type");
case T_NUMBER: return("number");
case T_STRING: return("string");
case T_ARRAY: return("array");
case T_LVAL: return("l-value");
case BREAK: return("BREAK");
case NEXT: return("NEXT");
case CONTINUE: return("CONTINUE");
default: sprintf(buf,"Unknown value: %d",type);
return(buf);
}
}
showinstr(pc,s,type)
char *s;
{
printf("[%-3d] %-15.15s, type=%-20.20s, ",pc,s,dt(Program[pc].type));
if( type )
printf("value=%s\n",Program[pc].str);
else
printf("value=%d\n",Program[pc].val);
}
show_it(p,i)
struct object *p;
{
switch( p->opcode ) {
case OP_BUILTIN: showinstr(i,"OP_BUILTIN",0); break;
case OP_CALL: showinstr(i,"OP_CALL",0); break;
case OP_RET: showinstr(i,"OP_RET",0); break;
case OP_GOTO: showinstr(i,"OP_GOTO",0); break;
case OP_END: showinstr(i,"OP_END",0); break;
case OP_IFTRUE: showinstr(i,"OP_IFTRUE",0); break;
case OP_IFN_TRUE: showinstr(i,"OP_IFN_TRUE",0); break;
case OP_IFS_TRUE: showinstr(i,"OP_IFS_TRUE",0); break;
case OP_IFFALSE: showinstr(i,"OP_IFFALSE",0); break;
case OP_IFN_FALSE: showinstr(i,"OP_IFN_FALSE",0); break;
case OP_IFS_FALSE: showinstr(i,"OP_IFS_FALSE",0); break;
case OP_POP: showinstr(i,"OP_POP",0); break;
case OP_NOT: showinstr(i,"OP_NOT",0); break;
case OP_NEG: showinstr(i,"OP_NEG",0); break;
case OP_BNOT: showinstr(i,"OP_BNOT",0); break;
case OP_MUL: showinstr(i,"OP_MUL",0); break;
case OP_DIV: showinstr(i,"OP_DIV",0); break;
case OP_MOD: showinstr(i,"OP_MOD",0); break;
case OP_ADD: showinstr(i,"OP_ADD",0); break;
case OP_SUB: showinstr(i,"OP_SUB",0); break;
case OP_BOR: showinstr(i,"OP_BOR",0); break;
case OP_XOR: showinstr(i,"OP_XOR",0); break;
case OP_BAND: showinstr(i,"OP_BAND",0); break;
case OP_SHL: showinstr(i,"OP_SHL",0); break;
case OP_SHR: showinstr(i,"OP_SHR",0); break;
case OP_AND1: showinstr(i,"OP_AND1",0); break;
case OP_AND2: showinstr(i,"OP_AND2",0); break;
case OP_A1_NUM: showinstr(i,"OP_A1_NUM",0); break;
case OP_A1_STR: showinstr(i,"OP_A1_STR",0); break;
case OP_A2_NUM: showinstr(i,"OP_A2_NUM",0); break;
case OP_A2_STR: showinstr(i,"OP_A2_STR",0); break;
case OP_OR1: showinstr(i,"OP_OR1",0); break;
case OP_OR2: showinstr(i,"OP_OR2",0); break;
case OP_OR1_NUM: showinstr(i,"OP_OR1_NUM",0); break;
case OP_OR1_STR: showinstr(i,"OP_OR1_STR",0); break;
case OP_OR2_NUM: showinstr(i,"OP_OR2_NUM",0); break;
case OP_OR2_STR: showinstr(i,"OP_OR2_STR",0); break;
case OP_EQ: showinstr(i,"OP_EQ",0); break;
case OP_NE: showinstr(i,"OP_NE",0); break;
case OP_GT: showinstr(i,"OP_GT",0); break;
case OP_GE: showinstr(i,"OP_GE",0); break;
case OP_LT: showinstr(i,"OP_LT",0); break;
case OP_LE: showinstr(i,"OP_LE",0); break;
case OP_NUMEQ: showinstr(i,"OP_NUMEQ",0); break;
case OP_NUMNE: showinstr(i,"OP_NUMNE",0); break;
case OP_NUMGT: showinstr(i,"OP_NUMGT",0); break;
case OP_NUMGE: showinstr(i,"OP_NUMGE",0); break;
case OP_NUMLT: showinstr(i,"OP_NUMLT",0); break;
case OP_NUMLE: showinstr(i,"OP_NUMLE",0); break;
case OP_STREQ: showinstr(i,"OP_STREQ",0); break;
case OP_STRNE: showinstr(i,"OP_STRNE",0); break;
case OP_STRGT: showinstr(i,"OP_STRGT",0); break;
case OP_STRGE: showinstr(i,"OP_STRGE",0); break;
case OP_STRLT: showinstr(i,"OP_STRLT",0); break;
case OP_STRLE: showinstr(i,"OP_STRLE",0); break;
case OP_PLUSPLUS: showinstr(i,"OP_PLUSPLUS",0); break;
case OP_MINUSMINUS: showinstr(i,"OP_MINUSMINUS",0); break;
case OP_ASSIGN: showinstr(i,"OP_ASSIGN",0); break;
case OP_ASS_NUM: showinstr(i,"OP_ASS_NUM",0); break;
case OP_ASS_STR: showinstr(i,"OP_ASS_STR",0); break;
case OP_ADDOP: showinstr(i,"OP_ADDOP",0); break;
case OP_SUBOP: showinstr(i,"OP_SUBOP",0); break;
case OP_MULOP: showinstr(i,"OP_MULOP",0); break;
case OP_DIVOP: showinstr(i,"OP_DIVOP",0); break;
case OP_MODOP: showinstr(i,"OP_MODOP",0); break;
case OP_OROP: showinstr(i,"OP_OROP",0); break;
case OP_ANDOP: showinstr(i,"OP_ANDOP",0); break;
case OP_LSHOP: showinstr(i,"OP_LSHOP",0); break;
case OP_RSHOP: showinstr(i,"OP_RSHOP",0); break;
case OP_XOROP: showinstr(i,"OP_XOROP",0); break;
case OP_NUMBER: showinstr(i,"OP_NUMBER",0); break;
case OP_STRING: showinstr(i,"OP_STRING",1); break;
case OP_VAR: showinstr(i,"OP_VAR",0); break;
case OP_AVAR: showinstr(i,"OP_AVAR",0); break;
case OP_PARAM: showinstr(i,"OP_PARAM",0); break;
case OP_APARAM: showinstr(i,"OP_APARAM",0); break;
case OP_CHKTYPE: showinstr(i,"OP_CHKTYPE",0); break;
case OP_INFIRST: showinstr(i,"OP_INFIRST",0); break;
case OP_INNEXT: showinstr(i,"OP_INNEXT",0); break;
case OP_ARG: showinstr(i,"OP_ARG",0); break;
default:
error("internal error");
}
}
dumpprogram()
{
int i;
printf("-----------\n");
for(i=0; i<LC; i++) {
show_it(&Program[i],i);
}
printf("-----------\n");
printf("Entry point = %d\n", startLC );
}
#endif
