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 4da1970..d2262ae 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 @@ -32,42 +32,47 @@ 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(); + 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 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 Vector DBGMods = new Vector(); // The module names and their numbers + private Vector stackListOld = new Vector(); + private BufferedReader dbgInput; + private OutputStream dbgOutput; // 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; // If we the debugger should be relaunched after script termination + private boolean bRelaunch = true; + private char[] lastCommand = new char[4]; + private boolean bBusy = false; + private boolean bDebug = true; // Prints text to console for debugging purposes private static final String GlobalVariablesTitle = PHPDebugCorePlugin .getResourceString("VariablesView.GlobalVariables.title"); /** - * @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. + * @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. + * @param bRelaunch The debugger should be relaunched after PHP script termination */ - public PHPDBGInterface (BufferedReader in, OutputStream os, PHPDBGProxy proxy) { + public PHPDBGInterface (BufferedReader in, OutputStream os, PHPDBGProxy proxy, boolean bRelaunch) { DBGBPList.clear (); - this.in = in; - this.os = os; - this.proxy = proxy; + this.dbgInput = in; + this.dbgOutput = os; + this.proxy = proxy; + this.bRelaunch = bRelaunch; } /** @@ -120,16 +125,26 @@ public class PHPDBGInterface { PHPDBGPacket DBGPacket; // A DBG message packet PHPDBGFrame DBGFrame; // A frame within a DBG packet + while (bBusy) { + } + + bBusy = true; + + if (bDebug) { + System.out.println ("PHPDBGInterface: getSourceTree"); + } + 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? + bBusy = false; return; // No } - DBGPacket.sendPacket (os); // Send the request to DBG + DBGPacket.sendPacket (dbgOutput); // Send the request to DBG waitResponse (1000); // Wait for the DBG response (1 second) flushAllPackets (); // Read and process the response from DBG @@ -183,6 +198,15 @@ public class PHPDBGInterface { PHPDBGFrame DBGFrame3; int modNo; + while (bBusy) { + } + + bBusy = true; + + if (bDebug) { + System.out.println ("PHPDBGInterface: setBreakpoint"); + } + DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_BPS); DBGFrame2 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA); @@ -240,10 +264,11 @@ public class PHPDBGInterface { DBGPacket.addFrame (DBGFrame1); // Second add command data if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? + bBusy = false; return 0; // No } - DBGPacket.sendPacket (os); // Send the request to DBG + DBGPacket.sendPacket (dbgOutput); // Send the request to DBG clearLastBP (); @@ -281,13 +306,17 @@ public class PHPDBGInterface { public void continueExecution () throws IOException { PHPDBGPacket DBGPacket; + if (bDebug) { + System.out.println ("PHPDBGInterface: continueExecution"); + } + 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 + DBGPacket.sendPacket (dbgOutput); // Send the request to DBG lastCommand = PHPDBGBase.DBGA_CONTINUE; // Store the info about the command we sent } @@ -298,13 +327,17 @@ public class PHPDBGInterface { public void pauseExecution () throws IOException { PHPDBGPacket DBGPacket; + if (bDebug) { + System.out.println ("PHPDBGInterface: pauseExecution"); + } + 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 + DBGPacket.sendPacket (dbgOutput); // Send the request to DBG } /** @@ -344,55 +377,106 @@ public class PHPDBGInterface { /** * */ - public void stepInto () throws IOException { + public boolean stepInto () throws IOException { PHPDBGPacket DBGPacket; + if (bBusy) { + if (bDebug) { + System.out.println ("PHPDBGInterface: stepOver vetoed"); + } + } + + while (bBusy) { + } + + bBusy = true; + + if (bDebug) { + System.out.println ("PHPDBGInterface: stepInto"); + } + BPUnderHit = 0; DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPINTO); if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? - return; // No + return false; // No } - DBGPacket.sendPacket (os); // Send the request to DBG + DBGPacket.sendPacket (dbgOutput); // Send the request to DBG lastCommand = PHPDBGBase.DBGA_STEPINTO; // Store the info about the command we sent + + return true; } /** * */ - public void stepOver () throws IOException { + public boolean stepOver () throws IOException { PHPDBGPacket DBGPacket; + if (bBusy) { + if (bDebug) { + System.out.println ("PHPDBGInterface: stepOver vetoed"); + } + } + + while (bBusy) { + } + + bBusy = true; + + if (bDebug) { + System.out.println ("PHPDBGInterface: stepOver"); + } + BPUnderHit = 0; DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOVER); if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? - return; // No + return false; // No } - DBGPacket.sendPacket (os); // Send the request to DBG + DBGPacket.sendPacket (dbgOutput); // Send the request to DBG lastCommand = PHPDBGBase.DBGA_STEPOVER; // Store the info about the command we sent + + return true; } /** * */ - public void stepOut () throws IOException { + public boolean stepOut () throws IOException { PHPDBGPacket DBGPacket; + if (bBusy) { + if (bDebug) { + System.out.println ("PHPDBGInterface: stepOver vetoed"); + } + } + + while (bBusy) { + } + + bBusy = true; + + if (bDebug) { + System.out.println ("PHPDBGInterface: stepOut"); + } + BPUnderHit = 0; DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOUT); if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? - return; // No + return false; // No } - DBGPacket.sendPacket (os); // Send the request to DBG + DBGPacket.sendPacket (dbgOutput); // Send the request to DBG lastCommand = PHPDBGBase.DBGA_STEPOUT; // Store the info about the command we sent + + return true; } /** @@ -423,6 +507,7 @@ public class PHPDBGInterface { public synchronized Vector getVariables(PHPStackFrame stack) throws IOException, DebugException { if (DBGStackList.length == 0) { DBGVarList.clear(); + return DBGVarList; } @@ -433,6 +518,7 @@ public class PHPDBGInterface { // Also note that 2.13.1 doesn't return $this in class context. // (You can inspect $this in Expressions View. And once it is shown, 2.13.1 comes to return $this.) Vector globalList = getVariables(DBGStackList[DBGStackList.length - 1], global_scope_id); + if (!globalList.isEmpty()) { // remove unresolved '$this=?' variable removeUnresolvedThisVar(globalList); @@ -443,20 +529,22 @@ public class PHPDBGInterface { } int scopeID = stack.getScopeID(); - if (!globalList.isEmpty() - && ((DBGStackList.length == 1) - || (scopeID == PHPDBGBase.CURLOC_SCOPE_ID + 1))) { + + 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; + PHPValue val = (PHPValue) var.getValue(); + + DBGVarList = val.getChildVariables(); - } else if (scopeID == PHPDBGBase.CURLOC_SCOPE_ID) { + return DBGVarList; + } + else if (scopeID == PHPDBGBase.CURLOC_SCOPE_ID) { // current stackframe DBGVarList = getVariables(stack, PHPDBGBase.CURLOC_SCOPE_ID); - - } else { + } + else { // back-trace stackframe //DBGVarList = getVariables(stack, scopeID); //removeUnresolvedThisVar(DBGVarList); @@ -489,12 +577,27 @@ public class PHPDBGInterface { } /** - * + * */ private Vector getVariables(PHPStackFrame stack, int scope_id) throws IOException { PHPDBGPacket DBGPacket = new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); PHPDBGFrame DBGFrame1 = new PHPDBGFrame(PHPDBGBase.FRAME_EVAL); + if (bBusy) { + if (bDebug) { + System.out.println ("PHPDBGInterface: getVariables vetoed"); + } + } + + while (bBusy) { + } + + bBusy = true; + + if (bDebug) { + System.out.println ("PHPDBGInterface: getVariables"); + } + DBGFrame1.addInt(0); DBGFrame1.addInt(scope_id); @@ -502,36 +605,44 @@ public class PHPDBGInterface { evalRet = ""; if (proxy.getSocket().isClosed()) { + bBusy = false; return new Vector(); } - DBGPacket.sendPacket(os); + + DBGPacket.sendPacket(dbgOutput); waitResponse(1000); flushAllPackets(); + bBusy = false; // Already done in flushAllPackets () + PHPDBGEvalString evalStr = new PHPDBGEvalString(stack, evalRet); return evalStr.getVariables(); } /** * Remove unresolved $this variable - * + * * DBG returns $this=? in function's or intermediate stackframes. * (In current method's stackframe, DBG returns $this=classname) - * + * * @param varList */ private void removeUnresolvedThisVar(Vector varList) { if (varList.size() > 0) { - PHPVariable var = (PHPVariable) varList.get(0); - PHPValue val = (PHPValue) var.getValue(); - Vector workList = val.getChildVariables(); + PHPVariable var = (PHPVariable) varList.get(0); + PHPValue val = (PHPValue) var.getValue(); + Vector workList = val.getChildVariables (); + for (int i = 0; i < workList.size(); i++) { PHPVariable workvar = (PHPVariable) workList.get(i); - if (workvar.getName().equals("$this")) { - String workval = ((PHPValue) workvar.getValue()).getValueString(); - if (workval.equals("?") || workval.equals("NULL")) { - workList.remove(i); + + if (workvar.getName().equals ("$this")) { + String workval = ((PHPValue) workvar.getValue ()).getValueString (); + + if (workval.equals ("?") || + workval.equals ("NULL")) { + workList.remove (i); } break; } @@ -548,6 +659,15 @@ public class PHPDBGInterface { PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_LOG); PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA); + while (bBusy) { + } + + bBusy = true; + + if (bDebug) { + System.out.println ("PHPDBGInterface: log"); + } + rawCounter++; DBGFrame1.addInt(rawCounter); // ilog DBGFrame1.addInt(1); // type @@ -567,10 +687,11 @@ public class PHPDBGInterface { DBGPacket.addFrame(DBGFrame1); if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication? + bBusy = false; return; // No, then leave here } - DBGPacket.sendPacket(os); + DBGPacket.sendPacket(dbgOutput); waitResponse(1000); flushAllPackets(); @@ -581,6 +702,15 @@ public class PHPDBGInterface { PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL); PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA); + while (bBusy) { + } + + bBusy = true; + + if (bDebug) { + System.out.println ("PHPDBGInterface: evalBlock"); + } + rawCounter++; DBGFrame1.addInt(rawCounter); // istr = raw data ID //DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth @@ -603,9 +733,11 @@ public class PHPDBGInterface { DBGPacket.addFrame(DBGFrame1); if (proxy.getSocket().isClosed()) { // Do we have a socket for DBG communication? + bBusy = false; return null; // No, then leave here } - DBGPacket.sendPacket(os); + + DBGPacket.sendPacket(dbgOutput); waitResponse(1000); flushAllPackets(); @@ -743,6 +875,7 @@ public class PHPDBGInterface { 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 } } @@ -773,7 +906,7 @@ public class PHPDBGInterface { if (isStackFrameInList (stackFrameNew, oldList)) { // Is this stackframe in the list stackFrameNew.setAvailable (true); // // - break; +// break; } } } @@ -808,6 +941,10 @@ public class PHPDBGInterface { PHPStackFrame stackFrameOld; PHPStackFrame[] newStackList; + if (bDebug) { + System.out.println ("PHPDBGInterface: updateStackFrameList Start"); + } + markIdenticalStackFrames (stackListOld, stackList); // Check whether the newly send stack frames can be found in the list // of old stack frames @@ -854,6 +991,10 @@ public class PHPDBGInterface { newStackList = new PHPStackFrame[stackListOld.size ()]; newStackList = (PHPStackFrame[]) stackListOld.toArray (newStackList); DBGStackList = newStackList; + + if (bDebug) { + System.out.println ("PHPDBGInterface: updateStackFrameList End"); + } } /** @@ -880,6 +1021,10 @@ public class PHPDBGInterface { Vector rawList = new Vector(); Vector stackList = new Vector(); // Intermediate stacklist which is build up in FRAME_STACK frame + if (bDebug) { + System.out.println ("PHPDBGInterface: readResponse start"); + } + rawList.clear (); stackList.clear (); @@ -891,6 +1036,11 @@ public class PHPDBGInterface { 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 + if (bDebug) { + System.out.println ("PHPDBGInterface: readResponse. Wrong sync"); + } + + bBusy = false; return 0; // Wrong header } @@ -903,10 +1053,15 @@ public class PHPDBGInterface { if (bytesToRead > 0) { // If there is something within the frame if (readInput (entirePack, bytesToRead) < bytesToRead) { // Read the frame into the buffer + if (bDebug) { + System.out.println ("PHPDBGInterface: readResponse. Did not read enough"); + } + + bBusy = false; 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 @@ -915,6 +1070,11 @@ public class PHPDBGInterface { nextFrame += 8; // The next read position if (dbg_frame[1] == 0) { // Something within the frame? + if (bDebug) { + System.out.println ("PHPDBGInterface: readResponse. Nothing within the frame"); + } + + bBusy = false; return 0; // Nothing to read, error } @@ -1127,8 +1287,15 @@ public class PHPDBGInterface { break; case PHPDBGBase.DBGC_END: - sessionEnded = true; - this.proxy.setTerminated(); + if (bRelaunch) { + continueExecution (); // Inform dbg that we want to continue execution + proxy.updateView (); // Sent a change event and create thread event to eclipse core + updateStackFrameList (stackList); // ??? Just a try + } + else { + sessionEnded = true; + proxy.setTerminated (); + } break; case PHPDBGBase.DBGC_BREAKPOINT: @@ -1158,6 +1325,12 @@ public class PHPDBGInterface { } } + if (bDebug) { + System.out.println ("PHPDBGInterface: readResponse finish, received: " + cmdReceived); + } + + bBusy = false; + return cmdReceived; // Return the command we received with this block } @@ -1179,14 +1352,51 @@ public class PHPDBGInterface { */ private int readInput (char[] buffer, int bytes) throws IOException { int bytesRead = 0; // Reset the bytes read counter + int nRetry = 0; // Retry counter + + if (bDebug) { + System.out.println ("PHPDBGInterface: readInput " + bytes); + } - 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 + for (int i = 0; i < bytes;) { // For the number of bytes we should read + if (dbgInput.ready ()) { // If input stream is ready for reading + nRetry = 0; // Reset the retry counter + buffer[i] = (char) (dbgInput.read () & 0x00FF); // Read a char and store only the least significant 8-bits bytesRead++; // Increment the bytes read counter + i++; } else { // Input stream is not ready - break; // Break the loop + nRetry++; // Increment the retry counter + + if (nRetry > 10) { // If nothing received within 100 retries + if (i > 0) { + if (bDebug) { + System.out.println ("PHPDBGInterface: Too many retries without receiving something"); + } + } + break; // we break the loop + } + + synchronized (dbgInput) { + if (i > 0) { + if (bDebug) { + System.out.println ("PHPDBGInterface: retry: " + nRetry + " Wait for something to receive, received: " + i + " need " + bytes); + } + } + try { + dbgInput.wait (10); // wait 5 ms maximum for something to receive + } catch (InterruptedException e) { + } + } + } + } + + if (bytesRead > 0) { + if (bytes != bytesRead) { + if (bDebug) { + System.out.println ("PHPDBGInterface: readInput: Possible error: not enough bytes in buffer should read: " + bytes + + " actually read: " + bytesRead); + } } } @@ -1207,18 +1417,33 @@ public class PHPDBGInterface { * @return - true if something was received from DBG * - false if nothing was send from DBG within the given time * + * This method has been a busy wait loop. It was changed to use + * a non busy wait to avoid a heavy load after automatic relaunch + * after script termination + * */ public boolean waitResponse (long milliseconds) throws IOException { long timeout; + if (bDebug) { + System.out.println ("PHPDBGInterface: waitResponse " + milliseconds); + } + 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 + synchronized (dbgInput) { + try { + dbgInput.wait (5); // wait 5 ms maximum for something to receive + } catch (InterruptedException e) { + } + } + + if (dbgInput.ready () || shouldStop) { // If something is received of if we should stop now + break; // break the waiting loop } } - return in.ready (); // true if we got something from DBG + return dbgInput.ready (); // true if we got something from DBG } }