Quantcast
Channel: Tech Support Guy
Viewing all articles
Browse latest Browse all 29110

Debugging Portable Numbers Format Interpreter 2

$
0
0
I'm now debugging the interpreter again. I have added events and am implementing a special event, called a breakpoint exception. This is triggerred after every instruction, except when we are in a breakpoint already. But my code is going on after it should stop.

My desLib is included as an attatchment. It goes in your include directory.

main.cpp:
Code:

#include "../pnf.hpp"


int main(int argc, char ** argv)
{
 if (argc < 2)
 {
  error(ERROR, (char *)"Wrong Arguments.");
  return -1;
 }

  if (argc >= 2)
  {
  PNF program(argc, argv);
   
   
  program.load();
  program.loads2();
  program.check();
  int ret = program.execute();


  return ret;
  }
  else
  error(ERROR, (char *)"Program Not Found.");
}

pnf.hpp:
Code:

#include <deslib/deslib.hpp>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <cctype>

/*
 IVERSION  - Switches versions. It's not possible to switch versions yet, because it's the first version.
              VERSION TVOID 0V

 IVOID      - Does nothing.
              VOID TVOID 0V

 ICRASH    - Intentional crash of program.
              CRASH TSTRING [string]

 IQUIT      - Quits the program. Returns return value.
              QUIT TVOID [return value]

 IHALT      - Halts the system by entering a forever loop.
              HALT TVOID 0V

 IPRINT    - Prints the specified value or the contents of the accumulator.
              PRINT TVOID 0V
              PRINT TBOOLEAN [data]
              PRINT TNUMBER [data]
              PRINT TCHARACTER [data]
              PRINT TSTRING [data]

 IPRINTLN  - Prints the specified value or the contents of the accumulator,
              then a newline.
              PRINTLN TVOID 0V
              PRINTLN TBOOLEAN [data]
              PRINTLN TNUMBER [data]
              PRINTLN TCHARACTER [data]
              PRINTLN TSTRING [data]

 IREAD      - Reads in a value to the accumulator.
              READ [type] 0V

 ILOAD      - Loads a value from memory into the accumulator.
              LOAD [type] [address]

 ISTORE    - Stores the contents of the accumulator at the specified memory
              location.
              STORE TVOID [address]

 ILOADC    - Loads a value from memory into the %calc register.
              LOADC [type] [address]

 ISTOREC    - Stores the contents of the %calc register into the specified
              memory location.
              STOREC TVOID [address]

 IESTORE    - Stores the contents of %accumulator into [%varcount].
              ESTORE TVOID 0V

 IESTOREC    - Stores the contents of %calc into [%varcount].
              ESTOREC TVOID 0V

 IVLOAD      - Gets a variable from variable location %operand, and stores it in
              %accumulator.
              VLOAD [type] [Variable Address]

 IVSTORE    - Stores a new variable from %accumulator to the next location.
              VSTORE TVOID 0V

 IVLOADC    - Gets a variable from variable location %operand, and stores it in
              %calc.
              VLOADC [type] [Variable Address]

 IVSTOREC    - Stores a new variable from %calc to the next location.
              VSTOREC TVOID 0V

 IMODT      - Modifies the type of %accumulator.
              MODT [type] 0V

 IMODCT      - Modifies the type of %calc.
              MODCT [type] 0V

 IADD      - Adds %calc or other value to %accumulator.
              ADD TVOID 0V
              ADD TNUMBER [data]
              ADD TCHARACTER [data]
              ADD TSTRING [data]

 ISUB      - Subtracts %calc from %accumulator.
              SUB VOID 0
              SUB TNUMBER [data]

 IMUL      - Multiplies %accumulator and %calc.
              MUL VOID 0
              MUL TNUMBER [data]

 IDIV      - Divides %calc by %accumulator.
              DIV VOID 0
              DIV TNUMBER [data]

 IMOD      - Takes a modulus of %accumulator and %calc.
              MOD VOID 0
              MOD TNUMBER [data]

 IPOW      - Raises %accumulator to the power of %calc.
              POW VOID 0
              POW TNUMBER [data]

 ISQRT      - Takes the square root of %accumulator.
              SQRT VOID 0
              SQRT TNUMBER [data]

 IINC      - Increments %accumulator.
              INC TVOID 0V

 IDEC      - Decrements %accumulator.
              DEC TVOID 0V

 IEQU      - Tests if %accumulator == %calc.
              EQU TVOID 0V
              EQU TBOOLEAN [data]
              EQU TNUMBER [data]
              EQU TCHARACTER [data]

 INEQU      - Tests if %accumulator != %calc.
              NEQU TVOID 0V
              NEQU TBOOLEAN [data]
              NEQU TNUMBER [data]
              NEQU TCHARACTER [data]

 IGTR      - Tests if %accumulator > %calc.
              GTR TVOID 0V
              GTR TNUMBER [data]
              GTR TCHARACTER [data]

 ILSS      - Tests if %accumulator < %calc.
              LSS TVOID 0V
              LSS TNUMBER [data]
              LSS TCHARACTER [data]

 IGEQU      - Tests if %accumulator >= %calc.
              GEQU TVOID 0V
              GEQU TNUMBER [data]
              GEQU TCHARACTER [data]

 ILEQU      - Tests if %accumulator <= %calc.
              LEQU TVOID 0V
              LEQU TNUMBER [data]
              LEQU TCHARACTER [data]

 IAND        - %accumulator && %calc
              AND TVOID 0V

 IOR        - %accumulator || %calc
              OR TVOID 0V

 INOT        - !(%accumulator)
              NOT TVOID 0V

 IGOTO      - Go to the memory address specified and continue running the
              program from there.
              GOTO TVOID [memory address]

 ICGOTO      - Go to the memory address specified and continue running the
              program from there if %accumulator equals true.
              CGOTO TVOID [memory address]

 IZGOTO    - Go to the memory address specified if %accumulator is 0.
              ZGOTO TVOID [memory address]

 IPGOTO    - Go to the memory address specified if %accumulator is > 0.
              PGOTO TVOID [memory address]

 INGOTO    - Go to the memory address specified if %accumulator is < 0.
              NGOTO TVOID [memory address]

 IGOTOL      - Go to the label specified and continue running the
              program from there.
              GOTO TVOID [label]

 ICGOTOL      - Go to the label specified and continue running the
                program from there if %accumulator equals true.
                CGOTO TVOID [label]

 IZGOTOL    - Go to the label specified if %accumulator is 0.
              ZGOTO TVOID [label]

 IPGOTOL    - Go to the memory address specified if %accumulator is > 0.
              PGOTO TVOID [label]

 INGOTOL    - Go to the label specified if %accumulator is < 0.
              NGOTO TVOID [label]

 IST        - Sets %accumulator to 0 if %calc is 0. (Used for loops.)
              ST TVOID 0V

 IPUSH      - Put the accumulator on the stack.
              PUSH TVOID 0V

 IPOP      - Loads a value into the accumulator from the stack.
              POP TVOID 0V

 ICALL      - Calls a subroutine that begins at [memory address].
              CALL TVOID [memory address]

 ICALLL      - Calls a subroutine that begins at [label].
              CALLL TVOID [label]

 IRET      - Returns from a subroutine.
              RET TVOID 0

 ILBL          - Declares a label.
                LBL TVOID 0V

 IVAR      - Declares a variable.
              VAR TVOID [variable]

 IELBL      - Declares an event label.
              ELBL TVOID 0V

 IEVLOAD    - Loads a value into %evalue.
              EVLOAD TVOID [value]

 IHEADD    - Adds a Hardware Event to the table.
              HEADD TVOID [event label number]

 IHEREM    - Removes a Hardware Event from the table.
              HEREM TVOID 0V

 IHEED      - Edits a Hardware Event in the table. %evalue must be the hevent
              number.
              HEED TVOID [new event label number number]

 IHEGET    - Gets a Hardware Event event label number from the table. Puts it
              in %evalue.
              HEGET TVOID [hardware event number]

 ISHEADD    - Adds a System Hardware Event to the table.
              SHEADD TVOID [event label number]

 ISHEREM    - Removes a System Hardware Event from the table.
              SHEREM TVOID 0V

 ISHEED      - Edits a System Hardware Event in the table. %evalue must be the
              shevent number.
              SHEED TVOID [new event label number number]

 ISHEGET    - Gets a System Hardware Event event label number from the table.
              Puts it in %evalue.
              SHEGET TVOID [hardware event number]

 IEADD    -  Adds an Event to the table.
              EADD TVOID [event label number]

 IEREM      - Removes an Event from the table.
              EREM TVOID 0V

 IEED      - Edits an Event in the table. %evalue must be the event number.
              EED TVOID [new event label number number]

 IEGET      - Gets an Event event label number from the table. Puts it in \
              %evalue.
              EGET TVOID [hardware event number]

 IEXADD    - Adds an Exception to the table.
              EXADD TVOID [event label number]

 IEXREM    - Removes an Exception from the table.
              EXREM TVOID 0V

 IEXED      - Edits an Exception in the table. %evalue must be the exception
              number.
              EXED TVOID [new event label number number]

 IEXGET    - Gets an Exception event label number from the table. Puts it
              in %evalue.
              EXGET TVOID [hardware event number]

 IIADD      - Adds an Interrupt to the table.
              IADD TVOID [event label number]

 IIREM      - Removes an Interrupt from the table.
              IREM TVOID 0V

 IIED      - Edits an Interrupt in the table. %evalue must be the interrupt
              number.
              IED TVOID [new event label number number]

 IIGET      - Gets an Interrupt event label number from the table. Puts it
              in %evalue.
              IGET TVOID [hardware event number]
             
 IHEVENT    - Executes a Hardware Event subroutine.
              HEVENT TVOID [hardware event number]

 ISHEVENT  - Executes a System Hardware Event Subroutine.
              SHEVENT TVOID [system hardware event number]

 IEVENT    - Executes an Event subroutine.
              EVENT TVOID [event number]

 IEXCEPTION - Executes an Exception subroutine.
              EXCEPTION TVOID [exception number]

 IINT      - Executes an Interrupt (User Defined Event) subroutine.
              INT TVOID [interrupt number]
*/
enum PNF_Instruction_Enum
{
 IVERSION = 0,
 IVOID,
 ICRASH,
 IQUIT,
 IHALT,
 IPRINT,
 IPRINTLN,
 IREAD,
 ILOAD,
 ISTORE,
 ILOADC,
 ISTOREC,
 IELOAD,
 IESTORE,
 IELOADC,
 IESTOREC,
 IVLOAD,
 IVSTORE,
 IVLOADC,
 IVSTOREC,
 IMODT,
 IMODCT,
 IADD,
 ISUB,
 IMUL,
 IDIV,
 IMOD,
 IPOW,
 ISQRT,
 IINC,
 IDEC,
 IEQU,
 INEQU,
 IGTR,
 ILSS,
 IGEQU,
 ILEQU,
 IAND,
 IOR,
 INOT,
 IGOTO,
 ICGOTO,
 IZGOTO,
 IPGOTO,
 INGOTO,
 IGOTOL,
 ICGOTOL,
 IZGOTOL,
 IPGOTOL,
 INGOTOL,
 IST,
 IPUSH,
 IPOP,
 ICALL,
 ICALLL,
 IRET,
 IVAR,
 ILBL,
 IEPRINT,
 IEPRINTLN,
 IEND,
 IELBL,
 IEVLOAD,
 IHEADD,
 IHEREM,
 IHEED,
 IHEGET,
 ISHEADD,
 ISHEREM,
 ISHEED,
 ISHEGET,
 IEADD,
 IEREM,
 IEED,
 IEGET,
 IEXADD,
 IEXREM,
 IEXED,
 IEXGET,
 IIADD,
 IIREM,
 IIED,
 IIGET,
 IHEVENT,
 ISHEVENT,
 IEVENT,
 IEXCEPTION,
 IINT
};
   
enum PNF_Type_Enum
{
 TVOID = 0,
 TBOOLEAN,
 TNUMBER,
 TCHARACTER,
 TSTRING
};


class PNF_Void
{
 public:
        void put();
        void get();
       
        double to_mem();
        void from_mem(double i);

        void print();
        void eprint();
        void read();
};

void PNF_Void::put()
{
 // Does nothing
}

void PNF_Void::get()
{
 // Does nothing
}

double PNF_Void::to_mem()
{
 return 0;
}

void PNF_Void::from_mem(double i)
{
 if (i != 0)
  error(ERROR, (char *)"Not Void.");
}

void PNF_Void::print()
{
 cout << 0;
}

void PNF_Void::eprint()
{
 cerr << 0;
}

void PNF_Void::read()
{
 // Does nothing
}


class PNF_Boolean
{
 protected:
          bool data;
 
 public:
        PNF_Boolean();
        PNF_Boolean(bool d);
        ~PNF_Boolean();
       
       
        void put(bool d);
        String get();
       
        double to_mem();
        void from_mem(double i);

        void print();
        void eprint();
        void read();
};

PNF_Boolean::PNF_Boolean()
{
 data = false;
}

PNF_Boolean::PNF_Boolean(bool d)
{
 data = d;
}

PNF_Boolean::~PNF_Boolean()
{
 
}
       
void PNF_Boolean::put(bool d)
{
 data = d;
}

String PNF_Boolean::get()
{
 if (data == true)
  return (char *)"true";
 else
  return (char *)"false";
}

double PNF_Boolean::to_mem()
{
 return data;
}

void PNF_Boolean::from_mem(double i)
{
 data = (bool)i;
}

void PNF_Boolean::print()
{
 cout << get();
}

void PNF_Boolean::eprint()
{
 cerr << get();
}

void PNF_Boolean::read()
{
 string data2;
 
 cin >> data2;

 if (data2 == "false")
  data = false;
 else if (data2 == "true")
  data = true;
 else
  data = false;
}


class PNF_Number
{
 protected:
          double data;
         
         
 public:
        PNF_Number();
        PNF_Number(double d);
        ~PNF_Number();
       
        void put(double d);
        double get();
       
       
        double to_mem();
        void from_mem(double d);

        void print();
        void eprint();
        void read();


        void add(double d);
        void sub(double d);
        void mul(double d);
        void div(double d);
        void mod(double d);

        void pow(double d);
        void sqrt(double d);
        void inc(double d);
        void dec(double d);
};

PNF_Number::PNF_Number()
{
 data = 0;
}

PNF_Number::PNF_Number(double d)
{
 data = d;
}

PNF_Number::~PNF_Number()
{
 
}
       
void PNF_Number::put(double d)
{
 data = d;
}

double PNF_Number::get()
{
 return data;
}

double PNF_Number::to_mem()
{
 return get();
}

void PNF_Number::from_mem(double d)
{
 put(d);
}

void PNF_Number::print()
{
 cout << data;
}

void PNF_Number::eprint()
{
 cerr << data;
}

void PNF_Number::read()
{
 cin >> data;
}

void PNF_Number::add(double d)
{
 data += d;
}

void PNF_Number::sub(double d)
{
 data -= d;
}

void PNF_Number::mul(double d)
{
 data *= d;
}

void PNF_Number::div(double d)
{
 data /= d;
}

void PNF_Number::mod(double d)
{
 long l = (long)data % (long)d;
 data = l;
}

void PNF_Number::pow(double d)
{
 data = ::pow(data, (int)d);
}

void PNF_Number::sqrt(double d)
{
 data = ::sqrt(data);
}

void PNF_Number::inc(double d)
{
 ++data;
}

void PNF_Number::dec(double d)
{
 --data;
}


class PNF_Character
{
 protected:
          char data;
         
         
 public:
        PNF_Character();
        PNF_Character(char d);
        ~PNF_Character();
       
        void put(char d);
        char get();
       
        double to_mem();
        void from_mem(double c);

        void print();
        void eprint();
        void read();

        void add(char d);
};

PNF_Character::PNF_Character()
{
 data = '\0';
}

PNF_Character::PNF_Character(char d)
{
 data = d;
}

PNF_Character::~PNF_Character()
{
 
}
       
void PNF_Character::put(char d)
{
 data = d;
}

char PNF_Character::get()
{
 return data;
}

double PNF_Character::to_mem()
{
 return (double)data;
}

void PNF_Character::from_mem(double c)
{
 data = (char)c;
}

void PNF_Character::print()
{
 cout << data;
}

void PNF_Character::eprint()
{
 cerr << data;
}

void PNF_Character::read()
{
 cin >> data;
}

void PNF_Character::add(char d)
{
 data += d;
}


class PNF_String
{
 protected:
          String data;
         
 public:
        PNF_String();
        PNF_String(String d);
        ~PNF_String();
       
        void put(String d);
        String get();
       
        double * to_mem();
        void from_mem(double * w);

        void print();
        void eprint();
        void read();

        void add(String d);
};

PNF_String::PNF_String()
{
 data = (char *)"";
}

PNF_String::PNF_String(String d)
{
 data = d;
}

PNF_String::~PNF_String()
{
 
}
       
void PNF_String::put(String d)
{
 data = d;
}

String PNF_String::get()
{
 return data;
}

double * PNF_String::to_mem()
{
 double * ret = new double[data.size()];
 
 for (unsigned long i = 0; i < data.size(); ++i)
 {
  if ((data.getString().data()[i]) == '\0')
  break;
  ret[i] = (long)data.getString().data()[i];
 }
 ret[data.size()] = 0;


 return ret;
}

void PNF_String::from_mem(double * w)
{
 unsigned long i;
 for (i = 0; w[i] != 0; ++i)
  data[i] = (char)w[i];
}

void PNF_String::print()
{
 cout << data;
}

void PNF_String::eprint()
{
 cerr << data;
}

void PNF_String::read()
{
 cin >> data;
}

void PNF_String::add(String d)
{
 data += d;
}


class PNF_Variable
{
 private:
        PNF_Void v;
        PNF_Boolean b;
        PNF_Number n;
        PNF_Character c;
        PNF_String s;
 
 
        long type;       
 
 
 public:
        long getType();
        void setType(long t);
       

