/********************************************************************** Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html Contributors: Vicente Fernando - www.alfersoft.com.ar - Initial implementation Christian Perkonig - remote debug **********************************************************************/ package net.sourceforge.phpdt.internal.debug.core; import java.io.BufferedReader; import java.io.IOException; import java.io.OutputStream; import java.util.Vector; import net.sourceforge.phpdt.internal.debug.core.model.PHPDBGEvalString; import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame; import net.sourceforge.phpdt.internal.debug.core.model.PHPVariable; import net.sourceforge.phpdt.internal.debug.core.model.PHPValue; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugException; import java.io.RandomAccessFile; /** * The interface object are created by the proxy * */ public class PHPDBGInterface { public boolean sessionEnded = false; public int sessType = -1; public int BPUnderHit = 0; public String sessID = new String (); private int[] LastBPRead = new int[10]; private Vector DBGBPList = new Vector (); private Vector DBGVarList = new Vector (); private PHPStackFrame[] DBGStackList; private Vector DBGMods = new Vector (); // The module names and their numbers private Vector stackListOld = new Vector (); private BufferedReader in; private OutputStream os; // The stream which goes to DBG private boolean shouldStop = false; private String evalRet = new String (""); private String serGlobals = new String (""); private int rawCounter = 1000; // An rawData frame ID counter private PHPDBGProxy proxy = null; private int lastCmd = -1; private int sid = 0; private boolean stopOnError = false; private char[] lastCommand = new char[4]; /** * @param in The input stream (communication from DBG). * @param os The output stream (communication to DBG). * @param proxy The proxy to which this interface belongs. */ public PHPDBGInterface (BufferedReader in, OutputStream os, PHPDBGProxy proxy) { DBGBPList.clear (); this.in = in; this.os = os; this.proxy = proxy; } /** * * @param mod_name The module (source file) to which we add the breakpoint. * @param line The line where the breakpoint is set. * @return Breakpoint ID ???. */ public int addBreakpoint (String mod_name, int line) throws IOException { return setBreakpoint (mod_name, "", line, PHPDBGBase.BPS_ENABLED + PHPDBGBase.BPS_UNRESOLVED, 0, 0, 0, 0, 0); } /** * * @param mod_name The module (source file) to which we add the breakpoint. * @param line The line where the breakpoint is set. * @param bpNo The breakpoint ID ???. */ public void removeBreakpoint (String mod_name, int line, int bpNo) throws IOException { setBreakpoint (mod_name, "", line, PHPDBGBase.BPS_DISABLED, 0, 0, 0, bpNo, 0); } /** * Is this method used anywhere? * */ public void requestDBGVersion () throws IOException { PHPDBGPacket DBGPacket; // A DBG message packet PHPDBGFrame DBGFrame; // A frame within a DBG packet DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); // A request for DBG DBGFrame = new PHPDBGFrame (PHPDBGBase.FRAME_VER); // We want the version of DBG DBGPacket.addFrame (DBGFrame); // Add the 'what we want' to the DBG packet if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? return; // No } DBGPacket.sendPacket (os); // Send the request to DBG } /** * Called by the proxy * */ public void getSourceTree () throws IOException { PHPDBGPacket DBGPacket; // A DBG message packet PHPDBGFrame DBGFrame; // A frame within a DBG packet DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); // A request for DBG DBGFrame = new PHPDBGFrame (PHPDBGBase.FRAME_SRC_TREE); // We want a source tree from DBG DBGPacket.addFrame (DBGFrame); // Add the 'what we want' to the DBG packet if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? return; // No } DBGPacket.sendPacket (os); // Send the request to DBG waitResponse (1000); // Wait for the DBG response (1 second) flushAllPackets (); // Read and process the response from DBG } /** * Is this method called from anywhere? * * @param modName The modul (filename). */ public void addDBGModName (String modName) throws IOException { PHPDBGPacket DBGPacket; // A DBG message packet PHPDBGFrame DBGFrame; // A frame within a DBG packet DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); // A request for DBG DBGFrame = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA); // We want Module name from DBG rawCounter++; // Increment the rawData ID counter DBGFrame.addInt (rawCounter); // FRAME_RAWDATA ID DBGFrame.addInt (modName.length () + 1); // The length of rawdata string (incl. null char termination) DBGFrame.addString (modName); // The file name (module name) DBGFrame.addChar ('\0'); // Add the C-String null termination DBGPacket.addFrame (DBGFrame); if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? return; // No } DBGPacket.sendPacket (os); } /** * This method is called for adding or removing breakpoints. * * @param mod_name The module name (file name). * @param condition Info about the condition when to break (not used at the moment). * @param line The breakpoints line. * @param state Info whether this breakpoint has to be dis- or enabled. * @param istep Always 0. * @param hitcount Always 0. * @param skiphits Always 0. * @param bpno The breakpoint ID. * @param isunderhit ??? * @return */ private int setBreakpoint (String mod_name, String condition, int line, int state, int istemp, int hitcount, int skiphits, int bpno, int isunderhit) throws IOException { PHPDBGPacket DBGPacket; PHPDBGFrame DBGFrame1; PHPDBGFrame DBGFrame2; int modNo; DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_BPS); DBGFrame2 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA); modNo = getModByName (mod_name); // Get the module ID by name if (modNo >= 0) { // Did we find a module ID for the module name? DBGFrame1.addInt (modNo); // Add the module ID to frame 1 } else { DBGFrame1.addInt (0); // mod number (0 use file name) } DBGFrame1.addInt (line); // line number if (modNo >= 0) { // Did we find a module ID for the module name? DBGFrame1.addInt (0); // use mod number } else { rawCounter++; DBGFrame1.addInt (rawCounter); // ID of FRAME_RAWDATA to send file name } DBGFrame1.addInt (state); // state BPS_* DBGFrame1.addInt (istemp); // istep DBGFrame1.addInt (hitcount); // hit count DBGFrame1.addInt (skiphits); // skip hits DBGFrame1.addInt (0); // ID of condition DBGFrame1.addInt (bpno); // breakpoint number DBGFrame1.addInt (isunderhit); // is under hit if (modNo < 0) { // Did we find a module ID for the module name? DBGFrame2.addInt (rawCounter); // FRAME_RAWDATA ID DBGFrame2.addInt (mod_name.length() + 1); // length of rawdata (+ null char) DBGFrame2.addString (mod_name); // file name DBGFrame2.addChar ('\0'); // null char DBGPacket.addFrame (DBGFrame2); // First add file name data } DBGPacket.addFrame (DBGFrame1); // Second add command data if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? return 0; // No } DBGPacket.sendPacket (os); // Send the request to DBG clearLastBP (); waitResponse (1000); // Wait for the DBG response (1 second) flushAllPackets (); // Read and process the response from DBG return LastBPRead[8]; // Return what ??? } /** * */ private void clearLastBP () { int i; for (i = 0; i < LastBPRead.length; i++) { LastBPRead[i] = 0; } } /** * */ private void copyToLastBP (int[] BPBody) { int i; for (i = 0; i < LastBPRead.length; i++) { LastBPRead[i] = BPBody[i]; } } /** * */ public void continueExecution () throws IOException { PHPDBGPacket DBGPacket; BPUnderHit = 0; DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_CONTINUE); if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? return; // No } DBGPacket.sendPacket (os); // Send the request to DBG lastCommand = PHPDBGBase.DBGA_CONTINUE; // Store the info about the command we sent } /** * */ public void pauseExecution () throws IOException { PHPDBGPacket DBGPacket; DBGPacket = new PHPDBGPacket (PHPDBGBase.IntToChar4 (PHPDBGBase.DBGC_PAUSE)); if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? return; // No } DBGPacket.sendPacket (os); // Send the request to DBG } /** * */ private int getBPUnderHit () { int i; int BPUnder = 0; int[] dbg_bpl_body = new int[10]; for (i = 0; i < DBGBPList.size (); i++) { // look for bp under hit dbg_bpl_body = (int[]) DBGBPList.get (i); if (dbg_bpl_body[9] == 1) { BPUnder = dbg_bpl_body[8]; } } return BPUnder; } public int getLastCmd() { return lastCmd; } public int getSID() { return sid; } public void setLastCmd (int cmd) { lastCmd = cmd; } /** * */ public void stepInto () throws IOException { PHPDBGPacket DBGPacket; BPUnderHit = 0; DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPINTO); if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? return; // No } DBGPacket.sendPacket (os); // Send the request to DBG lastCommand = PHPDBGBase.DBGA_STEPINTO; // Store the info about the command we sent } /** * */ public void stepOver () throws IOException { PHPDBGPacket DBGPacket; BPUnderHit = 0; DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOVER); if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? return; // No } DBGPacket.sendPacket (os); // Send the request to DBG lastCommand = PHPDBGBase.DBGA_STEPOVER; // Store the info about the command we sent } /** * */ public void stepOut () throws IOException { PHPDBGPacket DBGPacket; BPUnderHit = 0; DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOUT); if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? return; // No } DBGPacket.sendPacket (os); // Send the request to DBG lastCommand = PHPDBGBase.DBGA_STEPOUT; // Store the info about the command we sent } /** * */ public void stopExecution () throws IOException { PHPDBGPacket DBGPacket; BPUnderHit = 0; DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STOP); if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? return; // No } DBGPacket.sendPacket (os); // Send the request to DBG } /** * This method updates the 'static' variables list. * It does a replication between the 'static' list (the variable list which * is a member of this DBG interface object) and the DBG variable list * (the list of variables which is received from PHP via DBG with the current suspend) * Replication is done in the following way: * * * @param varListOld The 'static' list of variables which are to be updated. * @param varListNew The new list of (current) variables from DBG. */ private void updateVariableList (Vector varListOld, Vector varListNew) { PHPVariable varOld; // The variable from the 'static' list PHPVariable varNew; // The variable from the DBG list PHPValue valOld; // The value of the current variable from 'static' list PHPValue valNew; // The value of the current variable from DBG list int n; // Index for the DBG list int o; // Index for the static list // Add the variables (and childs) to the static list if they are new // and update the values of variables which are already existend within // the 'static' list. for (n = 0; n < varListNew.size (); n++) { // For every variable in 'DBG list' varNew = (PHPVariable) varListNew.get (n); // Get the DBG variable for (o = 0; o < varListOld.size (); o++) { // For every variable in static list varOld = (PHPVariable) varListOld.get (o); // Get the static variable if (varNew.getName ().equals (varOld.getName ())) { // Did we found the variable within the 'static' list? valOld = (PHPValue) varOld.getValue (); // Get the value from 'static' valNew = (PHPValue) varNew.getValue (); // Get the value from DBG try { if (valOld.hasVariables () || // If the 'static' value has child variables valNew.hasVariables ()) { // or if the DBG value has child variables updateVariableList (valOld.getChildVariables (), // Update the variable list for the child variables valNew.getChildVariables ()); } else if (!valOld.getValueString ().equals (valNew.getValueString ())) { // Has the value changed? valOld.setValueString (valNew.getValueString ()); // Yes, set the 'static' value (variable) to the new value varOld.setValueChanged (true); // and set the 'has changed' flag, so that the variable view // could show the user the changed status with a different // color } else { varOld.setValueChanged (false); // Reset the 'has changed' flag } } catch (DebugException e) { // That's, because of the hasVariables method } break; // Found the variable, } } if (o == varListOld.size ()) { // Did we found the variable within the static list? varListOld.add (varNew); // No, then add the DBG variable to the static list } } // Look for the variables we can remove from the 'static' list for (o = 0; o < varListOld.size (); o++) { // For every variable in 'static' list varOld = (PHPVariable) varListOld.get (o); // Get the static variable for (n = 0; n < varListNew.size (); n++) { // For all variables in 'DBG' list varNew = (PHPVariable) varListNew.get (n); // Get the variable from the 'DBG' list if (varNew.getName ().equals (varOld.getName ())) { // Did we found the 'static' list variable within the 'DBG' list? break; // Yes we found the variable, then leave the loop } } if (n == varListNew.size ()) { // Did not find the 'static' list variable within the 'DBG' list? varListOld.remove (o); // then remove the 'static' list variable from list o -= 1; // Adjust the 'static' list index } } } /** * This method is called by the proxy. * It sends a request to DBG to get the current variables * with their values. It waits for the response and processes * the input from DBG. * * @param stack The stackframe for which we want the variables. * @return The array of variables */ public PHPVariable[] getVariables (PHPStackFrame stack) throws IOException, DebugException { PHPDBGPacket DBGPacket; PHPDBGFrame DBGFrame1; PHPDBGEvalString evalStr; DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); // DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_EVAL); // DBGFrame1.addInt (0); // istr = raw data ID DBGFrame1.addInt (1); // scope_id = -1 means current location, 0 never used, +1 first depth DBGPacket.addFrame (DBGFrame1); // Add command data if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication? return null; // No, then leave here } DBGPacket.sendPacket (os); // Send the request to DBG waitResponse (1000); // Wait for the DBG response (1 second) flushAllPackets (); // Read and process the response from DBG evalStr = new PHPDBGEvalString (stack, serGlobals); // Process serialized variables updateVariableList (DBGVarList, evalStr.getVariables ()); // Replicate the 'static' variable list and the via DBG received variable list return (PHPVariable[]) DBGVarList.toArray (new PHPVariable[DBGVarList.size ()]); // Convert the list to an array and return the array } /** * * @param logString */ public void log(String logString) throws IOException, DebugException { PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_LOG); PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA); rawCounter++; DBGFrame1.addInt(rawCounter); // ilog DBGFrame1.addInt(1); // type DBGFrame1.addInt(0); // mod_no DBGFrame1.addInt(0); // line_no DBGFrame1.addInt(0); // imod_name DBGFrame1.addInt(0); // ext_info DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID DBGFrame2.addInt(logString.length() + 1); // length of rawdata (+ null char) DBGFrame2.addString(logString); // log string DBGFrame2.addChar('\0'); // null char // Add raw data first DBGPacket.addFrame(DBGFrame2); // Add command data DBGPacket.addFrame(DBGFrame1); if(proxy.getSocket().isClosed()) return; DBGPacket.sendPacket(os); waitResponse(1000); flushAllPackets(); } public PHPVariable[] evalBlock(PHPStackFrame stack, String evalString) throws IOException, DebugException { PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL); PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA); rawCounter++; DBGFrame1.addInt(rawCounter); // istr = raw data ID DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID DBGFrame2.addInt(evalString.length() + 1); // length of rawdata (+ null char) DBGFrame2.addString(evalString); // eval block DBGFrame2.addChar('\0'); // null char // Add raw data first DBGPacket.addFrame(DBGFrame2); // Add command data DBGPacket.addFrame(DBGFrame1); if(proxy.getSocket().isClosed()) return null; DBGPacket.sendPacket(os); waitResponse(1000); flushAllPackets(); PHPDBGEvalString evalStr=new PHPDBGEvalString(stack,evalRet); return evalStr.getVars(); } /** * Read and process everthing we got from DBG */ public void flushAllPackets () throws IOException { while (readResponse() != 0); } /** * Get the modules name by its number * * @param modNo The number (id) of the module * @return The name of the module */ public String getModByNo (int modNo) { int i; PHPDBGMod dbg_mod; for (i = 0; i < DBGMods.size (); i++) { // For all the modules we have within the array dbg_mod = (PHPDBGMod) DBGMods.get (i); // Get the module if (dbg_mod.getNo () == modNo) { // Is the module from the array the module we want? return dbg_mod.getName (); // Yes, return the name of the module } } return ""; // If nothing was found return emtpy string } /** * * @param modName The name of the module for which we want the ID * @return * - The ID of the module * - -1 if nothing was found */ private int getModByName (String modName) { int i; PHPDBGMod dbg_mod; for (i = 0; i < DBGMods.size (); i++) { // For all the modules we have within the array dbg_mod = (PHPDBGMod) DBGMods.get (i); // Get the module if (dbg_mod.getName ().equalsIgnoreCase (modName)) { // Is the module from the array the module we want? return dbg_mod.getNo (); // Yes, return the name of the module } } return -1; // If nothing was found return -1 } /** * Return the string for the given frame number * * @param framesInfo The buffer which is to read * @param frameNo The frame number * @return */ private String getRawFrameData (char[] framesInfo, int frameNo) { int nextFrame = 0; // The current read position within the buffer int[] dbg_frame = new int[2]; // The two frame header numbers while (nextFrame < framesInfo.length) { // As long we have something within the buffer dbg_frame[0] = PHPDBGBase.Char4ToInt (framesInfo, nextFrame); // The frame type dbg_frame[1] = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4); // The frame size nextFrame += 8; // The current read position if (dbg_frame[1] == 0) { // If frame size is 0 return ""; // return an emtpy string } switch (dbg_frame[0]) { // Switch for the frame type case PHPDBGBase.FRAME_RAWDATA: // The only frame type we are interrested in if (frameNo == PHPDBGBase.Char4ToInt (framesInfo, nextFrame)) { // Is it correct number of the frame int toRead; // toRead = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4); // The size of the string return String.copyValueOf (framesInfo, nextFrame + 8, toRead); // Copy frame content to String and return } break; } nextFrame += dbg_frame[1]; // Go for the next frame (add the length of the current one) } return ""; // We did not found any FRAM_RAWDATA, so return an emtpy strin } /** * * The stackList contains the currently read stackframes which were sent * from DBG. The DBG interface holds a list of the active stack frames. * This method looks whether the sent stackframes are already in the list. * Removes the unused stackframes from the list, or adds stackframes which * are not yet in the list. * * @param stackList */ private void updateStackFrameList (Vector stackList) { int i; int n; PHPStackFrame stackFrameNew; PHPStackFrame stackFrameOld; PHPStackFrame[] newStackList; for (i = 0; i < stackList.size (); i++) { // For all stackList entries stackFrameNew = (PHPStackFrame) stackList.get(i); for (n = 0; n < stackListOld.size (); n++) { // For all StackFrames in the StackFrame list stackFrameOld = (PHPStackFrame) stackListOld.get (n); // --- if (stackFrameNew.getModNo () == stackFrameOld.getModNo ()) { // Did we find the sent stackframe within the list of old stackframes? stackFrameOld.setLineNumber (stackFrameNew.getLineNumber()); break; // Yes, then break; } } if (n == stackListOld.size ()) { // Did not find the new stackframe within the list stackListOld.add (stackFrameNew); // then add the new stackframe } } // And now for removing unused stackframes from list for (n = 0; n < stackListOld.size (); n++) { // For all StackFrames in the StackFrame list stackFrameOld = (PHPStackFrame) stackListOld.get (n); // --- for (i = 0; i < stackList.size (); i++) { // For all stackList entries stackFrameNew = (PHPStackFrame) stackList.get (i); if (stackFrameNew.getModNo () == stackFrameOld.getModNo ()) { // Did we find the sent stackframe within the list of old stackframes? break; // Yes, then break; } } if (i == stackList.size ()) { // Did not find the old stackframe within the list of new ones stackListOld.remove (n); // then remove the old stackframe from list n -= 1; // Adjust the stack list index } } newStackList = new PHPStackFrame[stackListOld.size ()]; newStackList = (PHPStackFrame[]) stackListOld.toArray (newStackList); DBGStackList = newStackList; } /** * Read the response from DBG and process the frame * * @return * - The received command * - or 0 if something was wrong */ public int readResponse () throws IOException { int bytesToRead = 0; // The number of byte to read for the current DBG block int nextFrame = 0; // The current read position within entirePack int i = 0; int cmdReceived = 0; int stackIndex = 0; boolean errorStack = false; char[] dbg_header_struct_read = new char[16]; // The buffer for the first 16 bytes of a block int[] dbg_header_struct = new int[4]; // The first four numbers (long) of a block int[] dbg_bpl_tmp = new int[10]; int[] dbg_frame = new int[2]; int[] dbg_eval_tmp = new int[3]; int[] dbg_src_tree_tmp = new int[4]; // int[] dbg_error_tmp = new int[2]; Vector rawList = new Vector(); Vector stackList = new Vector(); // Intermediate stacklist which is build up in FRAME_STACK frame rawList.clear (); stackList.clear (); // Read from input while (readInput (dbg_header_struct_read, 16) != 0) { // Read 16 byte from input stream dbg_header_struct[0] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 0); // Debug sync header dbg_header_struct[1] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 4); // Command dbg_header_struct[2] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 8); // dbg_header_struct[3] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 12); // Bytes within this block if (dbg_header_struct[0] != 0x5953) { // Check DBG sync bytes return 0; // Wrong header } cmdReceived = dbg_header_struct[1]; // Get the command setLastCmd (cmdReceived); // Store the info about the current command bytesToRead = dbg_header_struct[3]; // Get the number of bytes to read for this block //System.out.println("Response Received: " + cmdReceived); char[] entirePack = new char[bytesToRead]; // Store the block data into buffer 'entirePack' if (bytesToRead > 0) { // If there is something within the frame if (readInput (entirePack, bytesToRead) < bytesToRead) { // Read the frame into the buffer return 0; // We did not read enough bytes, error } } nextFrame = 0; // Start with the first frame while (nextFrame < bytesToRead) { // As long as we have something within this block dbg_frame[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame); // The name of the frame dbg_frame[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // The size of the frame nextFrame += 8; // The next read position if (dbg_frame[1] == 0) { // Something within the frame? return 0; // Nothing to read, error } switch (dbg_frame[0]) { case PHPDBGBase.FRAME_STACK: int[] dbg_stack_new = new int[4]; // dbg_stack_new[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // Source line number dbg_stack_new[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // Module number dbg_stack_new[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8); // Scope id dbg_stack_new[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12); // ID of description string if ((dbg_stack_new[1] != 0) && !errorStack) { PHPStackFrame newStack; stackIndex++; newStack = new PHPStackFrame (null, // The thread getModByNo (dbg_stack_new[1]), // The name of the module (file) dbg_stack_new[0], // The source line number stackIndex, getRawFrameData (entirePack, // Get the string from this packet dbg_stack_new[3]), // The frame ID for which we want the string dbg_stack_new[1]); // The module number stackList.add (newStack); } errorStack = false; break; case PHPDBGBase.FRAME_SOURCE: // Nothing to be done here break; // TODO: what's with that frame? Something interesting case PHPDBGBase.FRAME_SRC_TREE: // dbg_src_tree_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // The parent module number dbg_src_tree_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // The parent line number (not used) dbg_src_tree_tmp[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8); // The module number dbg_src_tree_tmp[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12); // The filename number if (getModByNo (dbg_src_tree_tmp[2]).equals ("")) { String fileName; fileName = new String (getRawFrameData (entirePack, dbg_src_tree_tmp[3])); // Get the filename if (fileName.length () > 0) { // If we have a filename fileName = fileName.substring (0, fileName.length () - 1); // Remove '\0' char } if (dbg_src_tree_tmp[2] != 0) { // If there is a module number PHPDBGMod modNew; modNew = new PHPDBGMod (dbg_src_tree_tmp[2], fileName); // Create a module object DBGMods.add (modNew); // And store it to array } } break; case PHPDBGBase.FRAME_RAWDATA: // Nothing to be done here break; // FRAME_RAWDATA are processed within getRawFrameData case PHPDBGBase.FRAME_ERROR: // An error frame errorStack = true; // Yes, we have an error stack dbg_error_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // Error type dbg_error_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // Error message ID String error = "\n"; // switch (dbg_error_tmp[0]) { // Switch on error type case PHPDBGBase.E_ERROR: error += "[Error]"; break; case PHPDBGBase.E_WARNING: error += "[Warning]"; break; case PHPDBGBase.E_PARSE: error += "[Parse Error]"; break; case PHPDBGBase.E_NOTICE: error += "[Notice]"; break; case PHPDBGBase.E_CORE_ERROR: error += "[Core Error]"; break; case PHPDBGBase.E_CORE_WARNING: error += "[Core Warning]"; break; case PHPDBGBase.E_COMPILE_ERROR: error += "[Compile Error]"; break; case PHPDBGBase.E_COMPILE_WARNING: error += "[Compile Warning]"; break; case PHPDBGBase.E_USER_ERROR: error += "[User Error]"; break; case PHPDBGBase.E_USER_WARNING: error += "[User Warning]"; break; case PHPDBGBase.E_USER_NOTICE: error += "[User Notice]"; break; default: error += "[Unexpected Error]"; break; } error += ": "; error += new String (getRawFrameData (entirePack, dbg_error_tmp[1])); // Add the error string for this error message ID if (error.length () > 0) { // If we have a error message error = error.substring (0, error.length () - 1); // Remove '\0' char } error += "\n"; // Append a CR PHPDebugCorePlugin.log (new DebugException (new Status (IStatus.WARNING, PHPDebugCorePlugin.PLUGIN_ID, IStatus.OK, error, null))); // To print errors on the console, I must execute a code in the // php context, that write the stderr... I didn't found a better way // TODO: Find a better way???? // String codeExec= ""; // codeExec= "fwrite(fopen('php://stderr', 'w'),\\\"" + error + "\\\");"; // try { // evalBlock("eval(\"" + codeExec + "\");"); // } catch (DebugException e) { // PHPDebugCorePlugin.log(e); // } // if (!stopOnError) { // Is always false (Did not see where this is set to true!?) if (lastCommand.equals (PHPDBGBase.DBGA_CONTINUE)) { // If last command for PHP was a 'continue', continueExecution (); // send continue again } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPINTO)) { // If last command for PHP was a 'step into', stepInto (); // send 'step into' again } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPOUT)) { // If last command for PHP was a 'step out', stepOut (); // send 'step out' again } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPOVER)) { // If last command for PHP was a 'step over', stepOver (); // send 'step over' again } } break; case PHPDBGBase.FRAME_EVAL: String evalString; evalString = new String (""); dbg_eval_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // istr dbg_eval_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // iresult dbg_eval_tmp[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8); // ierror evalRet = getRawFrameData (entirePack, dbg_eval_tmp[1]); // evalString = getRawFrameData (entirePack, dbg_eval_tmp[0]); // serGlobals = evalRet; // break; case PHPDBGBase.FRAME_BPS: // break; // case PHPDBGBase.FRAME_BPL: int[] dbg_bpl_new; dbg_bpl_new = new int[10]; dbg_bpl_new[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); dbg_bpl_new[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); dbg_bpl_new[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8); dbg_bpl_new[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12); dbg_bpl_new[4] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 16); dbg_bpl_new[5] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 20); dbg_bpl_new[6] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 24); dbg_bpl_new[7] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 28); dbg_bpl_new[8] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 32); dbg_bpl_new[9] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 36); // look if breakpoint already exists in vector for (i = 0; i < DBGBPList.size (); i++) { dbg_bpl_tmp = (int[]) DBGBPList.get (i); if (dbg_bpl_tmp[8] == dbg_bpl_new[8]) { DBGBPList.remove (i); break; } } // add breakpoint to vector DBGBPList.add (dbg_bpl_new); copyToLastBP (dbg_bpl_new); // mod no returned? if (getModByNo (dbg_bpl_new[0]).equals ("")) { String fileName; fileName = new String (getRawFrameData (entirePack, dbg_bpl_new[2])); if (fileName.length () > 0) { // If we have filename fileName = fileName.substring (0, fileName.length () - 1); // Remove '\0' char } if (dbg_bpl_new[0] != 0) { PHPDBGMod modNew; modNew = new PHPDBGMod (dbg_bpl_new[0], fileName); DBGMods.add (modNew); } } break; case PHPDBGBase.FRAME_VER: break; case PHPDBGBase.FRAME_SID: sid = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); break; case PHPDBGBase.FRAME_SRCLINESINFO: break; case PHPDBGBase.FRAME_SRCCTXINFO: break; case PHPDBGBase.FRAME_LOG: break; case PHPDBGBase.FRAME_PROF: break; case PHPDBGBase.FRAME_PROF_C: break; case PHPDBGBase.FRAME_SET_OPT: break; } nextFrame += dbg_frame[1]; // go to next frame } // Now process command switch(cmdReceived) { case PHPDBGBase.DBGC_REPLY: break; case PHPDBGBase.DBGC_STARTUP: break; case PHPDBGBase.DBGC_END: sessionEnded = true; break; case PHPDBGBase.DBGC_BREAKPOINT: BPUnderHit = getBPUnderHit (); updateStackFrameList (stackList); break; case PHPDBGBase.DBGC_STEPINTO_DONE: case PHPDBGBase.DBGC_STEPOVER_DONE: case PHPDBGBase.DBGC_STEPOUT_DONE: case PHPDBGBase.DBGC_EMBEDDED_BREAK: case PHPDBGBase.DBGC_PAUSE: BPUnderHit = 1; updateStackFrameList (stackList); break; case PHPDBGBase.DBGC_ERROR: stackList.clear (); updateStackFrameList (stackList); break; case PHPDBGBase.DBGC_LOG: break; case PHPDBGBase.DBGC_SID: break; } } return cmdReceived; // Return the command we received with this block } /** * */ public PHPStackFrame[] getStackList() { return DBGStackList; } /** * Reads from input buffer (response sent from DBG) the given number of chars * into frame buffer. * * @param buffer The frame buffer where to store the read data from DBG. * @param bytes The number of bytes (chars) which are to read from input stream. * @return The number of bytes actually read. */ private int readInput (char[] buffer, int bytes) throws IOException { int bytesRead = 0; // Reset the bytes read counter for (int i = 0; i < bytes; i++) { // For the number of bytes we should read if (in.ready ()) { // If input stream is ready for reading buffer[i] = (char) (in.read () & 0x00FF); // Read a char and store only the least significant 8-bits bytesRead++; // Increment the bytes read counter } else { // Input stream is not ready break; // Break the loop } } return bytesRead; // Return the number of bytes actually read } /** * PHPProxy could stop the waiting for a response with this method. * */ public void setShouldStop () { this.shouldStop = true; } /** * @param milliseconds The maximum time in milliseconds we wait for something * to be send from DBG. * @return - true if something was received from DBG * - false if nothing was send from DBG within the given time * */ public boolean waitResponse (long milliseconds) throws IOException { long timeout; timeout = System.currentTimeMillis () + milliseconds; // Calculate the system time till we wait. while (System.currentTimeMillis () < timeout) { // Is waiting time running out? if (in.ready () || shouldStop) { // No, so did we get something or should we stop now break; // Yes, break the waiting } } return in.ready (); // true if we got something from DBG } }