/*
* (c) 2000-2009 Carlos G�mez Rodr�guez, todos los derechos reservados / all rights reserved.
* Licencia en license/bsd.txt / License in license/bsd.txt
*/
package eu.irreality.age;
import java.util.*;
public class CodeRunner
{
/*This is an EVA code runner only!*/
private final int INIT = 0;
private final int DATA = 1;
private final int CODE = 2;
private final int NONE = -1;
private final int MAXSEGMENT = 1024;
//tama�o m�ximo (instrucciones/etiquetas memoria, o l�neas en general)
//que puede tener un segmento
//los registros del mico
private String[] r = new String[100];
private String exc = new String();
private String obj = new String();
private String[] a = new String[10];
private String[] v = new String[10];
private String ra;
private int program_counter;
private String[][] segmento = new String[3][];
int[] cont = {0,0,0}; //longitud de segmentos init, data y code
private World ourWorld;
//la pila para el ensamblador
private Stack asmStack;
//pasar� a true si se hace un "continue", es decir, el c�digo termina; pero la ejecuci�n
//del comando ha de continuar como si el comando EVA hubiese fallado (no ejecutado, seguir
//parseando)
boolean continue_flag = false;
public CodeRunner ( String theCode , World theWorld ) throws EVASyntaxException
{
ourWorld = theWorld;
StringTokenizer lineas = new StringTokenizer ( theCode, "\n" );
//nos curamos en salud dandole capacidad MAXSEGMENT al segmento
//ergo, no se admiten mas de MAXSEGMENT instrucciones, mem, etc.
segmento = new String [3] [MAXSEGMENT];
int cursegment = NONE;
//organizar codigo en segmentos
while ( lineas.hasMoreTokens() )
{
String lineaActual = lineas.nextToken();
StringTokenizer palabrasEnLinea = new StringTokenizer ( lineaActual , " " );
if ( palabrasEnLinea.hasMoreTokens() )
{
String primeraPalabra = palabrasEnLinea.nextToken().trim();
if ( primeraPalabra.equalsIgnoreCase(".INIT") )
{
cursegment = INIT; //cambiamos de segmento
}
else if ( primeraPalabra.equalsIgnoreCase(".DATA") )
{
cursegment = DATA;
}
else if ( primeraPalabra.equalsIgnoreCase(".CODE") )
{
cursegment = CODE;
}
else if ( cursegment == NONE )
{
throw ( new EVASyntaxException ( "Lines of code without a segment" ) );
//Debug.println("ERROR: No segment\n");
}
else
{
segmento[cursegment][cont[cursegment]] = lineaActual;
//a�adimos la linea al segmento en que estamos
cont[cursegment]++;
}
}
}
//Debug.println("Code loaded.");
//Debug.println("Init segment lines: " + cont[INIT] );
//Debug.println("Data segment lines: " + cont[DATA] );
//Debug.println("Code segment lines: " + cont[CODE] );
//ya tenemos segment[CODE][i] linea i del segmento codigo, lo mismo para los otros
}
//true si existe la rutina
public boolean runCode ( String theCode , String routine , String dataSegment ) throws EVASyntaxException , EVASemanticException
{
addToDataSegment ( dataSegment );
return runCode ( theCode , routine );
}
/*prec: s escrito en EVA (Ens. Virt. Aetheria)*/
public boolean runCode ( String theCode , String routine ) throws EVASyntaxException , EVASemanticException
{
//Debug.println("Going to run code.");
//Debug.println("Routine = " + routine );
//ejecutar el segmento init (estados iniciales)
int curlimit = cont[INIT]; //longitud de init
for ( int i = 0 ; i < curlimit ; i++ )
{
StringTokenizer initTokenizer = new StringTokenizer( segmento[INIT][i] , ":" );
if ( initTokenizer.countTokens() < 2 )
{
throw( new EVASyntaxException(
"Too few tokens with : at INIT segment, line " + i + " (" + segmento[INIT][i] + ")" ) );
}
else
{
String reg = initTokenizer.nextToken().trim();
String val = initTokenizer.nextToken().trim();
}
}
//Debug.println("Initialization done.");
program_counter = getLine ( routine , CODE );
//Debug.println("PC = " + program_counter );
if ( program_counter == -1 )
{
return false;
//no ejecutado
}
else
{
while ( runNextInstruction() ) ;
if ( !continue_flag )
return true; //codigo ejecutado
else
{
continue_flag = false;
return false; //esto es si encontramos un continue, devolvemos "false" como si
//no hubieramos ejecutado el c�digo para que el parser siga ejecutando el comando.
}
}
}
private boolean runNextInstruction() throws EVASyntaxException , EVASemanticException
{
String instruccion = segmento[CODE][program_counter];
StringTokenizer st = new StringTokenizer( instruccion, " \t," );
if ( st.hasMoreTokens() )
{
//no es una nop
String codop = st.nextToken().trim();
if ( codop.charAt( codop.length() - 1 ) == ':' ) //tiene una etiqueta
{
if ( st.hasMoreTokens() )
codop = st.nextToken().trim(); //pasamos al siguiente
else codop = "nop";
}
if ( codop.equalsIgnoreCase ( "end" ) )
{
return false;
}
else if ( codop.equalsIgnoreCase ( "continue" ) || codop.equalsIgnoreCase ( "resume" ) )
{
continue_flag = true;
return false;
}
else if ( codop.equalsIgnoreCase ( "nop" ) || codop.equalsIgnoreCase ( "noop" ) || codop.equalsIgnoreCase ( "skip" ) )
{
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "ld" ) || codop.equalsIgnoreCase ( "load" ) )
{
if ( st.countTokens() < 2 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String reg = st.nextToken().trim();
String label = st.nextToken().trim();
try
{
setReg ( reg , getMem ( label ) );
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "li" ) || codop.equalsIgnoreCase ( "loadi" ) )
{
if ( st.countTokens() < 2 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String reg = st.nextToken().trim();
String val = "";
//StringTokenizer st2 = new StringTokenizer( instruccion, " \t," , true ); //counting separators
//st2.nextToken(); //codop
//st2.nextToken(); //separator
//st2.nextToken(); //reg
//st2.nextToken(); //separator
while ( true ) //coger los tokens pero con un s�lo caracter para no alterar el string
{
try
{
val += st.nextToken("�");
val += "�";
}
catch ( NoSuchElementException e )
{
break;
}
}
//quitar la �ltima cedilla a�adida
val = val.substring(0,val.length()-1);
//quitar posibles delimitadores que hayan quedado al principio de val
while ( val.charAt(0) == ',' || val.charAt(0) == ' ' || val.charAt(0) == '\t' )
{
val = val.substring(1);
}
try
{
setReg ( reg , val );
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "sd" ) || codop.equalsIgnoreCase ( "store" ) || codop.equalsIgnoreCase ( "stor" ) )
{
if ( st.countTokens() < 2 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String reg = st.nextToken().trim();
String label = st.nextToken().trim();
try
{
setMem ( label , getReg ( reg ) );
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "mov" ) || codop.equalsIgnoreCase ( "mv" ) || codop.equalsIgnoreCase ( "move" ) )
{
if ( st.countTokens() < 2 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String rt = st.nextToken().trim();
String rs = st.nextToken().trim();
try
{
setReg ( rt , getReg ( rs ) );
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "add" ) || codop.equalsIgnoreCase ( "sub" ) || codop.equalsIgnoreCase ( "mult" ) || codop.equalsIgnoreCase ( "mul" ) || codop.equalsIgnoreCase ( "div" ) )
{
if ( st.countTokens() < 3 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String rd = st.nextToken().trim();
String rs = st.nextToken().trim();
String rt = st.nextToken().trim();
int operando1,operando2;
try
{
operando1 = Integer.valueOf( getReg(rs) ).intValue();
operando2 = Integer.valueOf( getReg(rt) ).intValue();
try
{
if ( codop.equalsIgnoreCase("add") )
setReg ( rd , String.valueOf(operando1+operando2) );
if ( codop.equalsIgnoreCase("sub") )
setReg ( rd , String.valueOf(operando1-operando2) );
if ( codop.equalsIgnoreCase("mul") || codop.equalsIgnoreCase("mult") )
setReg ( rd , String.valueOf(operando1*operando2) );
if ( codop.equalsIgnoreCase("div") )
{
setReg ( rd , String.valueOf(operando1/operando2) );
if ( operando2 == 0 )
{
setReg ( "$Exc" , "DivisionByZero" );
setReg ( rd , "0" );
}
}
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
}
catch ( NumberFormatException en )
{
setReg ( "$Exc" , "NotANumber" );
setReg ( rd , "0" );
}
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "and" ) || codop.equalsIgnoreCase ( "or" ) )
{
if ( st.countTokens() < 3 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String rd = st.nextToken().trim();
String rs = st.nextToken().trim();
String rt = st.nextToken().trim();
int operando1,operando2;
try
{
operando1 = Integer.valueOf( getReg(rs) ).intValue();
operando2 = Integer.valueOf( getReg(rt) ).intValue();
try
{
if ( codop.equalsIgnoreCase("and") )
setReg ( rd , String.valueOf(operando1&operando2) );
if ( codop.equalsIgnoreCase("or") )
setReg ( rd , String.valueOf(operando1|operando2) );
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
}
catch ( NumberFormatException en )
{
setReg ( "$Exc" , "NotANumber" );
setReg ( rd , "0" );
}
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "fadd" ) || codop.equalsIgnoreCase ( "fsub" ) || codop.equalsIgnoreCase ( "fmult" ) || codop.equalsIgnoreCase ( "fmul" ) || codop.equalsIgnoreCase ( "fdiv" ) )
{
if ( st.countTokens() < 3 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String rd = st.nextToken().trim();
String rs = st.nextToken().trim();
String rt = st.nextToken().trim();
double operando1,operando2;
try
{
operando1 = Double.valueOf( getReg(rs) ).doubleValue();
operando2 = Double.valueOf( getReg(rt) ).doubleValue();
try
{
if ( codop.equalsIgnoreCase("fadd") )
setReg ( rd , String.valueOf(operando1+operando2) );
if ( codop.equalsIgnoreCase("fsub") )
setReg ( rd , String.valueOf(operando1-operando2) );
if ( codop.equalsIgnoreCase("fmul") || codop.equalsIgnoreCase("fmult") )
setReg ( rd , String.valueOf(operando1*operando2) );
if ( codop.equalsIgnoreCase("fdiv") )
{
setReg ( rd , String.valueOf(operando1/operando2) );
if ( operando2 == 0.0 )
{
setReg ( "$Exc" , "DivisionByZero" );
setReg ( rd , "0" );
}
}
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
}
catch ( NumberFormatException en )
{
setReg ( "$Exc" , "NotANumber" );
setReg ( rd , "0" );
}
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "addi" ) || codop.equalsIgnoreCase ( "subi" ) || codop.equalsIgnoreCase ( "multi" ) || codop.equalsIgnoreCase ( "muli" ) || codop.equalsIgnoreCase ( "divi" ) )
{
if ( st.countTokens() < 3 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String rd = st.nextToken().trim();
String rs = st.nextToken().trim();
String imm = st.nextToken().trim();
int operando1,operando2;
try
{
operando1 = Integer.valueOf( getReg(rs) ).intValue();
operando2 = Integer.valueOf( imm ).intValue();
try
{
if ( codop.equalsIgnoreCase("addi") )
setReg ( rd , String.valueOf(operando1+operando2) );
if ( codop.equalsIgnoreCase("subi") )
setReg ( rd , String.valueOf(operando1-operando2) );
if ( codop.equalsIgnoreCase("muli") || codop.equalsIgnoreCase("multi") )
setReg ( rd , String.valueOf(operando1*operando2) );
if ( codop.equalsIgnoreCase("divi") )
{
setReg ( rd , String.valueOf(operando1/operando2) );
if ( operando2 == 0 )
{
setReg ( "$Exc" , "DivisionByZero" );
setReg ( rd , "0" );
}
}
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
}
catch ( NumberFormatException en )
{
setReg ( "$Exc" , "NotANumber" );
setReg ( rd , "0" );
}
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "faddi" ) || codop.equalsIgnoreCase ( "fsubi" ) || codop.equalsIgnoreCase ( "fmulti" ) || codop.equalsIgnoreCase ( "fmuli" ) || codop.equalsIgnoreCase ( "fdivi" ) )
{
if ( st.countTokens() < 3 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String rd = st.nextToken().trim();
String rs = st.nextToken().trim();
String imm = st.nextToken().trim();
double operando1,operando2;
try
{
operando1 = Double.valueOf( getReg(rs) ).doubleValue();
operando2 = Double.valueOf( imm ).doubleValue();
try
{
if ( codop.equalsIgnoreCase("faddi") )
setReg ( rd , String.valueOf(operando1+operando2) );
if ( codop.equalsIgnoreCase("fsubi") )
setReg ( rd , String.valueOf(operando1-operando2) );
if ( codop.equalsIgnoreCase("fmuli") || codop.equalsIgnoreCase("fmulti") )
setReg ( rd , String.valueOf(operando1*operando2) );
if ( codop.equalsIgnoreCase("fdivi") )
{
setReg ( rd , String.valueOf(operando1/operando2) );
if ( operando2 == 0.0 )
{
setReg ( "$Exc" , "DivisionByZero" );
setReg ( rd , "0" );
}
}
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
}
catch ( NumberFormatException en )
{
setReg ( "$Exc" , "NotANumber" );
setReg ( rd , "0" );
}
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "bne" ) || codop.equalsIgnoreCase ( "beq" ) || codop.equalsIgnoreCase ( "bge" ) || codop.equalsIgnoreCase ( "bgt" ) || codop.equalsIgnoreCase ( "ble" ) || codop.equalsIgnoreCase ( "blt" ) )
{
if ( st.countTokens() < 3 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String r1 = st.nextToken().trim();
String r2 = st.nextToken().trim();
String label = st.nextToken().trim();
int operando1,operando2;
boolean condition = false;
try
{
operando1 = Integer.valueOf( getReg(r1) ).intValue();
operando2 = Integer.valueOf( getReg(r2) ).intValue();
if ( codop.equalsIgnoreCase("bne") )
condition = ( operando1 != operando2 );
else if ( codop.equalsIgnoreCase("beq") )
condition = ( operando1 == operando2 );
else if ( codop.equalsIgnoreCase("bge") )
condition = ( operando1 >= operando2 );
else if ( codop.equalsIgnoreCase("bgt") )
condition = ( operando1 > operando2 );
else if ( codop.equalsIgnoreCase("ble") )
condition = ( operando1 <= operando2 );
else if ( codop.equalsIgnoreCase("blt") )
condition = ( operando1 < operando2 );
}
catch ( NumberFormatException en )
{
//no son numeros. hacer igualdad de strings.
if ( codop.equalsIgnoreCase("beq") )
condition = getReg(r1).equals(getReg(r2));
else if ( codop.equalsIgnoreCase("bne") )
condition = !getReg(r1).equals(getReg(r2));
//no comparamos strings de superioridad o inferioridad
else
{
setReg ( "$Exc" , "NotANumber" );
condition = false;
}
}
//hacer el salto
if ( condition )
{
int direccion_salto = getLine ( label, CODE );
if ( direccion_salto < 0 )
{
program_counter++;
throw ( new EVASyntaxException (
"Jump address not found, code line " + program_counter ) );
}
program_counter = direccion_salto;
}
else program_counter++;
}
}
else if ( codop.equalsIgnoreCase ( "j" ) || codop.equalsIgnoreCase ( "goto" ) )
{
if ( !st.hasMoreTokens() )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String label = st.nextToken();
int direccion_salto = getLine ( label, CODE );
if ( direccion_salto < 0 )
{
program_counter++;
throw ( new EVASyntaxException (
"Jump address not found, code line " + program_counter ) );
}
program_counter = direccion_salto;
}
}
else if ( codop.equalsIgnoreCase ( "jal" ) )
{
if ( !st.hasMoreTokens() )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String label = st.nextToken();
int direccion_salto = getLine ( label, CODE );
if ( direccion_salto < 0 )
{
program_counter++;
throw ( new EVASyntaxException (
"Jump address not found, code line " + program_counter ) );
}
setReg ( "$ra" , String.valueOf(program_counter) );
program_counter = direccion_salto;
}
}
else if ( codop.equalsIgnoreCase ( "return" ) )
{
int direccion_salto;
try
{
direccion_salto = Integer.valueOf(getReg ( "$ra" )).intValue();
}
catch ( NumberFormatException nf )
{
throw ( new EVASyntaxException( "Invalid call to return, code line " + program_counter ) );
}
program_counter = direccion_salto;
}
else if ( codop.equalsIgnoreCase ( "push" ) )
{
if ( st.countTokens() < 1 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String reg = st.nextToken().trim();
String content;
try
{
content = getReg ( reg );
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
asmStack.push(content);
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "pop" ) )
{
if ( st.countTokens() < 1 )
{
throw ( new EVASyntaxException ( "Invalid instruction format, code line "+program_counter ) );
}
else
{
String reg = st.nextToken().trim();
String content = (String)asmStack.pop();
try
{
setReg ( reg , content );
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
}
program_counter++;
}
else if ( codop.equalsIgnoreCase ( "exc" ) || codop.equalsIgnoreCase( "exception" ) || codop.equalsIgnoreCase( "throw" ) )
{
throw ( new EVASemanticException ( exc , program_counter ) );
}
else if ( codop.equalsIgnoreCase ( "fun" ) || codop.equalsIgnoreCase( "function" ) )
{
String instructionParameters = "";
while ( st.hasMoreTokens() )
instructionParameters = st.nextToken();
try
{
execFunction ( instructionParameters );
}
catch ( EVASyntaxException e )
{
throw ( new EVASyntaxException (
e.getMessage() + ", line " + program_counter ) );
}
program_counter++;
}
else
{
throw ( new EVASyntaxException ( "Unidentified instruction " + "[" + codop + "]" + ", code line " + program_counter ) );
}
}
//ejecutar la instruccion indicada por el PC.
//codificarl�rl.
//end? return false.
return true; //s�, hay m�s instrucciones.
}
private void setReg ( String reg , String val ) throws EVASyntaxException
{
String actual = reg;
//Debug.println("Setting reg: " + actual );
if ( reg.charAt(0) != '$' )
{
throw ( new EVASyntaxException (
"Register must start with dollar sign" ) );
}
else
{
//quitar el dolar
actual = actual.substring(1,actual.length());
}
//Debug.println("Setting reg: " + actual );
if ( actual.substring(0,2).equalsIgnoreCase("ra") )
{
ra = val;
}
else if ( actual.charAt(0) == 'r' )
{
//quitar la r
actual = actual.substring(1,actual.length());
//a ve si es numero
int regnum;
try
{
regnum = Integer.valueOf(actual).intValue();
r[regnum] = val;
}
catch ( NumberFormatException NumExc )
{
throw( new EVASyntaxException (
"Wrong register format." ) );
}
}
else if ( actual.charAt(0) == 'v' )
{
//quitar la v
actual = actual.substring(1,actual.length());
//a ve si es numero
int regnum;
try
{
regnum = Integer.valueOf(actual).intValue();
v[regnum] = val;
}
catch ( NumberFormatException NumExc )
{
throw( new EVASyntaxException("Wrong register format"));
}
}
else if ( actual.charAt(0) == 'a' )
{
//quitar la a
actual = actual.substring(1,actual.length());
//a ve si es numero
int regnum;
try
{
regnum = Integer.valueOf(actual).intValue();
a[regnum] = val;
}
catch ( NumberFormatException NumExc )
{
throw( new EVASyntaxException("Wrong register format"));
}
}
else if ( actual.substring(0,3).equalsIgnoreCase("exc") )
{
exc = val;
}
else if ( actual.substring(0,3).equalsIgnoreCase("obj") )
{
obj = val;
}
else
{
throw( new EVASyntaxException("Wrong register format"));
}
}
//devuelve el valor en el registro reg
private String getReg ( String reg ) throws EVASyntaxException
{
String actual = reg;
if ( reg.charAt(0) != '$' )
{
throw ( new EVASyntaxException (
"Register must start with dollar sign" ) );
}
else
{
//quitar el dolar
actual = actual.substring(1,actual.length());
}
if ( actual.substring(0,2).equalsIgnoreCase("ra") )
{
return ra;
}
else if ( actual.charAt(0) == 'r' )
{
//quitar la r
actual = actual.substring(1,actual.length());
//a ve si es numero
int regnum;
try
{
regnum = Integer.valueOf(actual).intValue();
return r[regnum];
}
catch ( NumberFormatException NumExc )
{
throw( new EVASyntaxException("Wrong register format"));
}
}
else if ( actual.charAt(0) == 'v' )
{
//quitar la v
actual = actual.substring(1,actual.length());
//a ve si es numero
int regnum;
try
{
regnum = Integer.valueOf(actual).intValue();
return v[regnum];
}
catch ( NumberFormatException NumExc )
{
throw( new EVASyntaxException("Wrong register format"));
}
}
else if ( actual.charAt(0) == 'a' )
{
//quitar la r
actual = actual.substring(1,actual.length());
//a ve si es numero
int regnum;
try
{
regnum = Integer.valueOf(actual).intValue();
return a[regnum];
}
catch ( NumberFormatException NumExc )
{
throw( new EVASyntaxException("Wrong register format"));
}
}
else if ( actual.substring(0,3).equalsIgnoreCase("exc") )
{
return exc;
}
else if ( actual.substring(0,3).equalsIgnoreCase("obj") )
{
return obj;
}
else
{
throw( new EVASyntaxException("Wrong register format"));
}
}
//busca etiqueta en code/data segment.
private int getLine ( String toSearch , int elsegmento )
{
for ( int i = 0 ; i < cont[elsegmento] ; i++ )
{
StringTokenizer st = new StringTokenizer ( segmento[elsegmento][i],":" );
if ( st.countTokens() > 1 )
{
String label = st.nextToken().trim();
if ( label.equalsIgnoreCase(toSearch) ) return i;
}
}
return -1;
}
private String getMem ( String toSearch ) throws EVASyntaxException
{
int l = getLine ( toSearch , DATA );
if ( l < 0 )
throw ( new EVASyntaxException("Line "+toSearch+" doesn't exist in data segment") );
else
{
StringTokenizer st = new StringTokenizer ( segmento[DATA][l],":" );
if ( st.countTokens() > 1 )
{
st.nextToken();
return ( st.nextToken().trim() );
}
else return "";
}
}
private void setMem ( String toSearch , String value ) throws EVASyntaxException
{
int l = getLine ( toSearch , DATA );
if ( l < 0 )
throw ( new EVASyntaxException("Line "+toSearch+" doesn't exist in data segment") );
else
{
StringTokenizer st = new StringTokenizer ( segmento[DATA][l],":" );
segmento[DATA][l] = st.nextToken() + ": " + value.trim();
}
}
//para el "add to data segment".
//admite direcciones de memoria inexistentes, las crea.
//si la direccion existe, sin embargo, la sobreescribe.
private void addMem ( String toSearch , String value )
{
int l = getLine ( toSearch , DATA );
if ( l >= 0 )
{
StringTokenizer st = new StringTokenizer ( segmento[DATA][l],":" );
segmento[DATA][l] = st.nextToken() + ": " + value.trim();
}
else
{
segmento[DATA][cont[DATA]] = toSearch.trim() + ": " + value.trim();
cont[DATA]++;
}
}
private void addToDataSegment ( String stringToAdd )
{
StringTokenizer st = new StringTokenizer(stringToAdd,"\n");
while ( st.hasMoreTokens() )
{
StringTokenizer linest = new StringTokenizer ( st.nextToken(),":" );
String label = linest.nextToken();
String content = "";
while ( linest.hasMoreTokens() )
{
content += linest.nextToken();
}
addMem ( label , content );
}
}
private void execFunction ( String functionToExec ) throws EVASyntaxException
{
//static function escribir
if ( functionToExec.equalsIgnoreCase("escribir") )
{
ourWorld.write ( getReg( "$a0" ) );
}
else if ( functionToExec.equalsIgnoreCase("newline") )
{
ourWorld.write ("\n");
}
else if ( functionToExec.equalsIgnoreCase("getstate") )
{
int objid;
try
{
objid = Integer.valueOf( getReg("$Obj") ).intValue();
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Entity ourObject = ourWorld.getObject ( objid );
if ( ourObject == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
setReg ( "$v0" , String.valueOf ( ourObject.getState() ) );
}
}
else if ( functionToExec.equalsIgnoreCase("setstate") )
{
int objid;
int newstate;
long newtuleft;
try
{
objid = Integer.valueOf( getReg("$Obj") ).intValue();
newstate = Integer.valueOf( getReg("$a0") ).intValue();
newtuleft = Long.valueOf( getReg("$a1") ).longValue();
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Entity ourObject = ourWorld.getObject ( objid );
if ( ourObject == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
ourObject.setNewState ( newstate , newtuleft );
}
}
else if ( functionToExec.equalsIgnoreCase("getrelationshipstate") )
{
int objid1,objid2;
try
{
objid1 = Integer.valueOf( getReg("$Obj") ).intValue();
objid2 = Integer.valueOf( getReg("$a0") ).intValue();
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Mobile ourObject1 = (Mobile) ourWorld.getObject ( objid1 );
Entity ourObject2 = ourWorld.getObject ( objid2 );
if ( ourObject1 == null || ourObject2 == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
setReg ( "$v0" , String.valueOf ( ourObject1.getRelationshipState( ourObject2 ) ) );
}
} //end eva function: getrelationshipsstate
else if ( functionToExec.equalsIgnoreCase("setrelationshipstate") )
{
int objid1;
int objid2;
int newstate;
//long newtuleft; <- luego habra que a�adir tusleft a las relaciones
try
{
objid1 = Integer.valueOf( getReg("$Obj") ).intValue();
objid2 = Integer.valueOf( getReg("$a0" ) ).intValue();
newstate = Integer.valueOf( getReg("$a1") ).intValue();
//newtuleft = Long.valueOf( getReg("$a2") ).longValue();
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
//Debug.println("Dos");
return;
}
Mobile ourObject1 = (Mobile) ourWorld.getObject ( objid1 );
//Debug.println(ourObject1.getID());
Entity ourObject2 = ourWorld.getObject ( objid2 );
if ( ourObject1 == null || ourObject2 == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
//Debug.println("Uno");
//Debug.println(ourObject1 == null);
return;
}
else
{
//Debug.println(ourObject1);
//Debug.println(ourObject2);
//Debug.println(newstate);
ourObject1.setRelationshipState ( ourObject2 , newstate );
long prueba = (long)ourObject1.getRelationshipState(ourObject2)*((long)Math.pow(2,32));
//Debug.println( ourObject2.getState() + "::" + ourObject1.getRelationshipState(ourObject2) + "::" + prueba + "::" + Long.MAX_VALUE );
}
} //end eva function: setrelationshipsstate
else if ( functionToExec.equalsIgnoreCase("waitkeypress") )
{
int objid1;
try
{
objid1 = Integer.valueOf( getReg("$Obj") ).intValue();
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Player ourObject1 = (Player) ourWorld.getObject ( objid1 );
if ( ourObject1 == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
ourObject1.waitKeyPress();
}
} //end eva function: waitkeypress
else if ( functionToExec.equalsIgnoreCase("force") )
{
int objid1;
String s;
try
{
objid1 = Integer.valueOf( getReg("$Obj") ).intValue();
s = getReg("$a0");
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Player ourObject1 = (Player) ourWorld.getObject ( objid1 );
if ( ourObject1 == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
ourObject1.forceCommand(s);
}
} //end eva function: force
else if ( functionToExec.equalsIgnoreCase("clearscreen") )
{
int objid1;
try
{
objid1 = Integer.valueOf( getReg("$Obj") ).intValue();
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Player ourObject1 = (Player) ourWorld.getObject ( objid1 );
if ( ourObject1 == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
ourObject1.clearScreen();
}
} //end eva function: clearscreen
else if ( functionToExec.equalsIgnoreCase("makerandomvalidmove") )
{
int objid1;
try
{
objid1 = Integer.valueOf( getReg("$Obj") ).intValue();;
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Mobile ourObject1 = (Mobile) ourWorld.getObject ( objid1 );
if ( ourObject1 == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
ourObject1.makeRandomValidMove();
}
} //end eva function: makerandomvalidmove
else if ( functionToExec.equalsIgnoreCase("issubstringof") )
{
String s1,s2;
s1 = getReg("$a0");
s2 = getReg("$a1");
setReg("$v0", String.valueOf ( StringMethods.isSubstringOf(s1,s2) ) );
return;
}
else if ( functionToExec.equalsIgnoreCase("referstoentity") )
{
int objid1;
try
{
objid1 = Integer.valueOf( getReg("$a0") ).intValue();;
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Entity ourObject1 = (Entity) ourWorld.getObject ( objid1 );
if ( ourObject1 == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
//object OK, now get string and sing/plur
String s = getReg("$Obj");
String plurString = getReg("$a1");
boolean plural = (plurString==null)?false:(plurString.equalsIgnoreCase("true"))?true:false;
setReg("$v0", String.valueOf ( ParserMethods.refersToEntity(s,ourObject1,plural) ) );
}
} //end eva function: referstoentity
else if ( functionToExec.equalsIgnoreCase("referstoentities") )
{
int objid1,objid2;
try
{
objid1 = Integer.valueOf( getReg("$a0") ).intValue();
objid2 = Integer.valueOf( getReg("$a1") ).intValue();
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Entity ourObject1 = (Entity) ourWorld.getObject ( objid1 );
Entity ourObject2 = (Entity) ourWorld.getObject ( objid2 );
if ( ourObject1 == null || ourObject2 == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
//object OK, now get string and sing/plur
String s = getReg("$Obj");
String plurString1 = getReg("$a2");
String plurString2 = getReg("$a3");
boolean plural1 = (plurString1==null)?false:(plurString1.equalsIgnoreCase("true"))?true:false;
boolean plural2 = (plurString2==null)?false:(plurString2.equalsIgnoreCase("true"))?true:false;
setReg("$v0", String.valueOf ( ParserMethods.refersToEntities(s,ourObject1,ourObject2,plural1,plural2) ) );
}
} //end eva function: referstoentities
else if ( functionToExec.equalsIgnoreCase("giveitem") )
{
int objid1,objid2;
try
{
objid1 = Integer.valueOf( getReg("$Obj") ).intValue();
objid2 = Integer.valueOf( getReg("$a0") ).intValue();
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Mobile ourMobile=null;
try
{
ourMobile = (Mobile) ourWorld.getObject ( objid1 );
}
catch ( ClassCastException cce )
{
//ser� una habitaci�n
Room ourRoom = (Room) ourWorld.getObject ( objid1 );
Item ourItem = (Item) ourWorld.getObject ( objid2 );
if ( ourRoom == null || ourItem == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
try
{
ourRoom.addItem(ourItem);
}
catch ( WeightLimitExceededException wlee )
{
setReg ( "$Exc" , "WeightLimitExceeded" );
}
catch ( VolumeLimitExceededException vlee )
{
setReg ( "$Exc" , "VolumeLimitExceeded" );
}
}
}
Item ourItem = (Item) ourWorld.getObject ( objid2 );
if ( ourMobile == null || ourItem == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
try
{
ourMobile.addItem(ourItem);
}
catch ( WeightLimitExceededException wlee )
{
setReg ( "$Exc" , "WeightLimitExceeded" );
}
catch ( VolumeLimitExceededException vlee )
{
setReg ( "$Exc" , "VolumeLimitExceeded" );
}
}
} //end eva function: giveitem
else if ( functionToExec.equalsIgnoreCase("removeitem") )
{
int objid1,objid2;
try
{
objid1 = Integer.valueOf( getReg("$Obj") ).intValue();
objid2 = Integer.valueOf( getReg("$a0") ).intValue();
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Mobile ourMobile=null;
Item ourItem = (Item) ourWorld.getObject ( objid2 );
try
{
ourMobile = (Mobile) ourWorld.getObject ( objid1 );
}
catch ( ClassCastException cce )
{
//ser� una habitaci�n
Room ourRoom = (Room) ourWorld.getObject ( objid1 );
if ( ourRoom == null || ourItem == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
setReg("$v0", String.valueOf( ourRoom.removeItem(ourItem) ) );
}
}
if ( ourMobile == null || ourItem == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
setReg("$v0", String.valueOf( ourMobile.removeItem(ourItem) ) );
}
} //end eva function: removeitem
else if ( functionToExec.equalsIgnoreCase("hasitem") )
{
int objid1,objid2;
try
{
objid1 = Integer.valueOf( getReg("$Obj") ).intValue();
objid2 = Integer.valueOf( getReg("$a0") ).intValue();
}
catch ( NumberFormatException nfe )
{
setReg ( "$Exc" , "NotANumber" );
return;
}
Mobile ourMobile=null;
Item ourItem = (Item) ourWorld.getObject ( objid2 );
try
{
ourMobile = (Mobile) ourWorld.getObject ( objid1 );
}
catch ( ClassCastException cce )
{
Room ourRoom = (Room) ourWorld.getObject ( objid1 );
if ( ourRoom == null || ourItem == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
setReg("$v0", String.valueOf( ourRoom.hasItem(ourItem) ) );
}
}
if ( ourMobile == null || ourItem == null )
{
setReg ( "$Exc" , "NotAnIDNumber" );
return;
}
else
{
setReg("$v0", String.valueOf( ourMobile.hasItem(ourItem) ) );
}
} //end eva function: hasitem
else
{
throw ( new EVASyntaxException ( "Unrecognized or unsupported function: " + functionToExec ) );
}
}
}