X-Git-Url: http://git.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 03a735f..0ae3bc0 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
@@ -26,14 +26,11 @@ 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;
@@ -72,12 +69,14 @@ public class PHPDBGInterface {
/**
*
- * @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 ???.
+ * @param mod_name The module (source file) to which we add the breakpoint.
+ * @param line The line where the breakpoint is set.
+ * @param hitCount The number of hit counts before suspend.
+ * @param condition The break condition
+ * @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);
+ public int addBreakpoint (String mod_name, int line, int hitCount, String condition) throws IOException {
+ return setBreakpoint (mod_name, condition, line, PHPDBGBase.BPS_ENABLED + PHPDBGBase.BPS_UNRESOLVED, 0, hitCount, 0, 0, 0);
}
/**
@@ -178,11 +177,13 @@ public class PHPDBGInterface {
PHPDBGPacket DBGPacket;
PHPDBGFrame DBGFrame1;
PHPDBGFrame DBGFrame2;
+ PHPDBGFrame DBGFrame3;
int modNo;
DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);
DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_BPS);
DBGFrame2 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA);
+ DBGFrame3 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA);
modNo = getModByName (mod_name); // Get the module ID by name
@@ -201,14 +202,6 @@ public class PHPDBGInterface {
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)
@@ -218,6 +211,29 @@ public class PHPDBGInterface {
DBGPacket.addFrame (DBGFrame2); // First add file name data
}
+ DBGFrame1.addInt (state); // state BPS_*
+ DBGFrame1.addInt (istemp); // istemp
+ DBGFrame1.addInt (0); // hit count; this is not supported as one might think
+ DBGFrame1.addInt (hitcount); // skip hits is what we think is hit count.
+
+ 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
+ }
+ 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?
@@ -394,136 +410,6 @@ public class PHPDBGInterface {
}
/**
- * Go up the tree of PHPVariables
- * look whether the PHPValue is a reference to a parent PHPValue
- *
- * TODO Check where this recursion can come from.
- * Whether this back reference is legal or a bug.
- *
- * @param var
- * @return
- *
- * - false if the PHPValue is not a child of itself
- *
- true if the PHPValue is
- *
- */
-
- private boolean hasRecursion (PHPVariable var) {
- PHPVariable parentVar;
- PHPValue val;
-
- val = (PHPValue) var.getValue (); // Get the PHPValue from the current PHPVariable
-
- while (var != null) { // As long as we have PHPVariable
- parentVar = var.getParent (); // Get the parent PHPVariable
-
- if (parentVar != null) { // Is there a parent?
- if (parentVar.getValue ().equals (val)) { // Get the PHPValue for the parent PHPVariable and check
- // whether it is the same
- return true; // Return, if we have recursion
- }
- }
-
- var = parentVar;
- }
-
- return false; // No recursion found
- }
-
- /**
- * 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:
- *
- * - It looks for new variables within the DBG variables list and
- * adds them to the 'static' list.
- *
- It looks for changed variables copies the current value to the variable within
- * the 'static list' and mark these variables as 'hasChanged' (which uses the UI
- * for showing the variable with a different color).
- *
- It looks for variables within the 'static' list, and removes them
- * from the 'static' list in case the do not appear within the DBG list.
- *
- *
- * @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
- if (!hasRecursion (varOld) &&
- !hasRecursion (varNew)) { // Both branches should not have a recursion
- 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
@@ -532,7 +418,7 @@ 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;
PHPDBGEvalString evalStr;
@@ -546,7 +432,7 @@ public class PHPDBGInterface {
DBGPacket.addFrame (DBGFrame1); // Add command data
if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication?
- return null; // No, then leave here
+ return new Vector (); // No, then leave here with an empty vector
}
DBGPacket.sendPacket (os); // Send the request to DBG
@@ -555,7 +441,24 @@ public class PHPDBGInterface {
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
+ DBGVarList = evalStr.getVariables ();
+
+ 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.
+ // 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 :-)
+ } // TODO the best would be to remove the empty root node, but this would
+ // require a understanding and reworking of the PHPDBGEvalstring class.
+ }
return DBGVarList; // Return the variables as list
}
@@ -587,14 +490,17 @@ public class PHPDBGInterface {
// Add command data
DBGPacket.addFrame(DBGFrame1);
- if(proxy.getSocket().isClosed()) return;
+ if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication?
+ return; // No, then leave here
+ }
+
DBGPacket.sendPacket(os);
waitResponse(1000);
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);
@@ -613,7 +519,9 @@ public class PHPDBGInterface {
// Add command data
DBGPacket.addFrame(DBGFrame1);
- if(proxy.getSocket().isClosed()) return null;
+ if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication?
+ return null; // No, then leave here
+ }
DBGPacket.sendPacket(os);
waitResponse(1000);
@@ -703,6 +611,10 @@ public class PHPDBGInterface {
toRead = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4); // The size of the string
+ 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;
@@ -715,6 +627,75 @@ 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 ());
+ 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.
@@ -724,10 +705,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.
*
*
@@ -744,21 +725,32 @@ 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); // ---
+ stackFrameOld = (PHPStackFrame) stackListOld.get (n); //
- if (stackFrameNew.getModNo () == stackFrameOld.getModNo ()) { // 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.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
}
}
@@ -766,14 +758,11 @@ public class PHPDBGInterface {
// 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);
+ stackFrameOld = (PHPStackFrame) stackListOld.get (n); //
- if (stackFrameNew.getModNo () == stackFrameOld.getModNo ()) { // 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
@@ -839,7 +828,7 @@ public class PHPDBGInterface {
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
@@ -891,10 +880,6 @@ public class PHPDBGInterface {
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;
@@ -932,11 +917,6 @@ public class PHPDBGInterface {
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,
@@ -1021,10 +1001,6 @@ public class PHPDBGInterface {
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;
@@ -1074,6 +1050,7 @@ public class PHPDBGInterface {
case PHPDBGBase.DBGC_END:
sessionEnded = true;
+ this.proxy.setTerminated();
break;
case PHPDBGBase.DBGC_BREAKPOINT: