X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGInterface.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGInterface.java index 89ef3a2..5769aab 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGInterface.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGInterface.java @@ -14,13 +14,13 @@ package net.sourceforge.phpdt.internal.debug.core; import java.io.BufferedReader; import java.io.IOException; import java.io.OutputStream; -import java.util.Vector; import java.util.Collections; +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 net.sourceforge.phpdt.internal.debug.core.model.PHPVariable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; @@ -31,28 +31,30 @@ import org.eclipse.debug.core.DebugException; * */ 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 (); + 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 = new PHPStackFrame[0]; + 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]; + private OutputStream os; // The stream which goes to DBG + private boolean shouldStop = false; + private String evalRet = 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]; + + private static final String GlobalVariablesTitle = PHPDebugCorePlugin + .getResourceString("VariablesView.GlobalVariables.title"); /** * @param in The input stream (communication from DBG). @@ -179,7 +181,7 @@ public class PHPDBGInterface { PHPDBGFrame DBGFrame2; PHPDBGFrame DBGFrame3; int modNo; - + DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_BPS); DBGFrame2 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA); @@ -219,22 +221,21 @@ public class PHPDBGInterface { if (!condition.equals ("")) { // Do we have a condition for breakpoint rawCounter++; // Set to new ID DBGFrame1.addInt (rawCounter); // ID of condition - + DBGFrame3.addInt (rawCounter); // FRAME_RAWDATA ID DBGFrame3.addInt (condition.length() + 1); // length of rawdata (+ null char) DBGFrame3.addString (condition); // The break condition DBGFrame3.addChar ('\0'); // null char - DBGPacket.addFrame (DBGFrame3); // First add break condition + DBGPacket.addFrame (DBGFrame3); // First add break condition } else { DBGFrame1.addInt (0); // ID of condition is 0, because there is no condition } - DBGFrame1.addInt (bpno); // breakpoint number DBGFrame1.addInt (isunderhit); // is under hit - + DBGPacket.addFrame (DBGFrame1); // Second add command data if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? @@ -419,52 +420,100 @@ public class PHPDBGInterface { * @param stack The stackframe for which we want the variables. * @return The array of variables */ - public Vector getVariables (PHPStackFrame stack) throws IOException, DebugException { + public synchronized Vector getVariables(PHPStackFrame stack) throws IOException, DebugException { PHPDBGPacket DBGPacket; - PHPDBGFrame DBGFrame1; + 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 + // get global variables (and assign them to 'main()' stackframe) + Vector globalList = new Vector(); + globalList = getVariables(DBGStackList[DBGStackList.length - 1], PHPDBGBase.GLOBAL_SCOPE_ID); + if (!globalList.isEmpty()) { + // remove unexpected '$this=?' variable + PHPVariable var = (PHPVariable) globalList.get(0); + PHPValue val = (PHPValue) var.getValue(); + Vector workList = val.getChildVariables(); + for (int i = 0; i < workList.size(); i++) { + if (((PHPVariable) workList.get(i)).getName().equals("$this")) { + workList.remove(i); + break; + } + } + var.setName(GlobalVariablesTitle); + var.setModifiable(false); } - DBGPacket.sendPacket (os); // Send the request to DBG + int scopeID = stack.getScopeID(); + if (!globalList.isEmpty() + && ((DBGStackList.length == 1) + || (scopeID == PHPDBGBase.CURLOC_SCOPE_ID + 1))) { + // 'main()' stackframe + PHPVariable var = (PHPVariable) globalList.get(0); + PHPValue val = (PHPValue) var.getValue(); + DBGVarList = val.getChildVariables(); + return DBGVarList; - waitResponse (1000); // Wait for the DBG response (1 second) - flushAllPackets (); // Read and process the response from DBG + } else if (scopeID == PHPDBGBase.CURLOC_SCOPE_ID) { + // current stackframe + DBGVarList = getVariables(stack, PHPDBGBase.CURLOC_SCOPE_ID); - evalStr = new PHPDBGEvalString (stack, serGlobals); // Process serialized variables - DBGVarList = evalStr.getVariables (); + } else { + // back-trace stackframe + DBGVarList = getVariables(stack, scopeID); + // DBG 2.15.5 causes Application Error (on win32) in some cases + //DBGVarList.clear(); + } - if (DBGVarList.size () > 0) { // Did we get back variables? - PHPVariable var = (PHPVariable) DBGVarList.get (0); // Yes, then get the first PHPVariable - PHPValue val = (PHPValue) var.getValue (); // Get the value + if (DBGVarList.size() > 0) { // Did we get back variables? + PHPVariable var = (PHPVariable) DBGVarList.get(0); // Yes, then get the first PHPVariable + PHPValue val = (PHPValue) var.getValue(); // Get the value - if (var.getName ().equals ("")) { // Is the root node an empty node (usually it is) - DBGVarList = val.getChildVariables (); // Then remove the empty node. + if (var.getName().equals("")) { // Is the root node an empty node (usually it is) + DBGVarList = val.getChildVariables(); // Then remove the empty node. // With removing the empty root node, it wouldn't be necessary to // set the name to an empty string. So the code below is just for // info or in case the users want to have the empty root node. // The eclipse variable view cannot handle Variables which have an empty name // when it comes to variable tree restore operation. Without a name, no restore! - var.setName (" "); // Give a name to the variable root node. Even if it is only a space :-) + //var.setName (" "); // Give a name to the variable root node. Even if it is only a space :-) } // TODO the best would be to remove the empty root node, but this would // require a understanding and reworking of the PHPDBGEvalstring class. } + if (!globalList.isEmpty()) { + DBGVarList.add(globalList.get(0)); + } + return DBGVarList; // Return the variables as list } /** + * + * @throws IOException + */ + private Vector getVariables(PHPStackFrame stack, int scope_id) throws IOException { + PHPDBGPacket DBGPacket = new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); + PHPDBGFrame DBGFrame1 = new PHPDBGFrame(PHPDBGBase.FRAME_EVAL); + + DBGFrame1.addInt(0); + DBGFrame1.addInt(scope_id); + + DBGPacket.addFrame(DBGFrame1); + evalRet = ""; + + if (proxy.getSocket().isClosed()) { + return new Vector(); + } + DBGPacket.sendPacket(os); + waitResponse(1000); + flushAllPackets(); + + PHPDBGEvalString evalStr = new PHPDBGEvalString(stack, evalRet); + return evalStr.getVariables(); + } + + /** * * @param logString */ @@ -501,14 +550,19 @@ public class PHPDBGInterface { flushAllPackets(); } - public PHPVariable[] evalBlock(PHPStackFrame stack, String evalString) throws IOException, DebugException { + public synchronized 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 + //DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth + int scope_id = stack.getScopeID(); + if (DBGStackList.length == 1 || scope_id == PHPDBGBase.CURLOC_SCOPE_ID + 1) { + scope_id = PHPDBGBase.GLOBAL_SCOPE_ID; + } //- + DBGFrame1.addInt(scope_id); DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID DBGFrame2.addInt(evalString.length() + 1); // length of rawdata (+ null char) @@ -520,8 +574,8 @@ public class PHPDBGInterface { // Add command data DBGPacket.addFrame(DBGFrame1); - if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication? - return null; // No, then leave here + if (proxy.getSocket().isClosed()) { // Do we have a socket for DBG communication? + return null; // No, then leave here } DBGPacket.sendPacket(os); @@ -531,7 +585,6 @@ public class PHPDBGInterface { PHPDBGEvalString evalStr=new PHPDBGEvalString(stack,evalRet); return evalStr.getVars(); - } /** @@ -615,7 +668,7 @@ public class PHPDBGInterface { if ((int) framesInfo[nextFrame + 8 + toRead - 1] == 0) { // Is there a string termination at the end? return String.copyValueOf (framesInfo, nextFrame + 8, toRead - 1); // Then copy frame content to String without the \0 and return } - + return String.copyValueOf (framesInfo, nextFrame + 8, toRead); // Copy frame content to String and return } break; @@ -628,6 +681,76 @@ public class PHPDBGInterface { } /** + * Reset the availability flag for all stackframes in the list. + * + * @param list The list of old stackframes + */ + private void resetAvailability (Vector list) { + int i; + + for (i = 0; i < list.size (); i++) { + ((PHPStackFrame) list.get(i)).setAvailable (false); // + } + } + + /** + * Check whether the new stackframe is in the list of old stackframes. + * Test for identical stackframe (identical means same description and same line number). + * + * @param stackFrameNew The stackframe to check whether he is already within the old stackframe list + * @param list The list of old stackframes + * @return + * - true if we have found the identical stackframe within the list + * - false if we did not find the identical stackframe within the list + */ + private boolean isStackFrameInList (PHPStackFrame stackFrameNew, Vector list) { + int i; + PHPStackFrame stackFrameOld; + + for (i = 0; i < list.size (); i++) { + stackFrameOld = (PHPStackFrame) list.get (i); // + + if (stackFrameNew.getDescription ().equals (stackFrameOld.getDescription ()) && + stackFrameNew.getLineNumber () == stackFrameOld.getLineNumber ()) { // Did we find the sent stackframe within the list of old stackframes? + stackFrameOld.setAvailable (true); // We found the new stackframe in the list of old stack frames + stackFrameOld.setIndex (stackFrameNew.getIndex ()); + stackFrameOld.setScopeID(stackFrameNew.getScopeID()); + return true; // The stackframe was found in the list + } + } + + return false; + } + + /** + * Check whether the new stackframe is in the list of old stackframes. + * Test for exact stackframe (exact means same description and same line number). + * + * @param stackFrameNew The stackframe to check whether he is already within the old stackframe list + * @param list The list of old stackframes + * @return + * - true if we have exactly this stackframe within the list + * - false if we did not find the exact stackframe within the list + */ + private void markIdenticalStackFrames (Vector oldList, Vector newList) { + int i; + PHPStackFrame stackFrameNew; + + resetAvailability (oldList); // Reset the availability flag of the old stack frames + resetAvailability (newList); // Reset the availability flag of the old stack frames + + for (i = 0; i < newList.size (); i++) { // For all stackList entries + stackFrameNew = (PHPStackFrame) newList.get (i); + + if (isStackFrameInList (stackFrameNew, oldList)) { // Is this stackframe in the list + stackFrameNew.setAvailable (true); // + // + break; + } + } + } + + /** * * The stackList contains the currently read stackframes which were sent * from DBG. The DBG interface holds a list of the active stack frames. @@ -637,10 +760,10 @@ public class PHPDBGInterface { *
  • It looks for new stackframes within the DBG stackframe list and * adds them to the 'static' list. *
  • It looks for stackframes within the 'static' list, and removes them - * from the 'static' list in case the do not appear within the DBG list. + * from the 'static' list in case they do not appear within the DBG list. *
  • It looks for stackframes which are already existent and replicates the * line number and the index number. - *
  • At the end the 'static' stackfram list has to be sorted by the stackframes + *
  • At the end, the 'static' stackframe list has to be sorted by the stackframes * index numbers. * * @@ -657,22 +780,33 @@ public class PHPDBGInterface { PHPStackFrame stackFrameOld; PHPStackFrame[] newStackList; + markIdenticalStackFrames (stackListOld, stackList); // Check whether the newly send stack frames can be found in the list + // of old stack frames + 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.getDescription ().equals (stackFrameOld.getDescription ()) && - stackFrameNew.getLineNumber() == stackFrameOld.getLineNumber()) {// Did we find the sent stackframe within the list of old stackframes? + if (stackFrameOld.isAvailable ()) { // If this stack frame was already found in the new list skip it + continue; + } + + if (stackFrameNew.getDescription ().equals (stackFrameOld.getDescription ())) {// Did we find the sent stackframe within the list of old stackframes? stackFrameOld.setLineNumber (stackFrameNew.getLineNumber ()); stackFrameOld.setIndex (stackFrameNew.getIndex ()); + stackFrameOld.setScopeID(stackFrameNew.getScopeID()); + + stackFrameOld.setAvailable (true); // And mark this stack frame as available + stackFrameNew.setAvailable (true); // And mark this stack frame as available break; // Yes, then break; } } - if (n == stackListOld.size ()) { // Did not find the new stackframe within the list + if (!stackFrameNew.isAvailable ()) { // Did not find the new stackframe within the list? + stackFrameNew.setAvailable (true); // Mark the stack frame as available and stackListOld.add (stackFrameNew); // then add the new stackframe } } @@ -682,13 +816,9 @@ public class PHPDBGInterface { 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.getDescription ().equals (stackFrameOld.getDescription ()) && - stackFrameNew.getLineNumber() == stackFrameOld.getLineNumber()) {// Did we find the sent stackframe within the list of old stackframes? - break; // Yes, then break; - } + i = 0; + if (!stackFrameOld.isAvailable ()) { + i = stackList.size (); } if (i == stackList.size ()) { // Did not find the old stackframe within the list of new ones @@ -785,7 +915,8 @@ public class PHPDBGInterface { 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 + dbg_stack_new[1], // The module number + dbg_stack_new[2]); stackList.add (newStack); } @@ -885,7 +1016,6 @@ public class PHPDBGInterface { evalRet = getRawFrameData (entirePack, dbg_eval_tmp[1]); // evalString = getRawFrameData (entirePack, dbg_eval_tmp[0]); // - serGlobals = evalRet; // break; case PHPDBGBase.FRAME_BPS: //