        void put(PNF_Void v);
        void put(PNF_Boolean b);
        void put(PNF_Number n);
        void put(PNF_Character c);
        void put(PNF_String s);

        double * getm();
        void putm(double * d);

        void print();
        void println();
        void eprint();
        void eprintln();
        void read();

        PNF_Void to_void();
        PNF_Boolean to_boolean();
        PNF_Number to_number();
        PNF_Character to_character();
        PNF_String to_string();
};

long PNF_Variable::getType()
{
 return type;
}

void PNF_Variable::setType(long t)
{
 type = t;
}

void PNF_Variable::put(PNF_Void v)
{
 setType(TVOID);
 this->v = v;
}

void PNF_Variable::put(PNF_Boolean b)
{
 setType(TBOOLEAN);
 this->b = b;
}

void PNF_Variable::put(PNF_Number n)
{
 setType(TNUMBER);
 this->n = n;
}

void PNF_Variable::put(PNF_Character c)
{
 setType(TCHARACTER);
 this->c = c;
}

void PNF_Variable::put(PNF_String s)
{
 setType(TSTRING);
 this->s = s;
}
       
double * PNF_Variable::getm()
{
 double * ret = new double;

 switch (type)
 {
  case TVOID:
      *ret = v.to_mem();
      break;
     
  case TBOOLEAN:
      *ret = b.to_mem();
      break;
     
  case TNUMBER:
      *ret = n.to_mem();
      break;
     
  case TCHARACTER:
      *ret = c.to_mem();
      break;
     
  case TSTRING:
      ret = s.to_mem();
      break;
 };
 
 return ret;
}

void PNF_Variable::putm(double * d)
{
 switch (type)
 {
  case TVOID:
      v.from_mem(*d);
      break;
     
  case TBOOLEAN:
      b.from_mem(*d);
      break;
     
  case TNUMBER:
      n.from_mem(*d);
      break;
     
  case TCHARACTER:
      c.from_mem(*d);
      break;
     
  case TSTRING:
      s.from_mem(d);
      break;
 };
}

void PNF_Variable::print()
{
 switch (type)
 {
  case TVOID:
  v.print();
  break;

  case TBOOLEAN:
  b.print();
  break;

  case TNUMBER:
  n.print();
  break;

  case TCHARACTER:
  c.print();
  break;

  case TSTRING:
  s.print();
  break;

  default:
  error(ERROR, (char *)"Invalid Type.");
  break;
 }
}

void PNF_Variable::println()
{
 switch (type)
 {
  case TVOID:
  v.print();
  cout << endl;
  break;

  case TBOOLEAN:
  b.print();
  cout << endl;
  break;

  case TNUMBER:
  n.print();
  cout << endl;
  break;

  case TCHARACTER:
  c.print();
  cout << endl;
  break;

  case TSTRING:
  s.print();
  cout << endl;
  break;

  default:
  error(ERROR, (char *)"Invalid Type.");
  break;
 }
}

void PNF_Variable::eprint()
{
 switch (type)
 {
  case TVOID:
  v.eprint();
  break;

  case TBOOLEAN:
  b.eprint();
  break;

  case TNUMBER:
  n.eprint();
  break;

  case TCHARACTER:
  c.eprint();
  break;

  case TSTRING:
  s.eprint();
  break;

  default:
  error(ERROR, (char *)"Invalid Type.");
  break;
 }
}

void PNF_Variable::eprintln()
{
 switch (type)
 {
  case TVOID:
  v.eprint();
  cerr << endl;
  break;

  case TBOOLEAN:
  b.eprint();
  cerr << endl;
  break;

  case TNUMBER:
  n.eprint();
  cerr << endl;
  break;

  case TCHARACTER:
  c.eprint();
  cerr << endl;
  break;

  case TSTRING:
  s.eprint();
  cerr << endl;
  break;

  default:
  error(ERROR, (char *)"Invalid Type.");
  break;
 }
}

void PNF_Variable::read()
{
 switch (getType())
 {
  case TVOID:
  v.read();
  break;

  case TBOOLEAN:
  b.read();
  break;

  case TNUMBER:
  n.read();
  break;

  case TCHARACTER:
  c.read();
  break;

  case TSTRING:
  {
  s.read();
  }
  break;

  default:
  error(ERROR, (char *)"Invalid Type.");
  break;
 }
}

PNF_Void PNF_Variable::to_void()
{
 PNF_Void v;
 return v;
}

PNF_Boolean PNF_Variable::to_boolean()
{
 PNF_Boolean b;

 switch (getType())
 {
  case TVOID:
      b.put(false);
      break;

  case TBOOLEAN:
      b = this->b;
      break;

  case TNUMBER:
      b.put(n.get());
      break;

  case TCHARACTER:
      b.put(c.get());
      break;

  case TSTRING:
      b.put(s.get()[0]);
      break;
 }

 return b;
}

PNF_Number PNF_Variable::to_number()
{
 PNF_Number n;

 switch (getType())
 {
  case TVOID:
      n.put(0);
      break;

  case TBOOLEAN:
      if (b.get().getString() == "true")
          n.put(1);
      else
          n.put(0);
      break;

  case TNUMBER:
      n = this->n;
      break;

  case TCHARACTER:
      n.put(c.get());
      break;

  case TSTRING:
      n.put(s.get()[0]);
      break;
 }

 return n;
}

PNF_Character PNF_Variable::to_character()
{
 PNF_Character c;

 switch (getType())
 {
  case TVOID:
      c = '\0';
      break;

  case TBOOLEAN:
      if (b.get().getString() == "true")
        c = 't';
      else
        c = 'f';
      break;

  case TNUMBER:
      c = (char)n.get();
      break;

  case TCHARACTER:
      c = this->c;
      break;

  case TSTRING:
      c = s.get()[0];
      break;
 }


 return c;
}

PNF_String PNF_Variable::to_string()
{
 PNF_String s;

 switch (getType())
 {
  case TVOID:
      s.put((char *)"");
      break;

  case TBOOLEAN:
      s = b.get();
      break;

  case TNUMBER:
      s.put((char)n.get());
      break;

  case TCHARACTER:
      s.put(c.get());
      break;

  case TSTRING:
      s = this->s;
      break;
 }


 return s;
}

class Memory
{
 private:
        Array<double> mem;
       
       
 public:
        Memory();
        ~Memory();
       
       
        double get(unsigned long i);
        void put(unsigned long i, double d);
        long length();

        Array<double> getmem();
        void setmem(Array<double> a);

        void insert();
        void remove();
};

Memory::Memory()
{
 
}

Memory::~Memory()
{
 
}       
       
double Memory::get(unsigned long i)
{
 if (i >= length())
 {
  insert();
  mem.put(0, i);
 }
 return mem.get(i);
}

void Memory::put(unsigned long i, double d)
{
 if (i >= length())
 {
  insert();
  mem.put(d, i);
 }
 else
  mem.put(d, i);
}

long Memory::length()
{
 return mem.length();
}

Array<double> Memory::getmem()
{
 return this->mem;
}

void Memory::setmem(Array<double> a)
{
 this->mem = a;
}

void Memory::insert()
{
 mem.insert();
}

void Memory::remove()
{
 mem.remove();
}

class Stack
{
 private:
        stack<PNF_Variable> stk;
       
       
 public:
        Stack();
        ~Stack();
       
       
        PNF_Variable pop();
        void push(PNF_Variable & v);
        PNF_Variable top();

        long length();
};

Stack::Stack()
{
 
}

Stack::~Stack()
{

}
               
PNF_Variable Stack::pop()
{
 PNF_Variable ret = stk.top();
 stk.pop();


 return ret;
}

PNF_Variable Stack::top()
{
 return stk.top();
}

void Stack::push(PNF_Variable & v)
{
 stk.push(v);
}

long Stack::length()
{
 return stk.size();
}

class ETable
{
 private:
  Array<unsigned long> table;


 public:
  void add(unsigned long value);
  void remove();
  void edit(unsigned long index, unsigned long value);
  unsigned long get(unsigned long index);
  unsigned long length();
};

void ETable::add(unsigned long value)
{
 if (length() == 1)
  table.put(0, value);
 else
 {
  table.insert();
  table.put((length() - 1), value);
 }
}

void ETable::remove()
{
 table.remove();
}

void ETable::edit(unsigned long index, unsigned long value)
{
 if (index < length())
  table.put(index, value);
 else
 {
  add(value);
 }
}

unsigned long ETable::get(unsigned long index)
{
 if (index >= length())
  add(0);
 return table.get(index);
}

unsigned long ETable::length()
{
 return table.length();
}

struct Registers
{
 unsigned long icount;

 unsigned long instruction;
 unsigned long type;
 unsigned long operand;

 
 String iname;
 Array<String> args;


 unsigned long ecount;
 Array<unsigned long> varcount;
 Array<unsigned long> labels;
 Array<unsigned long> elabels;


 unsigned long evalue;
 ETable hevents;
 ETable shevents;
 ETable events;
 ETable exceptions;
 ETable interrupts;


 PNF_Variable accumulator;
 PNF_Variable calc;
};
 
       
class PNF
{
 private:     
        Memory mem;
        Registers reg;
        Stack stk;
        stack<unsigned long> substk;

        bool breakpoint;
       
       
 public:
        PNF(int argc, char ** argv);
        ~PNF();
       
       
        String getProgram();
        void setProgram(char * program);

        Memory & getmem();
        void setmem(Memory & mem);
       
       
        void crash(string str);


        void load();
        void loads2();
        void check();
        int execute();

        void breakpoint_exception();
};


PNF::PNF(int argc, char ** argv)
{
 double l = 0;
 double * pl = &l;
 
 reg.icount = 0;
 reg.instruction = 0;
 reg.type = 0;
 reg.operand = 0;

 reg.iname = argv[0];
 for (long i = 0; i < argc; ++i)
 {
  if (i + 1 == argc)
  break;

  if (reg.args.length() < (argc - 1))
  reg.args.insert();
  reg.args.put(argv[i + 1], i);
 }
 
 reg.accumulator.setType(TVOID);
 reg.accumulator.putm(pl);

 reg.calc.setType(TVOID);
 reg.calc.putm(pl);

 breakpoint = false;
}

PNF::~PNF()
{
 
}
               
String PNF::getProgram()
{
 return reg.iname;
}

void PNF::setProgram(char * program)
{
 reg.iname = program;
}       

Memory & PNF::getmem()
{
 return mem;
}

void PNF::setmem(Memory & mem)
{
 for (unsigned long i = 0; i < this->mem.length(); ++i)
  mem.getmem().put(this->mem.get(i), i);
}

void PNF::crash(string str)
{
 error(ERROR, str);
 cout << endl;

 cout << "Registers:\n";
 cout << "==========\n";
 cout << "%icount              = " << reg.icount << endl;
 cout << endl;
 cout << "%instruction        = " << reg.instruction << endl;
 cout << "%type                = " << reg.type << endl;
 cout << "%operand            = " << reg.operand << endl;
 cout << "%accumulator        = ";
 reg.accumulator.print();
 cout << endl;
 cout << "%calc                = ";
 reg.calc.print();
 cout << endl;
 cout << "%iname              = " << reg.iname;
 cout << "\n\n";


 for (unsigned long i = 0; i < mem.length(); ++i)
  cout << "memory[" << i << "]: " << mem.get(i) << endl;
 cout << "\n\n";

 for (unsigned long i = 0; i < stk.length(); ++i)
 {
  cout << "Stack[" << i << "]: ";
  stk.top().println();
 }

 for (unsigned long i = 0; i < reg.args.length(); ++i)
  cout << "args[" << i << "]: " << reg.args.get(i) << endl;
 cout << "\n\n";
 
 
 exit(-1);
}

void PNF::load()
{
 fin.open(reg.args.get(0).getString().c_str());
 if (!fin)
  crash("Program Not Found or File Not Readable.");
 
 String signature = (char *)"!@.PNF";
 String str;
 fin >> str;

 
 if (str.getString() == signature.getString())
 {
  double num = 0;
 
  unsigned long i;
  for (i = 0; !fin.eof(); ++i)
  {
  fin >> num;
  mem.put(i, num);
  }
  reg.ecount = i;
 }
 else
  crash("Wrong Signature.");
 fin.close();
}

void PNF::loads2()
{
 if (mem.get(0) != IVERSION)
  crash("Version Unknown.");
 if (mem.get(reg.ecount - 3) != IEND)
  crash("No END Instruction.");

 for (unsigned long j = 0, k = 0; j != reg.ecount; ++j)
 {
  if (mem.get(j) == IVAR && mem.get(j + 1) == TVOID)
  {
  reg.varcount.put(j + 2, k);
  reg.varcount.insert();
  ++k;
  }
 }

 for (unsigned long j = 0, k = 0; j != reg.ecount; ++j)
 {
  if (mem.get(j) == ILBL && mem.get(j + 1) == TVOID && mem.get(j + 2) == 0)
  {
  reg.labels.put(j + 3, k);
  reg.labels.insert();
  ++k;
  }
 }

 for (unsigned long j = 0, k = 0; j != reg.ecount; ++j)
 {
  if (mem.get(j) == IELBL && mem.get(j + 1) == TVOID && mem.get(j + 2) == 0)
  {
  reg.elabels.put(j + 3, k);
  reg.elabels.insert();
  ++k;
  }
 }

 reg.icount = 0;
}

void PNF::check()
{
 // Not implemented yet.
}

