case 'd': VM_Scheduler.dumpVirtualMachine(); return;
case 'e': if (VM.BuildForEventLogging) { VM.EventLoggingEnabled = !VM.EventLoggingEnabled; VM.sysWrite("event logging " + (VM.EventLoggingEnabled ? "enabled\n" : "disabled\n")); } else { VM.sysWrite("sorry, not built for event logging\n"); } return;
   eval(String[] tokens) throws Exception      {      char command = tokens        == null ? EOF  // end of file                   : tokens.length == 0    ? ' '  // empty line                   : tokens[0].charAt(0);         // first letter of first token      switch (command)         {         case ' ': // repeat previous command once         if (previousTokens != null)            eval(previousTokens);         return;                  case '*': // repeat previous command once per second, until SIGQUIT is received         if (previousTokens != null)            for (VM_Scheduler.debugRequested = false; VM_Scheduler.debugRequested == false; )               {               VM.sysWrite("\033[H\033[2J");               eval(previousTokens);               sleep(1000);               }         return;         }               previousTokens = tokens;            switch (command)         {         case 't': // display thread(s)         if (tokens.length == 1)            { // display all threads            for (int i = 0, col = 0; i < VM_Scheduler.threads.length; ++i)               {               VM_Thread thread = VM_Scheduler.threads[i];               if (thread == null) continue;               VM.sysWrite(rightJustify(thread.getIndex() + " ", 4) + leftJustify(thread.toString(), 40) + getThreadState(thread) + "\n");               }            }         else if (tokens.length == 2)            { // display specified thread            int threadIndex = Integer.valueOf(tokens[1]).intValue();            // !!TODO: danger here - how do we know if thread's context registers are            //         currently valid (ie. thread is not currently running and             //         won't start running while we're looking at it) ?            VM_Thread thread = VM_Scheduler.threads[threadIndex];            VM.sysWrite(thread.getIndex() + " " + thread + " " + getThreadState(thread) + "\n");                           VM_Address fp = (thread == VM_Thread.getCurrentThread())                    ? VM_Magic.getFramePointer()	      : thread.contextRegisters.getInnermostFramePointer();                           VM_Processor.getCurrentProcessor().disableThreadSwitching();            VM_Scheduler.dumpStack(fp);            VM_Processor.getCurrentProcessor().enableThreadSwitching();            }         else            VM.sysWrite("please specify a thread id\n");         return;	          case 'p': // print object 	 if (tokens.length == 2) {            int addr = Integer.parseInt(tokens[1], 16);            VM.sysWrite("Object at addr 0x");	    VM.sysWriteHex(addr);	    VM.sysWrite(": ");	    VM_ObjectModel.describeObject(VM_Address.fromInt(addr));	    VM.sysWriteln();	 }         else            VM.sysWriteln("Please specify an address\n");         return;         case 'd': // dump virtual machine state         VM_Scheduler.dumpVirtualMachine();         return;         case 'e': // enable/disable event logging         if (VM.BuildForEventLogging)            {            VM.EventLoggingEnabled = !VM.EventLoggingEnabled;            VM.sysWrite("event logging " + (VM.EventLoggingEnabled ? "enabled\n" : "disabled\n"));            }         else            VM.sysWrite("sorry, not built for event logging\n");         return;         case 'l': // dump and reset event log         if (VM.BuildForEventLogging)            {            String fileName = "temp.eventLog";            try {                FileOutputStream out = new FileOutputStream(fileName);                VM_EventLogger.dump(out);                out.close();                VM.sysWrite("event log written to \"" + fileName + "\"\n");                }            catch (IOException e)                {                VM.sysWrite("couldn't write \"" + fileName + "\": " + e + "\n");                }            }         else            VM.sysWrite("sorry, not built for event logging\n");         return;         case 'c': // continue execution of virtual machine (make debugger dormant until next debug request)         VM_Scheduler.debugRequested = false;         VM_Scheduler.debuggerMutex.lock();         yield(VM_Scheduler.debuggerQueue, VM_Scheduler.debuggerMutex);         return;         case 'q': // terminate execution of virtual machine         VM.sysWrite("terminating execution\n");         VM.sysExit(0);         return;         case EOF: // dump thread stacks and vm state and resume execution         VM_Scheduler.writeString("\n-- Stacks --\n");         for (int i = 1; i < VM_Scheduler.threads.length; ++i) {            VM_Thread t = VM_Scheduler.threads[i];            if (t != null) {               VM_Scheduler.writeString("\n Thread: ");               t.dump();               VM_Processor.getCurrentProcessor().disableThreadSwitching();               VM_Scheduler.dumpStack(t.contextRegisters.getInnermostFramePointer());               VM_Processor.getCurrentProcessor().enableThreadSwitching();            }         }         VM_Scheduler.writeString("\n");                  VM_Scheduler.dumpVirtualMachine();         VM_Scheduler.debugRequested = false;         VM_Scheduler.debuggerMutex.lock();         yield(VM_Scheduler.debuggerQueue, VM_Scheduler.debuggerMutex);         return;         default:         if (tokens.length == 1)            { // offer help            VM.sysWrite("Try one of:\n");            VM.sysWrite("   t                - display all threads\n");            VM.sysWrite("   t <threadIndex>  - display specified thread\n");            VM.sysWrite("   p <hex addr>     - print (describe) object at given address\n");            VM.sysWrite("   d                - dump virtual machine state\n");            VM.sysWrite("   e                - enable/disable event logging\n");            VM.sysWrite("   l                - write event log to a file\n");            VM.sysWrite("   c                - continue execution\n");            VM.sysWrite("   q                - terminate execution\n");            VM.sysWrite("   <class>.<method> - call a method\n");            VM.sysWrite("Or:\n");            VM.sysWrite("   <enter>          - repeat previous command once\n");            VM.sysWrite("   *                - repeat previous command once per second until SIGQUIT is received\n");            return;            }         // call a method                  // For the moment we only evaluate calls to static methods that take no parameters         // !!TODO: more elaborate parsing to accept arbitrary number of classname-qualifiers,         // parameter lists, static variables, arrays, etc.         if (tokens.length != 3 || !tokens[1].equals("."))            VM.sysWrite("please specify <class>.<method>\n");         else            {            Class    cls = Class.forName(tokens[0]);            Class[]  signature = new Class[0];            Method   method = cls.getMethod(tokens[2], signature);            Object[] args = new Object[0];            method.invoke(null, args);            }         return;         }      }