int PNF::execute()
{
 // Execute program
 for (unsigned long i = 0, j = 1, k = 2; ; i += 3, j += 3, k += 3)
 {
  // Load the registers with the proper memory 
  ++reg.icount;

  reg.instruction = (long)mem.get(i);
  reg.type = (long)mem.get(j);
  reg.operand = (long)mem.get(k);
 
 
  // Run the instruction
  switch (reg.instruction)
  {
  case IVERSION:
        switch (reg.type)
        {
        case TVOID:
              if (reg.operand != 0)
                crash("Invalid VOID Value.");
              else
                ; // Version Not Needed Yet.
              break;
             
        default:
              crash("Invalid Type.");
        };
        continue;
       
  case IVOID: 
        switch (reg.type)
        {
        case TVOID:
              if (reg.operand != 0)
                crash("Invalid VOID Value.");
              else
                ; // Does Nothing...     
              break;
             
        default:
              crash("Invalid Type.");
              break; 
        };
        break;
       
  case ICRASH:
        switch (reg.type)
        {
        case TSTRING: 
              {         
              unsigned long l;
              String str;
              for (l = k; mem.get(l) != 0; ++l)
              {
                char c = (char)mem.get(l);
                str = str + c;
              }
              i = l;
              crash(str.getString());
              }
              break;
             
        default:
                crash("Invalid Type.");
                break;
        }
        break;
       
  case IQUIT:
        switch (reg.type)
        {
        case TVOID:
              if (reg.operand != 0)
              crash("Invalid VOID Value.");
              else
              {
              cout << "a";
              exit(0);
              }
             
        default:
          crash("Invalid Type.");
        };
       
       
  case IHALT:
        switch (reg.type)
        {
        case TVOID:
              if (reg.operand != 0)
              crash("Invalid VOID Value.");
              else
              for (;;)
                ;
             
        default:
          crash("Invalid Type.");
          break;
        };
       
  case IPRINT:
  {
        switch (reg.type)
        {
        case TVOID:
        {
          if (reg.operand != 0)
          crash("Invalid VOID Value.");
          else
          {
          reg.accumulator.print();
          }
        }
        break;

        case TBOOLEAN:
          switch (reg.operand)
          {
          case 0:
            cout << "false";
            break;

          case 1:
            cout << "true";
            break;

          default:
            cout << "true";
            break;
          }
          break;

        case TNUMBER:
          cout << reg.operand;
          break;

        case TCHARACTER:
          cout << (char)reg.operand;
          break;

        case TSTRING:
        {
          unsigned long is = 0;
          for (is = k; mem.get(is) != 0; ++is)         
          cout << (char)mem.get(is);

          i = is + 1;
          j = i + 1;
          k = i + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        break;
             
        default:
          crash("Invalid Type.");
          break;
        };
  }
        break;

  case IPRINTLN:
  {
        switch (reg.type)
        {
        case TVOID:
              if (reg.operand != 0)
              crash("Invalid VOID Value.");
              else
              {
              reg.accumulator.println();
              }
              break;

        case TBOOLEAN:
          switch (reg.operand)
          {
          case 0:
            cout << "false\n";
            break;

          case 1:
            cout << "true\n";
            break;

          default:
            cout << "true\n";
            break;
          }
          break;

        case TNUMBER:
          cout << reg.operand << endl;
          break;

        case TCHARACTER:
          cout << (char)reg.operand << endl;
          break;

        case TSTRING:
        {
          unsigned long is = 0;
          for (is = k; mem.get(is) != 0; ++is)         
          cout << (char)mem.get(is);
          cout << endl;

          i = is + 1;
          j = i + 1;
          k = i + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        break;
             
        default:
          crash("Invalid Type.");
          break;
        };
  }
        break;

  case IREAD:
        reg.accumulator.setType(reg.type);

        if (reg.operand != 0)
        crash("Invalid Parameter.");
        else
        {
        reg.accumulator.read();
        }

        break;

  case ILOAD:
        {
        double m;
        double * pm;
       

        reg.accumulator.setType(reg.type);

        switch (reg.accumulator.getType())
        {
          case TBOOLEAN:
              m = mem.get(reg.operand);
              pm = &m;

              reg.accumulator.putm(pm);
              break;

          case TNUMBER:
              m = mem.get(reg.operand);
              pm = &m;

              reg.accumulator.putm(pm);
              break;

          case TCHARACTER:
              pm = &m;     
              *pm = mem.get(reg.operand);
              reg.accumulator.putm(pm);
              break;

          case TSTRING:
          {         
              String str = (char *)"";
              long n;
              long o;
              for (n = reg.operand; mem.get(n) != 0; ++n)
              {
                char ch = (char)mem.get(n);
                str += ch;
              }
              PNF_String str2(str.getString());
              reg.accumulator.put(str2);
          }
          break;
             
          default:
          crash("Invalid Type.");
          break;
        }
        break;
        }

  case ISTORE:
        {
        if (reg.type != 0)
          crash("Invalid Type Identifier.");

        double * pm;
        pm = reg.accumulator.getm();
       
        switch (reg.accumulator.getType())
        {
          case TVOID:
          mem.put(reg.operand, *pm);
          break;

          case TBOOLEAN:
          mem.put(reg.operand, *pm);
          break;

          case TNUMBER:
          mem.put(reg.operand, *pm);
          break;

          case TCHARACTER:
          mem.put(reg.operand, *pm);
          break;

          case TSTRING:
          for (long i = 0; pm[i] != 0; ++i)
            mem.put(reg.operand + i, pm[i]);
          break;


          default:
          crash("Invalid Type.");
        }
        }
        break;

  case ILOADC:
        {
        double m;
        double * pm;
       

        reg.calc.setType(reg.type);

        switch (reg.calc.getType())
        {
          case TBOOLEAN:
              m = mem.get(reg.operand);
              pm = &m;

              reg.calc.putm(pm);
              break;

          case TNUMBER:
              m = mem.get(reg.operand);
              pm = &m;

              reg.calc.putm(pm);
              break;

          case TCHARACTER:
              pm = &m;     
              *pm = mem.get(reg.operand);
              reg.calc.putm(pm);
              break;

          case TSTRING:
          {         
              String str = (char *)"";
              long n;
              long o;
              for (n = reg.operand; mem.get(n) != 0; ++n)
              {
                char ch = (char)mem.get(n);
                str += ch;
              }
              PNF_String str2(str.getString());
              reg.calc.put(str2);
          }
          break;
             
          default:
          crash("Invalid Type.");
          break;
        }
        break;
        }

  case ISTOREC:
        {
        if (reg.type != 0)
          crash("Invalid Type Identifier.");

        double * pm;
        pm = reg.calc.getm();
       
        switch (reg.calc.getType())
        {
          case TVOID:
          mem.put(reg.operand, *pm);
          break;

          case TBOOLEAN:
          mem.put(reg.operand, *pm);
          break;

          case TNUMBER:
          mem.put(reg.operand, *pm);
          break;

          case TCHARACTER:
          mem.put(reg.operand, *pm);
          break;

          case TSTRING:
          for (long i = 0; pm[i] != 0; ++i)
            mem.put(reg.operand + i, pm[i]);
          break;


          default:
          crash("Invalid Type.");
        }
        }
        break;

  case IELOAD:
        {
        double m;
        double * pm;
       

        reg.accumulator.setType(reg.type);

        switch (reg.accumulator.getType())
        {
          case TBOOLEAN:
              m = mem.get(reg.ecount);
              pm = &m;

              reg.accumulator.putm(pm);
              break;

          case TNUMBER:
              m = mem.get(reg.ecount);
              pm = &m;

              reg.accumulator.putm(pm);
              break;

          case TCHARACTER:
              pm = &m;     
              *pm = mem.get(reg.ecount);
              reg.accumulator.putm(pm);
              break;

          case TSTRING:
          {         
              String str = (char *)"";
              long n;
              long o;
              for (n = reg.ecount; mem.get(n) != 0; ++n)
              {
                char ch = (char)mem.get(n);
                str += ch;
              }
              PNF_String str2(str.getString());
              reg.accumulator.put(str2);
          }
          break;
             
          default:
          crash("Invalid Type.");
          break;
        }
        break;
        }

  case IESTORE:
        {
        if (reg.operand != 0)
          crash("Invalid Operand.");
        if (reg.type != 0)
          crash("Invalid Type Identifier.");

        double * pm;
        pm = reg.accumulator.getm();
       
        switch (reg.accumulator.getType())
        {
          case TVOID:
          mem.put(reg.ecount, *pm);
          ++reg.ecount;
          break;

          case TBOOLEAN:
          mem.put(reg.ecount, *pm);
          ++reg.ecount;
          break;

          case TNUMBER:
          mem.put(reg.ecount, *pm);
          ++reg.ecount;
          break;

          case TCHARACTER:
          mem.put(reg.ecount, *pm);
          ++reg.ecount;
          break;

          case TSTRING:
          unsigned long i;
          for (i = 0; pm[i] != 0; ++i)
            mem.put(reg.ecount + i, pm[i]);
          reg.ecount += i;
          break;


          default:
          crash("Invalid Type.");
        }
        }
        break;

  case IELOADC:
        {
        double m;
        double * pm;
       

        reg.calc.setType(reg.type);

        switch (reg.calc.getType())
        {
          case TBOOLEAN:
              m = mem.get(reg.ecount);
              pm = &m;

              reg.calc.putm(pm);
              break;

          case TNUMBER:
              m = mem.get(reg.ecount);
              pm = &m;

              reg.calc.putm(pm);
              break;

          case TCHARACTER:
              pm = &m;     
              *pm = mem.get(reg.ecount);
              reg.calc.putm(pm);
              break;

          case TSTRING:
          {         
              String str = (char *)"";
              long n;
              long o;
              for (n = reg.ecount; mem.get(n) != 0; ++n)
              {
                char ch = (char)mem.get(n);
                str += ch;
              }
              PNF_String str2(str.getString());
              reg.calc.put(str2);
          }
          break;
             
          default:
          crash("Invalid Type.");
          break;
        }
        break;
        }

case IESTOREC:
        {
        if (reg.operand != 0)
          crash("Invalid Operand.");
        if (reg.type != 0)
          crash("Invalid Type Identifier.");

        double * pm;
        pm = reg.calc.getm();
       
        switch (reg.calc.getType())
        {
          case TVOID:
          mem.put(reg.ecount, *pm);
          ++reg.ecount;
          break;

          case TBOOLEAN:
          mem.put(reg.ecount, *pm);
          ++reg.ecount;
          break;

          case TNUMBER:
          mem.put(reg.ecount, *pm);
          ++reg.ecount;
          break;

          case TCHARACTER:
          mem.put(reg.ecount, *pm);
          ++reg.ecount;
          break;

          case TSTRING:
          unsigned long i;
          for (i = 0; pm[i] != 0; ++i)
            mem.put(reg.ecount + i, pm[i]);
          reg.ecount += i;
          break;


          default:
          crash("Invalid Type.");
        }
        }
        break;

  case IVLOAD:
        {
        double m;
        double * pm;
       

        reg.accumulator.setType(reg.type);
        reg.operand = reg.varcount.get(reg.operand);

        switch (reg.accumulator.getType())
        {
          case TBOOLEAN:
              m = mem.get(reg.operand);
              pm = &m;

              reg.accumulator.putm(pm);
              break;

          case TNUMBER:
              m = mem.get(reg.operand);
              pm = &m;

              reg.accumulator.putm(pm);
              break;

          case TCHARACTER:
              pm = &m;     
              *pm = mem.get(reg.operand);
              reg.accumulator.putm(pm);
              break;

          case TSTRING:
          {         
              String str = (char *)"";
              long n;
              long o;
              for (n = reg.operand; mem.get(n) != 0; ++n)
              {
                char ch = (char)mem.get(n);
                str += ch;
              }
              PNF_String str2(str.getString());
              reg.accumulator.put(str2);
          }
          break;
             
          default:
          crash("Invalid Type.");
          break;
        }
        break;
        }

  case IVSTORE:
        {
        if (reg.operand != 0)
          crash("Invalid Operand.");
        if (reg.type != 0)
          crash("Invalid Type Identifier.");

        long j = reg.ecount;
        mem.put(j, IVAR);
        mem.put(j + 1, TVOID);
        double * pm;
        pm = reg.accumulator.getm();


        reg.varcount.insert();
        reg.varcount.put(j + 2, reg.varcount.length() - 1);
       
        switch (reg.accumulator.getType())
        {
          case TVOID:
          mem.put(j + 2, *pm);
          reg.ecount += 3;
          break;

          case TBOOLEAN:
          mem.put(j + 2, *pm);
          reg.ecount += 3;
          break;

          case TNUMBER:
          mem.put(j + 2, *pm);
          reg.ecount += 3;
          break;

          case TCHARACTER:
          mem.put(j + 2, *pm);
          reg.ecount += 3;
          break;

          case TSTRING:
          unsigned long i;
          for (i = 0; pm[i] != 0; ++i)
            mem.put((j + 2) + i, pm[i]);
          reg.ecount += 3;
          break;


          default:
          crash("Invalid Type.");
        }

        for (unsigned long j = 0, k = 0; j != reg.ecount; ++j)
        {
          if (mem.get(j) == IVAR && mem.get(j + 1) == TVOID)
          {
          reg.varcount.put(j + 2, k);
          reg.varcount.insert();
          ++k;
          }
        }
        }
        break;

  case IVLOADC:
        {
        double m;
        double * pm;
       

        reg.calc.setType(reg.type);
        reg.operand = reg.varcount.get(reg.operand);

        switch (reg.calc.getType())
        {
          case TBOOLEAN:
              m = mem.get(reg.operand);
              pm = &m;

              reg.calc.putm(pm);
              break;

          case TNUMBER:
              m = mem.get(reg.operand);
              pm = &m;

              reg.calc.putm(pm);
              break;

          case TCHARACTER:
              pm = &m;     
              *pm = mem.get(reg.operand);
              reg.calc.putm(pm);
              break;

          case TSTRING:
          {         
              String str = (char *)"";
              long n;
              long o;
              for (n = reg.operand; mem.get(n) != 0; ++n)
              {
                char ch = (char)mem.get(n);
                str += ch;
              }
              PNF_String str2(str.getString());
              reg.calc.put(str2);
          }
          break;
             
          default:
          crash("Invalid Type.");
          break;
        }
        break;
        }

  case IVSTOREC:
        {
        if (reg.operand != 0)
          crash("Invalid Operand.");
        if (reg.type != 0)
          crash("Invalid Type Identifier.");

        long j = reg.ecount;
        mem.put(j, IVAR);
        mem.put(j + 1, TVOID);
        double * pm;
        pm = reg.calc.getm();


        reg.varcount.insert();
        reg.varcount.put(j + 2, reg.varcount.length() - 1);
       
        switch (reg.calc.getType())
        {
          case TVOID:
          mem.put(j + 2, *pm);
          reg.ecount += 3;
          break;

          case TBOOLEAN:
          mem.put(j + 2, *pm);
          reg.ecount += 3;
          break;

          case TNUMBER:
          mem.put(j + 2, *pm);
          reg.ecount += 3;
          break;

          case TCHARACTER:
          mem.put(j + 2, *pm);
          reg.ecount += 3;
          break;

          case TSTRING:
          unsigned long i;
          for (i = 0; pm[i] != 0; ++i)
            mem.put((j + 2) + i, pm[i]);
          reg.ecount += 3;
          break;


          default:
          crash("Invalid Type.");
        }

        for (unsigned long j = 0, k = 0; j != reg.ecount; ++j)
        {
          if (mem.get(j) == IVAR && mem.get(j + 1) == TVOID)
          {
          reg.varcount.put(j + 2, k);
          reg.varcount.insert();
          ++k;
          }
        }
        }
        break;

  case IMODT:
        {
        if (reg.operand == 0)
          reg.accumulator.setType(reg.type);
        else
          crash("Invalid Operand.");
        }
        break;

  case IMODCT:
        {
        if (reg.operand == 0)
          reg.calc.setType(reg.type);
        else
          crash("Invalid Operand.");
        }
        break;

  case IADD:
        {
        if (reg.operand == 0 && reg.type == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          switch (reg.accumulator.getType())
          {
            case TNUMBER:
            {
            PNF_Number tn = reg.accumulator.to_number();
            tn.add(reg.calc.to_number().get());
            reg.accumulator.put(tn);
            break;
            }

            case TSTRING:
            {
            PNF_String ts = reg.accumulator.to_string();
            ts.add(reg.calc.to_string().get());
            reg.accumulator.put(ts);
            break;
            }

            default:
            crash("Invalid ADD Instruction.");
            break;
          }
          }
          else
          crash("Invalid ADD Instruction.");
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
          {
            reg.accumulator.to_number().add(reg.operand);
          }
          break;

          case TCHARACTER:
            reg.accumulator.to_character().add(reg.operand);
            break;

          case TSTRING:
          {
            unsigned long i2 = 0;
            for (i2 = k; mem.get(i2) != 0; ++i2)
            reg.accumulator.to_character().add((char)mem.get(i2));
            i = i2;
            j = i + 1;
            k = i + 2;           
          }
          break;

          default:
            crash("Invalid ADD Instruction.");
          }
        }
        }
        break;

  case ISUB:
        {
        if (reg.operand == 0 && reg.type == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          switch (reg.accumulator.getType())
          {
            case TNUMBER:
            {
            PNF_Number tn = reg.accumulator.to_number();
            tn.sub(reg.calc.to_number().get());
            reg.accumulator.put(tn);
            break;
            }

            default:
            crash("Invalid SUB Instruction.");
            break;
          }
          }
          else
          crash("Invalid SUB Instruction.");
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
            reg.accumulator.to_number().sub(reg.operand);
            break;

          default:
            crash("Invalid SUB Instruction.");
          }
        }
        break;
        }

  case IMUL:
        {
        if (reg.operand == 0 && reg.type == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          switch (reg.accumulator.getType())
          {
            case TNUMBER:
            {
            PNF_Number tn = reg.accumulator.to_number();
            tn.mul(reg.calc.to_number().get());
            reg.accumulator.put(tn);
            break;
            }

            default:
            crash("Invalid MUL Instruction.");
            break;
          }
          }
          else
          crash("Invalid MUL Instruction.");
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
            reg.accumulator.to_number().mul(reg.operand);
            break;

          default:
            crash("Invalid MUL Instruction.");
          }
        }
        break;
        }

  case IDIV:
        {
        if (reg.operand == 0 && reg.type == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          switch (reg.accumulator.getType())
          {
            case TNUMBER:
            {
            PNF_Number tn = reg.accumulator.to_number();
            tn.div(reg.calc.to_number().get());
            reg.accumulator.put(tn);
            break;
            }

            default:
            crash("Invalid DIV Instruction.");
            break;
          }
          }
          else
          crash("Invalid DIV Instruction.");
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
            reg.accumulator.to_number().div(reg.operand);
            break;

          default:
            crash("Invalid DIV Instruction.");
          }
        }
        break;
        }

        case IMOD:
        {
        if (reg.operand == 0 && reg.type == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          switch (reg.accumulator.getType())
          {
            case TNUMBER:
            {
            PNF_Number tn = reg.accumulator.to_number();
            tn.mod(reg.calc.to_number().get());
            reg.accumulator.put(tn);
            break;
            }

            default:
            crash("Invalid MOD Instruction.");
            break;
          }
          }
          else
          crash("Invalid MOD Instruction.");
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
            reg.accumulator.to_number().sub(reg.operand);
            break;

          default:
            crash("Invalid MOD Instruction.");
          }
        }
        break;
        }

  case IPOW:
        {
        if (reg.operand == 0 && reg.type == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          switch (reg.accumulator.getType())
          {
            case TNUMBER:
            {
            PNF_Number tn = reg.accumulator.to_number();
            tn.pow(reg.calc.to_number().get());
            reg.accumulator.put(tn);
            break;
            }

            default:
            crash("Invalid POW Instruction.");
            break;
          }
          }
          else
          crash("Invalid POW Instruction.");
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
            reg.accumulator.to_number().pow(reg.operand);
            break;

          default:
            crash("Invalid POW Instruction.");
          }
        }
        break;
        }

  case ISQRT:
        {
        if (reg.operand == 0 && reg.type == 0)
        {
          switch (reg.accumulator.getType())
          {
          case TNUMBER:
          {
            PNF_Number tn = reg.accumulator.to_number();
            tn.sqrt(reg.accumulator.to_number().get());
            reg.accumulator.put(tn);
            break;
          }

          default:
            crash("Invalid SQRT Instruction.");
            break;
          }
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
            reg.accumulator.to_number().sub(reg.operand);
            break;

          default:
            crash("Invalid SQRT Instruction.");
          }
        }
        }
        break;

  case IINC:
        {
        if (reg.operand == 0 && reg.type == 0)
        {
          switch (reg.accumulator.getType())
          {
          case TNUMBER:
          {
            PNF_Number tn = reg.accumulator.to_number();
            tn.inc(reg.accumulator.to_number().get());
            reg.accumulator.put(tn);
            break;
          }

          default:
            crash("Invalid INC Instruction.");
            break;
          }
        }
        else
          crash("Invalid INC Instruction.");
        }
        break;

  case IDEC:
        {
        if (reg.operand == 0 && reg.type == 0)
        {
          switch (reg.accumulator.getType())
          {
          case TNUMBER:
          {
            PNF_Number tn = reg.accumulator.to_number();
            tn.dec(reg.accumulator.to_number().get());
            reg.accumulator.put(tn);
            break;
          }

          default:
            crash("Invalid DEC Instruction.");
            break;
          }
        }
        else
          crash("Invalid DEC Instruction.");
        }
        break;

  case IEQU:
        {
        if (reg.type == TVOID && reg.operand == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          bool b = (reg.accumulator.to_number().get() == reg.calc.to_number().get());
          if (b == true)
          {
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          }
        }
        else
        {
          switch (reg.type)
          {
          case TBOOLEAN:
          {
            bool b = (reg.accumulator.to_boolean().get().getString() == "true" ? true : false);
            bool b2 = (reg.operand == 0 ? false : true);
            bool b3 = b && b2;
            PNF_Boolean b4;
            b4.put(b3);
            reg.accumulator.put(b4);
            }
            break;

          case TNUMBER:
          {
            bool b = (reg.accumulator.to_number().get() == reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          case TCHARACTER:
          {
            bool b = (reg.accumulator.to_character().get() == (char)reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          default:
            crash("Invalid Type.");
          }
        }
        }
        break;

  case INEQU:
        {
        if (reg.type == 0 && reg.operand == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          bool b = (reg.accumulator.to_number().get() != reg.calc.to_number().get());
          if (b == true)
          {
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          }
        }
        else
        {
          switch (reg.type)
          {
          case TBOOLEAN:
          {
            bool b = (reg.accumulator.to_boolean().get().getString() != "true" ? true : false);
            bool b2 = (reg.operand == 0 ? false : true);
            bool b3 = b && b2;
            PNF_Boolean b4;
            b4.put(b3);
            reg.accumulator.put(b4);
            }
            break;

          case TNUMBER:
          {
            bool b = (reg.accumulator.to_number().get() != reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          case TCHARACTER:
          {
            bool b = (reg.accumulator.to_character().get() != (char)reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          default:
            crash("Invalid Type.");
          }
        }
        }
        break;

  case IGTR:
        {
        if (reg.type == 0 && reg.operand == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          bool b = (reg.accumulator.to_number().get() > reg.calc.to_number().get());
          if (b == true)
          {
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          }
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
          {
            bool b = (reg.accumulator.to_number().get() > reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          case TCHARACTER:
          {
            bool b = (reg.accumulator.to_character().get() > (char)reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          default:
            crash("Invalid Type.");
          }
        }
        }
        break;

  case ILSS:
        {
        if (reg.type == 0 && reg.operand == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          bool b = (reg.accumulator.to_number().get() < reg.calc.to_number().get());
          if (b == true)
          {
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          }
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
          {
            bool b = (reg.accumulator.to_number().get() < reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          case TCHARACTER:
          {
            bool b = (reg.accumulator.to_character().get() < (char)reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          default:
            crash("Invalid Type.");
          }
        }
        }
        break;

  case IGEQU:
        {
        if (reg.type == 0 && reg.operand == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          bool b = (reg.accumulator.to_number().get() >= reg.calc.to_number().get());
          if (b == true)
          {
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          }
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
          {
            bool b = (reg.accumulator.to_number().get() >= reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          case TCHARACTER:
          {
            bool b = (reg.accumulator.to_character().get() >= (char)reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          default:
            crash("Invalid Type.");
          }
        }
        }
        break;

  case ILEQU:
        {
        if (reg.type == 0 && reg.operand == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          bool b = (reg.accumulator.to_number().get() <= reg.calc.to_number().get());
          if (b == true)
          {
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          }
        }
        else
        {
          switch (reg.type)
          {
          case TNUMBER:
          {
            bool b = (reg.accumulator.to_number().get() <= reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          case TCHARACTER:
          {
            bool b = (reg.accumulator.to_character().get() <= (char)reg.operand);
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          break;

          default:
            crash("Invalid Type.");
          }
        }
        }
        break;

  case IAND:
        {
        if (reg.type == 0 && reg.operand == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          bool b = (reg.accumulator.to_boolean().get().getString() == "true" && reg.calc.to_boolean().get().getString() == "true");
          if (b == true)
          {
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          }
        }
        }
        break;

        case IOR:
        {
        if (reg.type == 0 && reg.operand == 0)
        {
          if (reg.accumulator.getType() == reg.calc.getType())
          {
          bool b = (reg.accumulator.to_boolean().get().getString() == "true" || reg.calc.to_boolean().get().getString() == "true");
          if (b == true)
          {
            PNF_Boolean b2;
            b2.put(b);
            reg.accumulator.put(b2);
          }
          }
        }
        }
        break;

        case INOT:
        {
        if (reg.type == 0 && reg.operand == 0)
        {
          if (reg.accumulator.to_boolean().get().getString() == "true")
          reg.accumulator.to_boolean().put(false);
          else
          reg.accumulator.to_boolean().put(true);
        }
        }
        break;

  case IGOTO:
        if (reg.type == 0)
        {
        i = reg.operand;
        j = reg.operand + 1;
        k = reg.operand + 2;

        if (breakpoint == true)
        {
          i = i - 3;
          j = i + 1;
          k = i + 2;
        }
        }
        else
        crash("Invalid GOTO.");
        break;

  case ICGOTO:
        if (reg.type == 0)
        {
        if (reg.accumulator.to_boolean().get().getString() == "true")
        {
          i = reg.operand;
          j = reg.operand + 1;
          k = reg.operand + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        }
        else
        crash("Invalid CGOTO.");
        break;

  case IZGOTO:
        if (reg.accumulator.to_number().get() == 0)
        {
        if (reg.type == 0)
        {
          i = reg.operand;
          j = reg.operand + 1;
          k = reg.operand + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        else
          crash("Invalid ZGOTO.");
        }
        break;

  case IPGOTO:
        if (reg.accumulator.to_number().get() > 0)
        {
        if (reg.type == 0)
        {
          i = reg.operand;
          j = reg.operand + 1;
          k = reg.operand + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        else
          crash("Invalid PGOTO.");
        }
        break;

  case INGOTO:
        if (reg.accumulator.to_number().get() < 0)
        {
        if (reg.type == 0)
        {
          i = reg.operand;
          j = reg.operand + 1;
          k = reg.operand + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        else
          crash("Invalid NGOTO.");
        }
        break;

  case IGOTOL:
        if (reg.type == TVOID)
        {
        reg.operand = reg.labels.get(reg.operand);       

        i = reg.operand;
        j = reg.operand + 1;
        k = reg.operand + 2;

        if (breakpoint == true)
        {
          i = i - 3;
          j = i + 1;
          k = i + 2;
        }
        }
        else
        crash("Invalid GOTOL.");
        break;

  case ICGOTOL:
        if (reg.type == 0)
        {
        if (reg.accumulator.to_boolean().get().getString() == "true")
        {
          reg.operand = reg.labels.get(reg.operand);       

          i = reg.operand;
          j = reg.operand + 1;
          k = reg.operand + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        }
        else
        crash("Invalid CGOTOL.");
        break;

  case IZGOTOL:
        if (reg.accumulator.to_number().get() == 0)
        {
        if (reg.type == 0)
        {
          reg.operand = reg.labels.get(reg.operand);       

          i = reg.operand;
          j = reg.operand + 1;
          k = reg.operand + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        else
          crash("Invalid ZGOTOL.");
        }
        break;

  case IPGOTOL:
        if (reg.accumulator.to_number().get() > 0)
        {
        if (reg.type == 0)
        {
          reg.operand = reg.labels.get(reg.operand);       

          i = reg.operand;
          j = reg.operand + 1;
          k = reg.operand + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        else
          crash("Invalid PGOTOL.");
        }
        break;

  case INGOTOL:
        if (reg.accumulator.to_number().get() < 0)
        {
        if (reg.type == 0)
        {
          reg.operand = reg.labels.get(reg.operand);       

          i = reg.operand;
          j = reg.operand + 1;
          k = reg.operand + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        else
          crash("Invalid NGOTOL.");
        }
        break;

  case IST:
        {
        if (reg.type == 0 && reg.operand == 0)
        {
          reg.calc.to_number().dec(1);
          if (reg.calc.to_number().get() == 0)
          reg.accumulator.put(reg.calc.to_number());
        }
        }
        break;

  case IPUSH:
        if (reg.operand == 0)
        {
        switch (reg.type)
        {
          case TVOID:
                  {                             
                  stk.push(reg.accumulator);                 
                  }
                  break;

          default:
                  crash("Invalid PUSH.");
                  break;               
        }
        }
        else
            crash("Invalid PUSH.");
        break;

      case IPOP:
        {
        if (reg.operand == 0)
        {       
          switch (reg.type)
          {
          case TVOID: 
          {                                   
                  reg.accumulator = stk.top();
                  stk.pop();
                  break;
          }

          default:
                  crash("Invalid POP.");
                  break;
          }
        }
        else
            crash("Invalid POP.");
        }
        break;

      case ICALL:
        if (reg.type == 0)
        {
        // Push current instruction address.
        substk.push(i);

        // GOTO Address
          i = reg.operand;
          j = reg.operand + 1;
          k = reg.operand + 2;

        if (breakpoint == true)
        {
          i = i - 3;
          j = i + 1;
          k = i + 2;
        }
        }
        else
        crash("Invalid CALL.");
        break;

      case ICALLL:
        if (reg.type == 0)
        {
        // Push current instruction address.
        substk.push(i);

        // GOTO Address
          reg.operand = reg.labels.get(reg.operand);

          i = reg.operand;
          j = reg.operand + 1;
          k = reg.operand + 2;

        if (breakpoint == true)
        {
          i = i - 3;
          j = i + 1;
          k = i + 2;
        }
        }
        else
        crash("Invalid CALLL.");
        break;

      case IRET:
        if (reg.type == 0 && reg.operand == 0)
        {
        i = (substk.top());
        i += 3;
        substk.pop();

        // GOTO Address         
          j = i + 1;
          k = i + 2;

        // Breakpoint is done...
        breakpoint = false;

        i = i - 3;
        j = i + 1;
        k = i + 2;
        }
        else
        crash("Invalid RET.");
       
        cout << "b";
        continue;


  case IVAR:
        {
        // Work done on loads2().
        }
        break;

  case ILBL:
        {
        // Work done on loads2().
        }
        break;

  case IEPRINT:
  {
        switch (reg.type)
        {
        case TVOID:
        {
          if (reg.operand != 0)
          crash("Invalid VOID Value.");
          else
          {
          reg.accumulator.eprint();
          }
        }
        break;

        case TBOOLEAN:
          switch (reg.operand)
          {
          case 0:
            cerr << "false";
            break;

          case 1:
            cerr << "true";
            break;

          default:
            cerr << "true";
            break;
          }
          break;

        case TNUMBER:
          cerr << reg.operand;
          break;

        case TCHARACTER:
          cerr << (char)reg.operand;
          break;

        case TSTRING:
        {
          unsigned long is = 0;
          for (is = k; mem.get(is) != 0; ++is)
          cerr << (char)mem.get(is);

          i = is + 1;
          j = i + 1;
          k = i + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        break;
             
        default:
          crash("Invalid Type.");
          break;
        };
  }
        break;

  case IEPRINTLN:
  {
        switch (reg.type)
        {
        case TVOID:
              if (reg.operand != 0)
              crash("Invalid VOID Value.");
              else
              {
              reg.accumulator.eprintln();
              }
              break;

        case TBOOLEAN:
          switch (reg.operand)
          {
          case 0:
            cerr << "false\n";
            break;

          case 1:
            cerr << "true\n";
            break;

          default:
            cerr << "true\n";
            break;
          }
          break;

        case TNUMBER:
          cerr << reg.operand << endl;
          break;

        case TCHARACTER:
          cerr << (char)reg.operand << endl;
          break;

        case TSTRING:
        {
          unsigned long is = 0;
          for (is = k; mem.get(is) != 0; ++is)
          cerr << (char)mem.get(is);
          cerr << endl;

          i = is + 1;
          j = i + 1;
          k = i + 2;

          if (breakpoint == true)
          {
          i = i - 3;
          j = i + 1;
          k = i + 2;
          }
        }
        break;
             
        default:
          crash("Invalid Type.");
          break;
        };
  }
        break;
 
  case IEND:
  {
    // Do nothing, just a marker for the end.
  }
  break;

  case IELBL:
        {
        // Work done on loads2().
        }
        break;

  case IEVLOAD:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.evalue = (unsigned long)reg.operand;
  }
  break;

  case IHEADD:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.hevents.add(reg.operand);
  }
  break;

  case IHEREM:
  {
    if (reg.type != TVOID && reg.operand != 0)
    crash("Invalid Type or Void Value.");
    else
    reg.hevents.remove();
  }
  break;

  case IHEED:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.hevents.edit(reg.evalue, reg.operand);
  }
  break;

  case IHEGET:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.evalue = reg.hevents.get(reg.operand);
  }
  break;

  case ISHEADD:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.shevents.add(reg.operand);
  }
  break;

  case ISHEREM:
  {
    if (reg.type != TVOID && reg.operand != 0)
    crash("Invalid Type or Void Value.");
    else
    reg.shevents.remove();
  }
  break;

  case ISHEED:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.shevents.edit(reg.evalue, reg.operand);
  }
  break;

  case ISHEGET:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.evalue = reg.shevents.get(reg.operand);
  }
  break;

  case IEADD:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.events.add(reg.operand);
  }
  break;

  case IEREM:
  {
    if (reg.type != TVOID && reg.operand != 0)
    crash("Invalid Type or Void Value.");
    else
    reg.events.remove();
  }
  break;

  case IEED:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.events.edit(reg.evalue, reg.operand);
  }
  break;

  case IEGET:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.evalue = reg.events.get(reg.operand);
  }
  break;

  case IEXADD:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.exceptions.add(reg.operand);
  }
  break;

  case IEXREM:
  {
    if (reg.type != TVOID && reg.operand != 0)
    crash("Invalid Type or Void Value.");
    else
    reg.exceptions.remove();
  }
  break;

  case IEXED:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.exceptions.edit(reg.evalue, reg.operand);
  }
  break;

  case IEXGET:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.evalue = reg.exceptions.get(reg.operand);
  }
  break;

  case IIADD:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.interrupts.add(reg.operand);
  }
  break;

  case IIREM:
  {
    if (reg.type != TVOID && reg.operand != 0)
    crash("Invalid Type or Void Value.");
    else
    reg.interrupts.remove();
  }
  break;

  case IIED:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.interrupts.edit(reg.evalue, reg.operand);
  }
  break;

  case IIGET:
  {
    if (reg.type != TVOID)
    crash("Invalid Type.");
    else
    reg.evalue = reg.interrupts.get(reg.operand);
  }
  break;

  case IHEVENT:
  {
    if (reg.type == 0)
    {
    // Push current instruction address.
    substk.push(i);

    // GOTO Address
    reg.operand = reg.hevents.get(reg.operand);
    reg.operand = reg.elabels.get(reg.operand);

    i = reg.operand;
    j = reg.operand + 1;
    k = reg.operand + 2;

    if (breakpoint == true)
    {
      i = i - 3;
      j = i + 1;
      k = i + 2;
    }
    }
    else
    crash("Invalid HEVENT.");
  }
  break;

  case ISHEVENT:
  {
    if (reg.type == 0)
    {
    // Push current instruction address.
    substk.push(i);

    // GOTO Address
    reg.operand = reg.shevents.get(reg.operand);
    reg.operand = reg.elabels.get(reg.operand);

    i = reg.operand;
    j = reg.operand + 1;
    k = reg.operand + 2;

    if (breakpoint == true)
    {
      i = i - 3;
      j = i + 1;
      k = i + 2;
    }
    }
    else
    crash("Invalid SHEVENT.");
  }
  break;

  case IEVENT:
  {
    if (reg.type == 0)
    {
    // Push current instruction address.
    substk.push(i);

    // GOTO Address
    reg.operand = reg.events.get(reg.operand);
    reg.operand = reg.elabels.get(reg.operand);

    i = reg.operand;
    j = reg.operand + 1;
    k = reg.operand + 2;

    if (breakpoint == true)
    {
      i = i - 3;
      j = i + 1;
      k = i + 2;
    }
    }
    else
    crash("Invalid EVENT.");
  }
  break;

  case IEXCEPTION:
  {
    if (reg.type == 0)
    {
    // Push current instruction address.
    substk.push(i);

    // GOTO Address
    reg.operand = reg.exceptions.get(reg.operand);
    reg.operand = reg.elabels.get(reg.operand);

    i = reg.operand;
    j = reg.operand + 1;
    k = reg.operand + 2;

    if (breakpoint == true)
    {
      i = i - 3;
      j = i + 1;
      k = i + 2;
    }
    }
    else
    crash("Invalid EXCEPTION.");
  }
  break;

  case IINT:
  {
    if (reg.type == 0)
    {
    // Push current instruction address.
    substk.push(i);

    // GOTO Address
    reg.operand = reg.interrupts.get(reg.operand);
    reg.operand = reg.elabels.get(reg.operand);

    i = reg.operand;
    j = reg.operand + 1;
    k = reg.operand + 2;

    if (breakpoint == true)
    {
      i = i - 3;
      j = i + 1;
      k = i + 2;
    }
    }
    else
    crash("Invalid INT.");
  }
  break;
       
       
  default:
          crash("Invalid Instruction.");
          break;
  }
 
  // Execute breakpoint exception if not in breakpoint
  if (breakpoint == false)
  {
  // Tell the program we are now in a breakpoint...
  breakpoint = true;

  // Push current instruction address.
  cout << "i: " << i << "\n";
  substk.push(i);

  // GOTO Address
  reg.operand = reg.exceptions.get(0);
  reg.operand = reg.elabels.get(reg.operand);
  if (reg.operand == 0)
    breakpoint_exception();
  else
  {
    i = reg.operand;
    j = reg.operand + 1;
    k = reg.operand + 2;

    i = i - 3;
    j = i + 1;
    k = i + 2;
  }
  }
  else
  cout << "Not in breakpoint.\n";
 }
}

void PNF::breakpoint_exception()
{

}

As you can see, it's supposed to trigger a builtin function if there is no user-defined function. Here is exceptiontest.pnf:
Code:

!@.PNF


0 0 0
75 0 0
6 4 72 101 108 108 111 32 87 111 114 108 100 33 0
3 0 0
61 0 0
6 4 73 110 32 98 114 101 97 107 112 111 105 110 116 46 0
55 0 0
60 0 0

Here there is a user-defined function so we use this instead of the builtin function. The output when running this is:
Code:

i: 3
In breakpoint.
Not in breakpoint.
6bHello World!
i: 21
In breakpoint.
Not in breakpoint.
61bi: 24
In breakpoint.
Not in breakpoint.
6bIn breakpoint.
i: 44
In breakpoint.
Not in breakpoint.
60bi: 47
In breakpoint.
Not in breakpoint.
0bterminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

There is only supposed to be one breakpoint triggerred after the, "Hello World!". I have no idea whether this is going wrong on the RET instruction, or the breakpoint, or the PRINTLN instruction.

Attached Files
File Type: zip deslib.zip (31.1 KB)

Viewing all articles
Browse latest Browse all 29110

Trending Articles