From e75c3554f466e5265db461ad7f26972d046725bb Mon Sep 17 00:00:00 2001 From: axelcl Date: Sat, 15 Oct 2005 20:36:00 +0000 Subject: [PATCH] Patches from Robert Kraske (robekras): * collapsing variable tree * more documentation --- net.sourceforge.phpeclipse.debug.core/build.xml | 143 ++-- .../phpdt/internal/debug/core/PHPDBGBase.java | 217 +++-- .../phpdt/internal/debug/core/PHPDBGFrame.java | 135 ++- .../phpdt/internal/debug/core/PHPDBGInterface.java | 1270 +++++++++++++------- .../phpdt/internal/debug/core/PHPDBGPacket.java | 62 +- .../phpdt/internal/debug/core/PHPDBGProxy.java | 1039 +++++++++------- .../debug/core/model/PHPDBGEvalString.java | 144 ++- .../internal/debug/core/model/PHPStackFrame.java | 180 ++- .../phpdt/internal/debug/core/model/PHPThread.java | 266 +++-- .../phpdt/internal/debug/core/model/PHPValue.java | 172 ++- .../internal/debug/core/model/PHPVariable.java | 205 ++-- 11 files changed, 2409 insertions(+), 1424 deletions(-) diff --git a/net.sourceforge.phpeclipse.debug.core/build.xml b/net.sourceforge.phpeclipse.debug.core/build.xml index 1ed78e0..e205d70 100644 --- a/net.sourceforge.phpeclipse.debug.core/build.xml +++ b/net.sourceforge.phpeclipse.debug.core/build.xml @@ -1,17 +1,24 @@ - + + + + + + + + @@ -28,6 +35,7 @@ + @@ -37,74 +45,65 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + + + @@ -113,17 +112,17 @@ - - + + - + - + @@ -139,11 +138,11 @@ - - + + - + @@ -152,28 +151,28 @@ - - - + + + - - + + - - + + - + @@ -191,7 +190,7 @@ - + diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGBase.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGBase.java index f72c52a..f814943 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGBase.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGBase.java @@ -14,56 +14,56 @@ public class PHPDBGBase { // Constants // php-engine commands/events - public static final int DBGC_REPLY = 0x0000; /* reply to previous DBGA_REQUEST request */ - public static final int DBGC_STARTUP = 0x0001; /* script startup */ - public static final int DBGC_END = 0x0002; /* script done */ - public static final int DBGC_BREAKPOINT = 0x0003; /* user definded breakpoint occured */ - public static final int DBGC_STEPINTO_DONE = 0x0004; /* step to the next statement is completed */ - public static final int DBGC_STEPOVER_DONE = 0x0005; /* step to the next statement is completed */ - public static final int DBGC_STEPOUT_DONE = 0x0006; /* step to the next statement is completed */ - public static final int DBGC_EMBEDDED_BREAK = 0x0007; /* breakpoint caused by DebugBreak() function */ - public static final int DBGC_ERROR = 0x0010; /* error occured */ - public static final int DBGC_LOG = 0x0011; /* logging support */ - public static final int DBGC_SID = 0x0012; /* send SID */ - public static final int DBGC_PAUSE = 0x0013; /* pause current session as soon as possible */ - - public static final char[] DBGA_CONTINUE = IntToChar4(0x8001); /* php should continue run */ - public static final char[] DBGA_STOP = IntToChar4(0x8002); - public static final char[] DBGA_STEPINTO = IntToChar4(0x8003); - public static final char[] DBGA_STEPOVER = IntToChar4(0x8004); - public static final char[] DBGA_STEPOUT = IntToChar4(0x8005); - public static final char[] DBGA_IGNORE = IntToChar4(0x8006); - public static final char[] DBGA_REQUEST = IntToChar4(0x8010); /* debugger client requests some information from PHP engine */ - - public static final int FRAME_STACK = 100000; /* "call:stack" - e.g. backtrace */ - public static final int FRAME_SOURCE = 100100; /* source text */ - public static final int FRAME_SRC_TREE = 100200; /* tree of source files */ - public static final int FRAME_RAWDATA = 100300; /* raw data or string */ - public static final int FRAME_ERROR = 100400; /* error notification */ - public static final int FRAME_EVAL = 100500; /* evaluating/watching */ - public static final int FRAME_BPS = 100600; /* set/remove breakpoint */ - public static final int FRAME_BPL = 100700; /* breakpoint(s) request = get the list */ - public static final int FRAME_VER = 100800; /* version request */ - public static final int FRAME_SID = 100900; /* session id info*/ - public static final int FRAME_SRCLINESINFO = 101000; /* source lines info */ - public static final int FRAME_SRCCTXINFO = 101100; /* source contexts info */ - public static final int FRAME_LOG = 101200; /* logging */ - public static final int FRAME_PROF = 101300; /* profiler */ - public static final int FRAME_PROF_C = 101400; /* profiler counter/accuracy */ - public static final int FRAME_SET_OPT = 101500; /* set/update options */ - - public static final char[] DBGSYNC = { 0, 0, (char) 89, (char) 83}; /* DBG syncronization chars */ + public static final int DBGC_REPLY = 0x0000; // reply to previous DBGA_REQUEST request + public static final int DBGC_STARTUP = 0x0001; // script startup + public static final int DBGC_END = 0x0002; // script done + public static final int DBGC_BREAKPOINT = 0x0003; // user definded breakpoint occured + public static final int DBGC_STEPINTO_DONE = 0x0004; // step to the next statement is completed + public static final int DBGC_STEPOVER_DONE = 0x0005; // step to the next statement is completed + public static final int DBGC_STEPOUT_DONE = 0x0006; // step to the next statement is completed + public static final int DBGC_EMBEDDED_BREAK = 0x0007; // breakpoint caused by DebugBreak() function + public static final int DBGC_ERROR = 0x0010; // error occured + public static final int DBGC_LOG = 0x0011; // logging support + public static final int DBGC_SID = 0x0012; // send SID + public static final int DBGC_PAUSE = 0x0013; // pause current session as soon as possible + + public static final char[] DBGA_CONTINUE = IntToChar4(0x8001); // php should continue run + public static final char[] DBGA_STOP = IntToChar4(0x8002); + public static final char[] DBGA_STEPINTO = IntToChar4(0x8003); + public static final char[] DBGA_STEPOVER = IntToChar4(0x8004); + public static final char[] DBGA_STEPOUT = IntToChar4(0x8005); + public static final char[] DBGA_IGNORE = IntToChar4(0x8006); + public static final char[] DBGA_REQUEST = IntToChar4(0x8010); // debugger client requests some information from PHP engine + + public static final int FRAME_STACK = 100000; // "call:stack" - e.g. backtrace + public static final int FRAME_SOURCE = 100100; // source text + public static final int FRAME_SRC_TREE = 100200; // tree of source files + public static final int FRAME_RAWDATA = 100300; // raw data or string + public static final int FRAME_ERROR = 100400; // error notification + public static final int FRAME_EVAL = 100500; // evaluating/watching + public static final int FRAME_BPS = 100600; // set/remove breakpoint + public static final int FRAME_BPL = 100700; // breakpoint(s) request = get the list + public static final int FRAME_VER = 100800; // version request + public static final int FRAME_SID = 100900; // session id info + public static final int FRAME_SRCLINESINFO = 101000; // source lines info + public static final int FRAME_SRCCTXINFO = 101100; // source contexts info + public static final int FRAME_LOG = 101200; // logging + public static final int FRAME_PROF = 101300; // profiler + public static final int FRAME_PROF_C = 101400; // profiler counter/accuracy + public static final int FRAME_SET_OPT = 101500; // set/update options + + public static final char[] DBGSYNC = { 0, 0, (char) 89, (char) 83}; // DBG syncronization chars // Session Types - public static final int DBG_COMPAT = 0x0001; - public static final int DBG_JIT = 0x0002; - public static final int DBG_REQ = 0x0003; - public static final int DBG_EMB = 0x0004; - - public static final int BPS_DELETED = 0; - public static final int BPS_DISABLED = 1; - public static final int BPS_ENABLED = 2; - public static final int BPS_UNRESOLVED = 0x100; + public static final int DBG_COMPAT = 0x0001; + public static final int DBG_JIT = 0x0002; + public static final int DBG_REQ = 0x0003; + public static final int DBG_EMB = 0x0004; + + public static final int BPS_DELETED = 0; + public static final int BPS_DISABLED = 1; + public static final int BPS_ENABLED = 2; + public static final int BPS_UNRESOLVED = 0x100; public static final int E_ERROR = (1<<0L); public static final int E_WARNING = (1<<1L); @@ -80,58 +80,115 @@ public class PHPDBGBase { public PHPDBGBase() { } - public static void copyCharsTo(char[] to, char[] from, int bytes, int tostart) { + + /** + * Copies the number of bytes from a source buffer to a destination buffer + * Destination index starts with 0 + tostart, + * and source index starts with 0. + * + * @param to The destination buffer. + * @param from The source buffer. + * @param bytes The number of bytes which are to copy. + * @param tostart The start index for the destination buffer. + */ + public static void copyCharsTo (char[] to, char[] from, int bytes, int tostart) { int i; - for(i=0; i < bytes; i++) to[i + tostart]= from[i]; + + for (i = 0; i < bytes; i++) { // For the number of bytes which are to copy + to[i + tostart] = from[i]; // Copy from destination to source (+startindex) + } } - public static void copyChars(char[] to, char[] from, int bytes) { - copyCharsTo(to, from, bytes, 0); + /** + * Copies the number of bytes from a source buffer to a destination buffer + * Destination index starts with 0, + * and source index starts with 0. + * + * @param to The destination buffer. + * @param from The source buffer. + * @param bytes The number of bytes which are to copy. + */ + public static void copyChars (char[] to, char[] from, int bytes) { + copyCharsTo (to, from, bytes, 0); } - public static int Char4ToInt(char[] ch, int startPos) { - int pos=startPos, ret=0; - - ret += CharToInt(ch[pos++]) << 24; - ret += CharToInt(ch[pos++]) << 16; - ret += CharToInt(ch[pos++]) << 8; - ret += CharToInt(ch[pos++]) << 0; + /** + * Converts a four chars big endian value into + * an integer value + * + * @param ch The buffer which contains the four chars which are to convert. + * @param startPos The start position (of the four bytes) within the buffer. + */ + public static int Char4ToInt (char[] ch, int startPos) { + int pos = startPos; + int ret = 0; + + ret += CharToInt (ch[pos++]) << 24; + ret += CharToInt (ch[pos++]) << 16; + ret += CharToInt (ch[pos++]) << 8; + ret += CharToInt (ch[pos++]) << 0; + return ret; } - public static int CharToInt(char ch) { + /** + * @return The character which is converted to an integer value. + */ + public static int CharToInt (char ch) { return (int) (ch & 0x00FF); } - public static char[] IntToChar4(int num) { - char[] ret= new char[4]; - + /** + * Converts an integer value into a four char big endian number + * + * @param num The integer value which is to convert to a four char big endian number. + * @return The four byte buffer with the big endian number. + */ + public static char[] IntToChar4 (int num) { + char[] ret = new char[4]; + ret[0] = (char) ((num >> 24) & 0x00FF); ret[1] = (char) ((num >> 16) & 0x00FF); - ret[2] = (char) ((num >> 8) & 0x00FF); - ret[3] = (char) ((num >> 0) & 0x00FF); + ret[2] = (char) ((num >> 8) & 0x00FF); + ret[3] = (char) ((num >> 0) & 0x00FF); return ret; } - public static String CharArrayToString(char[] cha) { - String ret= new String(); - int i, p; - - for(i=0; i < cha.length; i++) { - p= (int) cha[i]; - ret= ret + "(" + String.valueOf(p) + ") "; + /** + * Converts the chars of an array into a string in form of + * (byte value string) (byte value string) (byte value string) ... + * + * @param cha The input buffer which contains the chars which are to convert. + * @return The string which contains the bytes as strings. + * E.g.: (123) (11) (46) (213) ... + */ + public static String CharArrayToString (char[] cha) { + String ret = new String (); + int i; + int p; + + for (i = 0; i < cha.length; i++) { // For all bytes within the input buffer + p = (int) cha[i]; // Convert the byte into an integer value + ret = ret + "(" + String.valueOf (p) + ") "; // Add the value } + return ret; } - - public static byte[] CharArrayToByteArray(char[] cha) { - byte[] ret= new byte[cha.length]; - int i; - - for(i=0; i < cha.length; i++) { - ret[i]= (byte) cha[i]; + + /** + * + * @param cha The input buffer which contains the chars which are to convert. + * @return The byte array which contains the converted chars. + */ + public static byte[] CharArrayToByteArray (char[] cha) { + byte[] ret = new byte[cha.length]; // The resulting byte array + int i; // The index for the buffers + + for (i = 0; i < cha.length; i++) { // For all chars within the input buffer + ret[i] = (byte) cha[i]; // Convert the character to a byte and store to buffer } - return ret; + + return ret; // Return the byte array } } diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGFrame.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGFrame.java index 6e9b777..15b1ffb 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGFrame.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGFrame.java @@ -14,67 +14,114 @@ import java.util.Vector; public class PHPDBGFrame { - public static final int FRAME_HEADER_SIZE= 8; - private char[] frameType= new char[4]; - private Vector frameData= new Vector(); - private int frameSize= 0; - - public PHPDBGFrame(int frameType) { - this.frameType= PHPDBGBase.IntToChar4(frameType); - frameSize+= FRAME_HEADER_SIZE; + public static final int FRAME_HEADER_SIZE = 8; // Header consist of 4 byte frame type and 4 byte frame length + private char[] frameType = new char[4]; + private Vector frameData = new Vector (); + private int frameSize = 0; + + /** + * Construct a new frame. + * + * @param frameType The type of the frame which is created. + */ + public PHPDBGFrame (int frameType) { + this.frameType = PHPDBGBase.IntToChar4 (frameType); + frameSize += FRAME_HEADER_SIZE; } - - public void addInt(int num) { - char[] newData= PHPDBGBase.IntToChar4(num); - frameData.add(newData); - frameSize+= 4; + + /** + * Add an integer to the frame. + * + * @param num + */ + public void addInt (int num) { + char[] newData = PHPDBGBase.IntToChar4 (num); // Convert the integer to four bytes big endian + frameData.add (newData); // Add the four bytes to the frame data + frameSize += 4; // Calculate the new fram size } - public void addChar(char ch) { - char[] newData= new char[1]; - newData[0]= ch; - frameData.add(newData); - frameSize+= 1; + /** + * Add a character to the frame. + * + * @param ch The character which is to add to the frame. + */ + public void addChar (char ch) { + char[] newData = new char[1]; + + newData[0] = ch; // + frameData.add (newData); // Add the character to the frame data + frameSize += 1; // Calculate the new fram size } - public void addString(String str) { - frameData.add(str); - frameSize+= str.length(); + /** + * @param str + */ + public void addString (String str) { + frameData.add (str); + frameSize += str.length (); } - public int getSize() { + /** + * Get the size of the frame, including the frame header. + * + * @return The size of the entire frame. + */ + public int getSize () { return frameSize; } - public int getSizeOfData() { + /** + * Return the size of the frame, which is the number of all bytes + * without the 8 byte from frame header. + * + * @return The size of the frame (without the frame header). + */ + public int getSizeOfData () { return frameSize - FRAME_HEADER_SIZE; } - public char[] getHeader() { - char[] ret= new char[FRAME_HEADER_SIZE]; + /** + * Get the header of this frame. + * + * @return The eight char array which forms the header of this frame. + */ + public char[] getHeader () { + char[] ret = new char[FRAME_HEADER_SIZE]; // Allocate 8 chars for the header - PHPDBGBase.copyChars(ret, frameType, 4); - PHPDBGBase.copyCharsTo(ret, PHPDBGBase.IntToChar4(getSizeOfData()), 4, 4); - return ret; + PHPDBGBase.copyChars (ret, frameType, 4); // The first four chars are the frame type + PHPDBGBase.copyCharsTo (ret, PHPDBGBase.IntToChar4 (getSizeOfData ()), 4, 4); // The second four chars is for the size of the data area + + return ret; // Return the header } - - public char[] getFrameData() { - char[] ret= new char[getSizeOfData()]; - int i, pos= 0; - - for(i=0; i < frameData.size(); i++) { - if(frameData.get(i).getClass().getName().equals("[C")) { - char[] conv= (char[])frameData.get(i); - PHPDBGBase.copyCharsTo(ret, conv, conv.length, pos); - pos+= conv.length; + + /** + * Get the data array of this frame + * + * TODO Finish commenting + * + * @return The char array which holds the data of this frame. + */ + public char[] getFrameData () { + char[] ret = new char[getSizeOfData ()]; // The frame data (data without the frame header) + int pos = 0; // The current position for the 'ret' array + int i; // The current position for the frame data list + + for (i = 0; i < frameData.size (); i++) { // For frame data entries within the list + if (frameData.get (i).getClass ().getName ().equals ("[C")) { // What kind of type is the frame data + char[] conv = (char[]) frameData.get (i); // + + PHPDBGBase.copyCharsTo (ret, conv, conv.length, pos); // + pos += conv.length; } else { - if(frameData.get(i).getClass().getName().equals("java.lang.String")) { - String conv= (String)frameData.get(i); - PHPDBGBase.copyCharsTo(ret, conv.toCharArray(), conv.length(), pos); - pos+= conv.length(); + if (frameData.get (i).getClass ().getName ().equals ("java.lang.String")) { // + String conv = (String) frameData.get (i); // + + PHPDBGBase.copyCharsTo (ret, conv.toCharArray (), conv.length (), pos); // + pos += conv.length (); // } } } - return ret; + + return ret; // Return the data frame array } -} \ No newline at end of file +} 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 ef96492..957c86e 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 @@ -19,262 +19,510 @@ 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 - public boolean sessionEnded= false; - public int sessType= -1; - public int BPUnderHit= 0; - public String sessID= new String(); - - // Private - private int[] LastBPRead= new int[10]; - private Vector DBGBPList= new Vector(); - private PHPStackFrame[] DBGStackList; - private PHPVariable[] DBGVariableList; - private Vector DBGMods= new Vector(); - private BufferedReader in; - private OutputStream os; - private boolean shouldStop= false; - private String evalRet= new String(""); - private String serGlobals= new String(""); - private int rawCounter=1000; - private PHPDBGProxy proxy= null; + public boolean sessionEnded = false; + public int sessType = -1; + public int BPUnderHit = 0; + public String sessID = new String (); - private int lastCmd=-1; - private int sid=0; - private boolean stopOnError= false; - private char[] lastCommand= new char[4]; - - public PHPDBGInterface(BufferedReader in, OutputStream os, PHPDBGProxy proxy) { - DBGBPList.clear(); - this.in= in; - this.os= os; - this.proxy= proxy; + 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; } - 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. + * @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 void removeBreakpoint(String mod_name, int line, int bpNo) throws IOException { - setBreakpoint(mod_name, "", line, PHPDBGBase.BPS_DISABLED, 0, 0, 0, bpNo, 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); } - public void requestDBGVersion() throws IOException { - PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); - PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_VER); - - DBGPacket.addFrame(DBGFrame); + /** + * Is this method used anywhere? + * + */ + public void requestDBGVersion () throws IOException { + PHPDBGPacket DBGPacket; // A DBG message packet + PHPDBGFrame DBGFrame; // A frame within a DBG packet - if(proxy.getSocket().isClosed()) return; - DBGPacket.sendPacket(os); - } + DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); // A request for DBG + DBGFrame = new PHPDBGFrame (PHPDBGBase.FRAME_VER); // We want the version of DBG - public void getSourceTree() throws IOException { - PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); - PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_SRC_TREE); - - DBGPacket.addFrame(DBGFrame); - - if(proxy.getSocket().isClosed()) return; - DBGPacket.sendPacket(os); + DBGPacket.addFrame (DBGFrame); // Add the 'what we want' to the DBG packet - // Wait response (1 second) and read response - waitResponse(1000); - flushAllPackets(); + if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? + return; // No + } + + DBGPacket.sendPacket (os); // Send the request to DBG } - public void addDBGModName(String modName) throws IOException { - PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); - PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA); - - rawCounter++; - DBGFrame.addInt(rawCounter); // FRAME_RAWDATA ID - DBGFrame.addInt(modName.length() + 1); // length of rawdata (+ null char) - DBGFrame.addString(modName); // file name - DBGFrame.addChar('\0'); // null char + /** + * Called by the proxy + * + */ + public void getSourceTree () throws IOException { + PHPDBGPacket DBGPacket; // A DBG message packet + PHPDBGFrame DBGFrame; // A frame within a DBG packet - DBGPacket.addFrame(DBGFrame); - - if(proxy.getSocket().isClosed()) return; - DBGPacket.sendPacket(os); + 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 } - // Returns DBG Breakpoint ID - private int setBreakpoint(String mod_name, String condition, int line, int state, int istemp, int hitcount, int skiphits, int bpno, int isunderhit) throws IOException { - int modNo= 0; + /** + * 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 - PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); - PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_BPS); - PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA); + 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); + } - modNo= getModByName(mod_name); - - if(modNo >= 0) { - DBGFrame1.addInt(modNo); // mod number + /** + * 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 (0); // mod number (0 use file name) } - - DBGFrame1.addInt(line); // line number - - if(modNo >= 0) { - DBGFrame1.addInt(0); // use mod number + + 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 (rawCounter); // ID of FRAME_RAWDATA to send file name } - DBGFrame1.addInt(state); // state BPS_* - DBGFrame1.addInt(istemp); // istemp - 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) { - 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 - // First add file name data - DBGPacket.addFrame(DBGFrame2); + 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 } - // Second add command data - DBGPacket.addFrame(DBGFrame1); + DBGPacket.addFrame (DBGFrame1); // Second add command data - if(proxy.getSocket().isClosed()) return 0; - DBGPacket.sendPacket(os); + if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? + return 0; // No + } - clearLastBP(); + DBGPacket.sendPacket (os); // Send the request to DBG - // Wait response (1 second) and read response - waitResponse(1000); - flushAllPackets(); + clearLastBP (); + + waitResponse (1000); // Wait for the DBG response (1 second) + flushAllPackets (); // Read and process the response from DBG - return LastBPRead[8]; + return LastBPRead[8]; // Return what ??? } - private void clearLastBP() { + /** + * + */ + private void clearLastBP () { int i; - for(i=0; i < LastBPRead.length; i++) - LastBPRead[i]= 0; + for (i = 0; i < LastBPRead.length; i++) { + LastBPRead[i] = 0; + } } - private void copyToLastBP(int[] BPBody) { + /** + * + */ + private void copyToLastBP (int[] BPBody) { int i; - for(i=0; i < LastBPRead.length; i++) - LastBPRead[i]= BPBody[i]; + for (i = 0; i < LastBPRead.length; i++) { + LastBPRead[i] = BPBody[i]; + } } - public void continueExecution() throws IOException { - BPUnderHit= 0; - PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_CONTINUE); - if(proxy.getSocket().isClosed()) return; - DBGPacket.sendPacket(os); - lastCommand= PHPDBGBase.DBGA_CONTINUE; + /** + * + */ + 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= new PHPDBGPacket(PHPDBGBase.IntToChar4(PHPDBGBase.DBGC_PAUSE)); - if(proxy.getSocket().isClosed()) return; - DBGPacket.sendPacket(os); + /** + * + */ + 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, BPUnder=0; - int[] dbg_bpl_body= new int[10]; + /** + * + */ + 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); - // look for bp under hit - for(i=0; i < DBGBPList.size(); i++) { - dbg_bpl_body= (int[]) DBGBPList.get(i); - if(dbg_bpl_body[9] == 1) { - BPUnder= dbg_bpl_body[8]; + 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) + } + + public void setLastCmd (int cmd) { - lastCmd=cmd; + lastCmd = cmd; } - public void stepInto() throws IOException { - BPUnderHit= 0; - PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPINTO); - if(proxy.getSocket().isClosed()) return; - DBGPacket.sendPacket(os); - lastCommand= PHPDBGBase.DBGA_STEPINTO; + /** + * + */ + 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 { - BPUnderHit= 0; - PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOVER); - if(proxy.getSocket().isClosed()) return; - DBGPacket.sendPacket(os); - lastCommand= PHPDBGBase.DBGA_STEPOVER; + /** + * + */ + 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 { - BPUnderHit= 0; - PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOUT); - if(proxy.getSocket().isClosed()) return; - DBGPacket.sendPacket(os); - lastCommand= PHPDBGBase.DBGA_STEPOUT; + /** + * + */ + 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 { - BPUnderHit= 0; - PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STOP); - if(proxy.getSocket().isClosed()) return; - DBGPacket.sendPacket(os); + /** + * + */ + 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 } - public PHPVariable[] getVariables(PHPStackFrame stack) throws IOException, DebugException { - PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); - PHPDBGFrame 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 - - // Add command data - DBGPacket.addFrame(DBGFrame1); - - if(proxy.getSocket().isClosed()) return null; - DBGPacket.sendPacket(os); + /** + * 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 + 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 + } - waitResponse(1000); - flushAllPackets(); - - // Process serialized variables - PHPDBGEvalString evalStr=new PHPDBGEvalString(stack,serGlobals); - - DBGVariableList= evalStr.getVars(); + 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 - return DBGVariableList; + 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); @@ -286,7 +534,7 @@ public class PHPDBGInterface { DBGFrame1.addInt(0); // mod_no DBGFrame1.addInt(0); // line_no DBGFrame1.addInt(0); // imod_name - DBGFrame1.addInt(0); // ext_info + DBGFrame1.addInt(0); // ext_info DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID DBGFrame2.addInt(logString.length() + 1); // length of rawdata (+ null char) @@ -297,7 +545,7 @@ public class PHPDBGInterface { DBGPacket.addFrame(DBGFrame2); // Add command data DBGPacket.addFrame(DBGFrame1); - + if(proxy.getSocket().isClosed()) return; DBGPacket.sendPacket(os); @@ -323,211 +571,326 @@ public class PHPDBGInterface { 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(); - - } - public void flushAllPackets() throws IOException { - while(readResponse() != 0); } - public String getModByNo(int modNo) { - int i; - PHPDBGMod dbg_mod; + /** + * Read and process everthing we got from DBG + */ + public void flushAllPackets () throws IOException { + while (readResponse() != 0); + } - // look for mod - for(i=0; i < DBGMods.size(); i++) { - dbg_mod= (PHPDBGMod) DBGMods.get(i); - if(dbg_mod.getNo() == modNo) { - return dbg_mod.getName(); + /** + * 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 ""; - } - private int getModByName(String modName) { - int i; - PHPDBGMod dbg_mod; + return ""; // If nothing was found return emtpy string + } - // look for mod - for(i=0; i < DBGMods.size(); i++) { - dbg_mod= (PHPDBGMod) DBGMods.get(i); - if(dbg_mod.getName().equalsIgnoreCase(modName)) { - return dbg_mod.getNo(); + /** + * + * @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; + + return -1; // If nothing was found return -1 } - private String getRawFrameData(char[] framesInfo, int frameNo) { - int nextFrame= 0; - int[] dbg_frame= new int[2]; - - while(nextFrame < framesInfo.length) { - dbg_frame[0] = PHPDBGBase.Char4ToInt(framesInfo, nextFrame); // frame name - dbg_frame[1] = PHPDBGBase.Char4ToInt(framesInfo, nextFrame + 4); // frame size + /** + * 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; // - nextFrame += 8; - if(dbg_frame[1] == 0) return ""; + toRead = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4); // The size of the string - switch(dbg_frame[0]) { - case PHPDBGBase.FRAME_RAWDATA: - if(frameNo == PHPDBGBase.Char4ToInt(framesInfo, nextFrame)) { - int toRead= PHPDBGBase.Char4ToInt(framesInfo, nextFrame + 4); - return String.copyValueOf(framesInfo, nextFrame + 8, toRead); + return String.copyValueOf (framesInfo, nextFrame + 8, toRead); // Copy frame content to String and return } break; } - // go to next frame - nextFrame += dbg_frame[1]; + + nextFrame += dbg_frame[1]; // Go for the next frame (add the length of the current one) } - return ""; - } - - - public int readResponse() throws IOException { - int bytesToRead=0, nextFrame=0, i=0, cmdReceived=0, stackIndex=0; - boolean errorStack= false; - char[] dbg_header_struct_read= new char[16]; - int[] dbg_header_struct= new int[4]; - 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(); + + 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; - - rawList.clear(); - stackList.clear(); + + 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) { - dbg_header_struct[0] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 0); - dbg_header_struct[1] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 4); - dbg_header_struct[2] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 8); - dbg_header_struct[3] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 12); - - // Check DBG sync bytes - if(dbg_header_struct[0] != 0x5953) return 0; - - cmdReceived= dbg_header_struct[1]; - setLastCmd(cmdReceived); - bytesToRead= dbg_header_struct[3]; + 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]; + char[] entirePack = new char[bytesToRead]; // Store the block data into buffer 'entirePack' - if(bytesToRead > 0) { - if(readInput(entirePack, bytesToRead) < bytesToRead) return 0; + 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 + } } - - // First process frames - nextFrame= 0; - while(nextFrame < bytesToRead) { - dbg_frame[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame); // frame name - dbg_frame[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // frame size - nextFrame += 8; - if(dbg_frame[1] == 0) return 0; - switch(dbg_frame[0]) { + + 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); // line no - dbg_stack_new[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // mod no - dbg_stack_new[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8); // scope id - dbg_stack_new[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12); // id of description string + 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; - if(dbg_stack_new[1] != 0 && !errorStack) { stackIndex++; - PHPStackFrame newStack= new PHPStackFrame(null, getModByNo(dbg_stack_new[1]), dbg_stack_new[0], stackIndex, getRawFrameData(entirePack, dbg_stack_new[3]), dbg_stack_new[1]); - stackList.add(newStack); + 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: + + errorStack = false; break; - case PHPDBGBase.FRAME_SRC_TREE: - dbg_src_tree_tmp[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); // parent_mod_no - dbg_src_tree_tmp[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // parent_line_no /* NOT USED */ - dbg_src_tree_tmp[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8); // mod_no - dbg_src_tree_tmp[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12); // imod_name - - if(getModByNo(dbg_src_tree_tmp[2]).equals("")) { - String fileName= new String(getRawFrameData(entirePack, dbg_src_tree_tmp[3])); - // Remove '\0' char - if(fileName.length() > 0) fileName= fileName.substring(0, fileName.length() - 1); - - if(dbg_src_tree_tmp[2] != 0) { - PHPDBGMod modNew= new PHPDBGMod(dbg_src_tree_tmp[2], fileName); - DBGMods.add(modNew); + + 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: - break; - case PHPDBGBase.FRAME_ERROR: - errorStack= true; - dbg_error_tmp[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); // type /* type of error */ - dbg_error_tmp[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // imessage /* ID of error message */ - - String error= "\n"; - switch(dbg_error_tmp[0]) { - 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; + + 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+= ": "; - error+= new String(getRawFrameData(entirePack, dbg_error_tmp[1])); - // Remove '\0' char - if(error.length() > 0) error= error.substring(0, error.length() - 1); - error+= "\n"; - PHPDebugCorePlugin.log(new DebugException(new Status(IStatus.WARNING, PHPDebugCorePlugin.PLUGIN_ID, IStatus.OK, error, null))); + 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 { @@ -535,158 +898,215 @@ public class PHPDBGInterface { // } catch (DebugException e) { // PHPDebugCorePlugin.log(e); // } - if(!stopOnError) { - if(lastCommand.equals(PHPDBGBase.DBGA_CONTINUE)) { - continueExecution(); - } else if(lastCommand.equals(PHPDBGBase.DBGA_STEPINTO)) { - stepInto(); - } else if(lastCommand.equals(PHPDBGBase.DBGA_STEPOUT)) { - stepOut(); - } else if(lastCommand.equals(PHPDBGBase.DBGA_STEPOVER)) { - stepOver(); +// + 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= 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: + 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= 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); - + 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); + 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); - + DBGBPList.add (dbg_bpl_new); + copyToLastBP (dbg_bpl_new); + // mod no returned? - if(getModByNo(dbg_bpl_new[0]).equals("")) { - String fileName= new String(getRawFrameData(entirePack, dbg_bpl_new[2])); - // Remove '\0' char - if(fileName.length() > 0) fileName= fileName.substring(0, fileName.length() - 1); - if(dbg_bpl_new[0] != 0) { - PHPDBGMod modNew= new PHPDBGMod(dbg_bpl_new[0], fileName); - DBGMods.add(modNew); + 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); + 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; } - // go to next frame - nextFrame += dbg_frame[1]; + + 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; + sessionEnded = true; break; + case PHPDBGBase.DBGC_BREAKPOINT: - newStackList= new PHPStackFrame[stackList.size()]; - newStackList= (PHPStackFrame[]) stackList.toArray(newStackList); - DBGStackList= newStackList; - BPUnderHit= getBPUnderHit(); + 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; - newStackList= new PHPStackFrame[stackList.size()]; - newStackList= (PHPStackFrame[]) stackList.toArray(newStackList); - DBGStackList= newStackList; + BPUnderHit = 1; + updateStackFrameList (stackList); break; + case PHPDBGBase.DBGC_ERROR: - stackList.clear(); - newStackList= new PHPStackFrame[stackList.size()]; - newStackList= (PHPStackFrame[]) stackList.toArray(newStackList); - DBGStackList= newStackList; + stackList.clear (); + updateStackFrameList (stackList); break; + case PHPDBGBase.DBGC_LOG: break; + case PHPDBGBase.DBGC_SID: break; } } - return cmdReceived; + + return cmdReceived; // Return the command we received with this block } + /** + * + */ + public PHPStackFrame[] getStackList() { return DBGStackList; } - private int readInput(char[] buffer, int bytes) throws IOException { - int bytesRead= 0; - - for(int i=0; i < bytes; i++) { - if(in.ready()) { - buffer[i]= (char) (in.read() & 0x00FF); - bytesRead++; + /** + * 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 } - else - break; } - return bytesRead; + + return bytesRead; // Return the number of bytes actually read } - - public void setShouldStop() { - this.shouldStop= true; + + /** + * PHPProxy could stop the waiting for a response with this method. + * + */ + public void setShouldStop () { + this.shouldStop = true; } - public boolean waitResponse(long milliseconds) throws IOException { - long timeout= System.currentTimeMillis() + milliseconds; - while(System.currentTimeMillis() < timeout) { - if(in.ready() || shouldStop) { - break; + /** + * @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(); + + return in.ready (); // true if we got something from DBG } } diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGPacket.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGPacket.java index 9c1c322..cbbcdbe 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGPacket.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGPacket.java @@ -15,42 +15,40 @@ import java.io.OutputStream; import java.util.Vector; public class PHPDBGPacket { - private static final int PACKET_HEADER_SIZE= 16; - private char[] packetHeader= new char[PACKET_HEADER_SIZE]; - private int packetSize; - private Vector frames= new Vector(); - - public PHPDBGPacket(char[] packetType) { - PHPDBGBase.copyChars(packetHeader, PHPDBGBase.DBGSYNC, 4); - PHPDBGBase.copyCharsTo(packetHeader, packetType, 4, 4); + private static final int PACKET_HEADER_SIZE = 16; + private char[] packetHeader = new char[PACKET_HEADER_SIZE]; + private int packetSize; + private Vector frames = new Vector (); + + public PHPDBGPacket (char[] packetType) { + PHPDBGBase.copyChars (packetHeader, PHPDBGBase.DBGSYNC, 4); + PHPDBGBase.copyCharsTo (packetHeader, packetType, 4, 4); } - public void addFrame(PHPDBGFrame frame) { - frames.add(frame); - packetSize+= frame.getSize(); + public void addFrame (PHPDBGFrame frame) { + frames.add (frame); + packetSize += frame.getSize (); } - - public void sendPacket(OutputStream out) throws IOException { - int i; + + public void sendPacket (OutputStream out) throws IOException { + int i; PHPDBGFrame frame; - - PHPDBGBase.copyCharsTo(packetHeader, PHPDBGBase.IntToChar4(packetSize), 4, 12); - - // Send packet header - out.write(PHPDBGBase.CharArrayToByteArray(packetHeader)); - out.flush(); - - // Send Frames - for(i=0; i < frames.size(); i++) { - // Header of frame - frame= (PHPDBGFrame)frames.get(i); - out.write(PHPDBGBase.CharArrayToByteArray(frame.getHeader())); - out.flush(); - if (frame.getSizeOfData() > 0) { - // Data of frame - out.write(PHPDBGBase.CharArrayToByteArray(frame.getFrameData())); - out.flush(); + + PHPDBGBase.copyCharsTo (packetHeader, PHPDBGBase.IntToChar4 (packetSize), 4, 12); + + out.write (PHPDBGBase.CharArrayToByteArray (packetHeader)); // Send packet header + out.flush (); // + + for (i = 0; i < frames.size (); i++) { // Send Frames + frame = (PHPDBGFrame) frames.get (i); // Header of frame + + out.write (PHPDBGBase.CharArrayToByteArray (frame.getHeader ())); // Convert the char buffer to a byte buffer and send + out.flush (); + + if (frame.getSizeOfData () > 0) { // If there is a data frame + out.write (PHPDBGBase.CharArrayToByteArray (frame.getFrameData ()));// Convert the data char buffer to a byte buffer and send + out.flush (); } } } -} \ No newline at end of file +} diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java index 0c30b77..db66060 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java @@ -32,454 +32,599 @@ import org.eclipse.debug.core.model.IBreakpoint; public class PHPDBGProxy { - private ServerSocket server = null; - - private Socket socket; - - private BufferedReader reader = null; - - private PHPDBGInterface DBGInt = null; - - private PHPDebugTarget debugTarget = null; - - private PHPLoop phpLoop; - - private PHPThread PHPMainThread; - - private PHPDBGProxy thisProxy = null; - - private int port; - - private boolean remote; - - private boolean pathtranslation; - - private Map pathmap; - - private IPath remoteSourcePath; - - public PHPDBGProxy() { - thisProxy = this; - } - - public PHPDBGProxy(boolean remote, String remoteSourcePath,boolean pathTranslate,Map paths) { - thisProxy = this; - this.remote = remote; - this.remoteSourcePath = new Path(remoteSourcePath); - this.pathmap=paths; - this.pathtranslation=pathTranslate; - } - - public void start() { - createServerSocket(); - this.startPHPLoop(); - } - - public void stop() { - phpLoop.setShouldStop(); - if (DBGInt != null) - DBGInt.setShouldStop(); - if (!remote) { - try { - getDebugTarget().getProcess().terminate(); - } catch (DebugException e) { - e.printStackTrace(); - } - } - phpLoop.notifyWait(); - } - - protected ServerSocket getServerSocket() throws IOException { - if (server == null) { - createServerSocket(); - } - return server; - } - - protected void createServerSocket() { - port = SocketUtil.findUnusedLocalPort("localhost", 10001, 10101); -// port = 10001; - if (port == -1) { - PHPDebugCorePlugin.log(5, "Cannot find free port!!!!"); - return; - } - try { - if (server == null) { - server = new ServerSocket(port); - //System.out.println("ServerSocket on port: " + port); - } - } catch (IOException e) { - // IO Error - PHPDebugCorePlugin.log(e); - stop(); - } - } - - public Socket getSocket() throws IOException { - return socket; - } - - protected void setDBGInterface(PHPDBGInterface DBGInt) { - this.DBGInt = DBGInt; - } - - public BufferedReader getReader() throws IOException { - if (reader == null) { - reader = new BufferedReader(new InputStreamReader(this.getSocket().getInputStream(), "ISO8859_1")); - } - return reader; - } - - public BufferedReader getReader(Socket socket) throws IOException { - if (socket != null) - return new BufferedReader(new InputStreamReader(socket.getInputStream(), "ISO8859_1")); - else - return null; - } - - public OutputStream getOutputStream() throws IOException { - return this.getSocket().getOutputStream(); - } - - protected void setBreakPoints() throws IOException, CoreException { - IBreakpoint[] breakpoints = DebugPlugin.getDefault() - .getBreakpointManager().getBreakpoints(); - for (int i = 0; i < breakpoints.length; i++) { - if (breakpoints[i].isEnabled()) { - addBreakpoint(breakpoints[i]); - } - } - } - - private String MapPath(PHPLineBreakpoint phpLBP) { - IPath filename; - if (remote) { - filename = phpLBP.getMarker().getResource() - .getProjectRelativePath(); - filename = remoteSourcePath.append(filename); - } else + private ServerSocket server = null; + private BufferedReader reader = null; + private PHPDBGInterface DBGInt = null; // The DBG interface which is linked with the proxy + private PHPDebugTarget debugTarget = null; + private PHPDBGProxy thisProxy = null; + private PHPLoop phpLoop; + private PHPThread PHPMainThread; + private Socket socket; + private int port; + private boolean remote; + private boolean pathtranslation; + private Map pathmap; + private IPath remoteSourcePath; + + /** + */ + public PHPDBGProxy () { + thisProxy = this; + } + + /** + * @param remote + * @param remoteSourcePath + * @param pathTranslate + * @param paths + */ + public PHPDBGProxy (boolean remote, String remoteSourcePath, boolean pathTranslate, Map paths) { + thisProxy = this; + this.remote = remote; + this.remoteSourcePath = new Path (remoteSourcePath); + this.pathmap = paths; + this.pathtranslation = pathTranslate; + } + + /** + * + */ + public void start () { + createServerSocket (); // Create a server socket for communicatio with DBG + + this.startPHPLoop (); // + } + + /** + * + */ + public void stop () { + phpLoop.setShouldStop (); // Notify the thread's 'run loop' to stop + + if (DBGInt != null) { // If we have a DBG interface linked with this proxy + DBGInt.setShouldStop (); // Notify the DBG interface to stop the waiting for response + } + + if (!remote) { // If it's not a remote proxy session + try { + getDebugTarget ().getProcess ().terminate (); // + } catch (DebugException e) { + e.printStackTrace (); + } + } + + phpLoop.notifyWait (); + } + + /** + * TODO Is this method called from anywhere? + * + * Returns a already created server socket, or + * creates a server socket if none exists, and + * returns the newly created one. + * + * @return A server socket + */ + protected ServerSocket getServerSocket () throws IOException { + if (server == null) { // Do we have already a server socket + createServerSocket (); // No, then create one + } + + return server; // Return the server socket + } + + /** + * + * TODO The example for setting up DBG within PHP.ini shows ports from 10000 to 10016 ??? + * if my interpretation is correct. + * How can we find the correct DBG port? + */ + protected void createServerSocket () { + port = SocketUtil.findUnusedLocalPort ("localhost", 10001, 10101); // Get the first free port in the range from 10001 to 10101 + +// port = 10001; + if (port == -1) { // Did we get a free port? + PHPDebugCorePlugin.log (5, "Cannot find free port!!!!"); // No, output a error message + + return; // And return + } + try { + if (server == null) { // If there is no server socket yet + server = new ServerSocket (port); // create a server socket for the free port + //System.out.println("ServerSocket on port: " + port); + } + } catch (IOException e) { + // IO Error + PHPDebugCorePlugin.log (e); + stop (); + } + } + + /** + * + */ + public Socket getSocket () throws IOException { + return socket; // Return the socket + } + + /** + * Set the DBG interface which is linked to this proxy + * + * @paran DBGInt The DGB interface which is linked with this proxy + */ + protected void setDBGInterface (PHPDBGInterface DBGInt) { + this.DBGInt = DBGInt; + } + + /** + * Give back a buffered input stream for the socket which is + * linked with this proxy + */ + public BufferedReader getReader () throws IOException { + if (reader == null) { // Do we already have a buffered input stream + reader = new BufferedReader (new InputStreamReader (this.getSocket ().getInputStream (), + "ISO8859_1")); + } + + return reader; // Return the buffered input stream + } + + /** + * + */ + public BufferedReader getReader (Socket socket) throws IOException { + if (socket != null) { // Is a socket provided + return new BufferedReader (new InputStreamReader (socket.getInputStream (), + "ISO8859_1")); // Then create a buffered input stream + } + else { + return null; // Without a socket we can't create a input stream + } + } + + /** + * + * @return The output stream for this proxy's socket + */ + public OutputStream getOutputStream () throws IOException { + return this.getSocket ().getOutputStream (); + } + + /** + * + */ + protected void setBreakPoints () throws IOException, CoreException { + IBreakpoint[] breakpoints = DebugPlugin.getDefault ().getBreakpointManager ().getBreakpoints (); + + for (int i = 0; i < breakpoints.length; i++) { + if (breakpoints[i].isEnabled ()) { + addBreakpoint (breakpoints[i]); + } + } + } + + /** + * + */ + private String MapPath (PHPLineBreakpoint phpLBP) { + IPath filename; + + if (remote) { + filename = phpLBP.getMarker().getResource().getProjectRelativePath(); + filename = remoteSourcePath.append (filename); + } else { filename = phpLBP.getMarker().getResource().getLocation(); - String path = filename.toOSString(); - if (pathmap != null && remote) { - java.util.Iterator i = pathmap.keySet().iterator(); - while (i.hasNext()) { - String k = (String) i.next(); - if (path.startsWith(k)) { - path = pathmap.get(k) + path.substring(k.length()); - break; - } - } } - if (pathtranslation && remote) { - if (remoteSourcePath.toString().substring(0, 1).equals("/")) - path = path.replace('\\', '/'); - else - path = path.replace('/', '\\'); - } - return path; - } - - public void addBreakpoint(IBreakpoint breakpoint) { - if (DBGInt == null) - return; - int bpNo = 0; - try { - PHPLineBreakpoint phpLBP; - if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier()) { - phpLBP = (PHPLineBreakpoint) breakpoint; - // bpNo= DBGInt.addBreakpoint(phpLBP.getMarker().getResource().getLocation().toOSString(), phpLBP.getLineNumber()); - - bpNo = DBGInt.addBreakpoint(MapPath(phpLBP), phpLBP.getLineNumber()); - phpLBP.setDBGBpNo(bpNo); - } - } catch (IOException e) { - PHPDebugCorePlugin.log(e); - stop(); - } catch (CoreException e) { - PHPDebugCorePlugin.log(e); - stop(); - } - } - - public void removeBreakpoint(IBreakpoint breakpoint) { - if (DBGInt == null) - return; - try { - PHPLineBreakpoint phpLBP; - if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier()) { - phpLBP = (PHPLineBreakpoint) breakpoint; - - // bpNo= DBGInt.addBreakpoint(filename.toOSString(), phpLBP.getLineNumber()); - DBGInt.removeBreakpoint(MapPath(phpLBP), phpLBP.getLineNumber(), phpLBP.getDBGBpNo()); - } - } catch (IOException e) { - PHPDebugCorePlugin.log(e); - stop(); - } catch (CoreException e) { - PHPDebugCorePlugin.log(e); - stop(); - } - } - - public void phpLoopNotify() { - phpLoop.notifyWait(); - } - - public void startPHPLoop() { - phpLoop = new PHPLoop(); - phpLoop.start(); - } - - public void resume() { - try { - DBGInt.continueExecution(); - phpLoop.notifyWait(); - } catch (IOException e) { - PHPeclipsePlugin.log("Debugging session ended.", e); - stop(); - } - } - - public void pause() { - try { - if (null != DBGInt) - DBGInt.pauseExecution(); - else { - // TODO Make sure the Suspend action is grayed out - // when DBGInt is null - } - } catch (IOException e) { - PHPDebugCorePlugin.log(e); - stop(); - } - } - - protected PHPDebugTarget getDebugTarget() { - return debugTarget; - } - - public void setDebugTarget(PHPDebugTarget debugTarget) { - this.debugTarget = debugTarget; - debugTarget.setPHPDBGProxy(this); - } - - public PHPVariable[] readVariables(PHPStackFrame frame) { - try { - return DBGInt.getVariables(frame); - } catch (IOException ioex) { - ioex.printStackTrace(); - throw new RuntimeException(ioex.getMessage()); - } catch (DebugException ex) { - ex.printStackTrace(); - throw new RuntimeException(ex.getMessage()); - } - } - - public PHPVariable[] eval(PHPStackFrame frame, String evalString) { - try { - return DBGInt.evalBlock(frame, evalString); - // return DBGInt.getVariables(frame); - } catch (IOException ioex) { - ioex.printStackTrace(); - throw new RuntimeException(ioex.getMessage()); - } catch (DebugException ex) { - ex.printStackTrace(); - throw new RuntimeException(ex.getMessage()); - } - } - - public void readStepOverEnd(PHPStackFrame stackFrame) { - try { - DBGInt.stepOver(); - phpLoop.notifyWait(); - } catch (Exception e) { - PHPDebugCorePlugin.log(e); - } - } - - public void readStepReturnEnd(PHPStackFrame stackFrame) { - try { - DBGInt.stepOut(); - phpLoop.notifyWait(); - } catch (Exception e) { - PHPDebugCorePlugin.log(e); - } - } - - public void readStepIntoEnd(PHPStackFrame stackFrame) { - try { - DBGInt.stepInto(); - phpLoop.notifyWait(); - } catch (Exception e) { - PHPDebugCorePlugin.log(e); - } - } - - /* - * public PHPStackFrame[] readFrames(PHPThread thread) { //try { //this.println("th " + thread.getId() + " ; f "); //return new - * FramesReader(getMultiReaderStrategy()).readFrames(thread); return null; //} catch (IOException e) { // - * PHPDebugCorePlugin.log(e); // return null; //} - * } - */ - - public void closeSocket() throws IOException { - if (socket != null) { - socket.close(); - } - } - - public void closeServerSocket() throws IOException { - if (server != null) { - server.close(); - } - } - - public int getPort() { - return port; - } - - class PHPLoop extends Thread { - private boolean shouldStop; - - public PHPLoop() { - shouldStop = false; - this.setName("PHPDebuggerLoop"); - } - - public synchronized void setShouldStop() { - shouldStop = true; - try { - // If the loop thread is blocked on the server socket, - // forcibly unblock it to avoid leaking the thread, - // the socket and the port - closeServerSocket(); - } catch (IOException x) { - // Log this as a warning? - PHPDebugCorePlugin.log(x); + + String path = filename.toOSString(); + + if ((pathmap != null) && remote) { + java.util.Iterator i = pathmap.keySet().iterator(); + + while (i.hasNext()) { + String k = (String) i.next(); + if (path.startsWith(k)) { + path = pathmap.get(k) + path.substring(k.length()); + break; + } + } + } + + if (pathtranslation && remote) { + if (remoteSourcePath.toString ().substring (0, 1).equals ("/")) { + path = path.replace ('\\', '/'); + } + else { + path = path.replace ('/', '\\'); + } + } + + return path; + } + + /** + * + */ + public void addBreakpoint (IBreakpoint breakpoint) { + if (DBGInt == null) { + return; + } + + int bpNo = 0; + + try { + PHPLineBreakpoint phpLBP; + + if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier()) { + phpLBP = (PHPLineBreakpoint) breakpoint; + + // bpNo= DBGInt.addBreakpoint(phpLBP.getMarker().getResource().getLocation().toOSString(), phpLBP.getLineNumber()); + + bpNo = DBGInt.addBreakpoint(MapPath(phpLBP), phpLBP.getLineNumber()); + phpLBP.setDBGBpNo(bpNo); + } + } catch (IOException e) { + PHPDebugCorePlugin.log(e); + stop(); + } catch (CoreException e) { + PHPDebugCorePlugin.log(e); + stop(); + } + } + + /** + * + */ + public void removeBreakpoint (IBreakpoint breakpoint) { + if (DBGInt == null) { + return; } - } - - public synchronized void notifyWait() { - notify(); - } - - public void run() { - try { - char[] buf = new char[16]; - int i, pos, timeout; - long interval = 200; // 200ms - String line; - PHPStackFrame[] StackList; - boolean endFile = false; - boolean newconnect = false; - Socket newSocket = null; - PHPDBGInterface newDBGInt; - int sid = -1; - - // synchronized (this) { - // wait(); - // } - - PHPMainThread = new PHPThread(getDebugTarget(), getPort()); - PHPMainThread.setName("Thread [main]"); - timeout = 0; - - // while ((getDebugTarget() == null) && (timeout < 100)) { - // sleep(100); - // timeout++; - // } - // Be sure debug target is set - // PHPMainThread.setDebugTarget(getDebugTarget()); - getDebugTarget().addThread(PHPMainThread); - - //System.out.println("Waiting for breakpoints."); - while (!shouldStop) { - newconnect = true; - try { - newSocket = server.accept(); - //System.out.println("Accepted! : " + socket.toString()); - } catch (SocketTimeoutException e) { - // no one wants to connect - newconnect = false; - } catch (IOException e) { - PHPDebugCorePlugin.log(e); - return; - } - - if (newconnect) { - if (DBGInt == null) - server.setSoTimeout(1); - newDBGInt = new PHPDBGInterface(getReader(newSocket), newSocket.getOutputStream(), thisProxy); - newDBGInt.waitResponse(1000); - newDBGInt.flushAllPackets(); - // Check version and session ID - if ((DBGInt == null) || (DBGInt.getSID() == newDBGInt.getSID())) { - DBGInt = newDBGInt; - try { - closeSocket(); - } catch (IOException e) { - PHPDebugCorePlugin.log(e); - shouldStop = true; - } - socket = newSocket; - setBreakPoints(); - DBGInt.continueExecution(); - } else { - newDBGInt.continueExecution(); - newSocket.close(); - } - } - - if (DBGInt.waitResponse(interval)) { - - DBGInt.flushAllPackets(); - - if (DBGInt.BPUnderHit != 0) { - StackList = DBGInt.getStackList(); - if (StackList.length > 0) { - for (i = 0; i < StackList.length; i++) { - StackList[i].setThread(PHPMainThread); - if (DBGInt.getModByNo(StackList[i].getModNo()).equals("")) { - DBGInt.getSourceTree(); - } - StackList[i].setFile(DBGInt.getModByNo(StackList[i].getModNo())); - } - PHPMainThread.setStackFrames(StackList); - } - // Fire debug event - PHPMainThread.suspend(); - - synchronized (this) { - wait(); - } - } - } - if (remote) { - if (PHPMainThread.isTerminated()) { - shouldStop = true; - break; - } - } else { - if (PHPMainThread.isTerminated() || getDebugTarget().getProcess().isTerminated()) { - shouldStop = true; - break; - } - } - } - } catch (Exception ex) { - PHPDebugCorePlugin.log(ex); - System.out.println(ex); - } finally { - try { - getDebugTarget().terminate(); - closeSocket(); - closeServerSocket(); - } catch (IOException e) { - PHPDebugCorePlugin.log(e); - return; - } - //System.out.println("Socket loop finished."); - } - } - } + + try { + PHPLineBreakpoint phpLBP; + + if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier ()) { + phpLBP = (PHPLineBreakpoint) breakpoint; + + // bpNo= DBGInt.addBreakpoint(filename.toOSString(), phpLBP.getLineNumber()); + + DBGInt.removeBreakpoint(MapPath(phpLBP), phpLBP.getLineNumber(), phpLBP.getDBGBpNo()); + } + } catch (IOException e) { + PHPDebugCorePlugin.log (e); + stop (); + } catch (CoreException e) { + PHPDebugCorePlugin.log (e); + stop (); + } + } + + /** + * + */ + public void phpLoopNotify () { + phpLoop.notifyWait (); + } + + /** + * + */ + public void startPHPLoop () { + phpLoop = new PHPLoop (); // Create a DBG communication loop object + + phpLoop.start (); // And start the communication loop + } + + /** + * + */ + public void resume () { + try { + DBGInt.continueExecution(); + phpLoop.notifyWait(); + } catch (IOException e) { + PHPeclipsePlugin.log("Debugging session ended.", e); + stop(); + } + } + + /** + * + */ + public void pause () { + try { + if (null != DBGInt) { + DBGInt.pauseExecution(); + } + else { + // TODO Make sure the Suspend action is grayed out + // when DBGInt is null + } + } catch (IOException e) { + PHPDebugCorePlugin.log (e); + stop (); + } + } + + /** + * + */ + protected PHPDebugTarget getDebugTarget() { + return debugTarget; + } + + /** + * + * @param debugTarget + */ + public void setDebugTarget (PHPDebugTarget debugTarget) { + this.debugTarget = debugTarget; + debugTarget.setPHPDBGProxy(this); + } + + /** + * This method is called by a stackframe. + * It reads the variables from PHP via DBG + * + * @param frame The stackframe which wants the variables. + * @return The array of variables for this stackframe. + */ + public PHPVariable[] readVariables (PHPStackFrame frame) { + try { + return DBGInt.getVariables (frame); // Get the variables from DBG interface + } catch (IOException ioex) { + ioex.printStackTrace (); + throw new RuntimeException (ioex.getMessage ()); + } catch (DebugException ex) { + ex.printStackTrace (); + throw new RuntimeException (ex.getMessage ()); + } + } + + /** + * + * @param frame + * @param evalString + * @return + */ + public PHPVariable[] eval (PHPStackFrame frame, String evalString) { + try { + return DBGInt.evalBlock (frame, evalString); + //return DBGInt.getVariables(frame); + } catch (IOException ioex) { + ioex.printStackTrace(); + throw new RuntimeException(ioex.getMessage()); + } catch (DebugException ex) { + ex.printStackTrace(); + throw new RuntimeException(ex.getMessage()); + } + } + + public void readStepOverEnd (PHPStackFrame stackFrame) { + try { + DBGInt.stepOver(); + phpLoop.notifyWait(); + } catch (Exception e) { + PHPDebugCorePlugin.log(e); + } + } + + public void readStepReturnEnd (PHPStackFrame stackFrame) { + try { + DBGInt.stepOut(); + phpLoop.notifyWait(); + } catch (Exception e) { + PHPDebugCorePlugin.log(e); + } + } + + public void readStepIntoEnd (PHPStackFrame stackFrame) { + try { + DBGInt.stepInto(); + phpLoop.notifyWait(); + } catch (Exception e) { + PHPDebugCorePlugin.log(e); + } + } + + /* + * public PHPStackFrame[] readFrames(PHPThread thread) { //try { //this.println("th " + thread.getId() + " ; f "); //return new + * FramesReader(getMultiReaderStrategy()).readFrames(thread); return null; //} catch (IOException e) { // + * PHPDebugCorePlugin.log(e); // return null; //} + * } + */ + + public void closeSocket() throws IOException { + if (socket != null) { + socket.close(); + } + } + + public void closeServerSocket() throws IOException { + if (server != null) { + server.close(); + } + } + + public int getPort() { + return port; + } + + /** + * + * + */ + class PHPLoop extends Thread { + private boolean shouldStop; + + public PHPLoop () { + shouldStop = false; + this.setName ("PHPDebuggerLoop"); + } + + /** + * + */ + public synchronized void setShouldStop () { + shouldStop = true; // The run loop should stop + + try { + // If the loop thread is blocked on the server socket, + // forcibly unblock it to avoid leaking the thread, + // the socket and the port + closeServerSocket (); + } catch (IOException x) { + // Log this as a warning? + PHPDebugCorePlugin.log (x); + } + } + + /** + * + */ + public synchronized void notifyWait () { + notify (); + } + + /** + * + * + */ + public void run () { + try { + int i; + int timeout; + long interval = 200; // Wait 200 ms maximum for a DBG response + boolean newconnect = false; // + Socket newSocket = null; + PHPStackFrame[] StackList; + PHPDBGInterface newDBGInt; + + // synchronized (this) { + // wait(); + // } + + PHPMainThread = new PHPThread (getDebugTarget (), getPort ()); + PHPMainThread.setName ("Thread [main]"); + timeout = 0; + + // while ((getDebugTarget() == null) && (timeout < 100)) { + // sleep(100); + // timeout++; + // } + // Be sure debug target is set + // PHPMainThread.setDebugTarget(getDebugTarget()); + + getDebugTarget ().addThread (PHPMainThread); + + //System.out.println("Waiting for breakpoints."); + + while (!shouldStop) { // As long as nobody will stop us + newconnect = true; // The first time + + try { + newSocket = server.accept(); // Waits until DBG want to connect + //System.out.println("Accepted! : " + socket.toString()); + } catch (SocketTimeoutException e) { + newconnect = false; // No one wants to connect (connection already done) + } catch (IOException e) { + PHPDebugCorePlugin.log(e); + return; + } + + if (newconnect) { // Is it just after a new connection + if (DBGInt == null) { // Do we have a DBG interface? + server.setSoTimeout(1); // ??? + } + + newDBGInt = new PHPDBGInterface (getReader (newSocket), // Create a new interface + newSocket.getOutputStream (), + thisProxy); + newDBGInt.waitResponse (1000); // Wait for the initial DBG response + newDBGInt.flushAllPackets (); // Read and process the DBG response + + // Check version and session ID + if ((DBGInt == null) || // If we have no interface + (DBGInt.getSID () == newDBGInt.getSID ())) {// or the new session ID is different to the old one + DBGInt = newDBGInt; // Set the new interface as current one + + try { + closeSocket (); + } + catch (IOException e) { + PHPDebugCorePlugin.log (e); + shouldStop = true; + } + + socket = newSocket; + setBreakPoints (); + DBGInt.continueExecution (); // Notify DBG that PHP should continue + } + else { + newDBGInt.continueExecution (); // Notify DBG that PHP should continue + newSocket.close (); + } + } + + if (DBGInt.waitResponse (interval)) { // Wait for a DBG response (200 ms) + DBGInt.flushAllPackets (); // If we got something, read and process it + + if (DBGInt.BPUnderHit != 0) { // ??? + StackList = DBGInt.getStackList (); // Get the stack list from DBGInterface + + if (StackList.length > 0) { // If there is something in stack list + for (i = 0; i < StackList.length; i++) { // For all stack list + StackList[i].setThread (PHPMainThread); // Set the PHPTread for all PHPStackFrames + + if (DBGInt.getModByNo (StackList[i].getModNo ()).equals ("")) { + DBGInt.getSourceTree (); + } + + StackList[i].setFile (DBGInt.getModByNo (StackList[i].getModNo ())); + } + + PHPMainThread.setStackFrames (StackList); + } + + PHPMainThread.suspend (); // Fire debug event + + synchronized (this) { + wait (); + } + } + } + + if (remote) { + if (PHPMainThread.isTerminated ()) { + shouldStop = true; + + break; // Go for terminating the thread + } + } else { + if (PHPMainThread.isTerminated () || + getDebugTarget ().getProcess ().isTerminated ()) { + shouldStop = true; + + break; // Go for terminating the thread + } + } + } + } catch (Exception ex) { + PHPDebugCorePlugin.log (ex); + System.out.println (ex); + } finally { + try { + getDebugTarget ().terminate (); + closeSocket(); + closeServerSocket (); + } catch (IOException e) { + PHPDebugCorePlugin.log (e); + + return; + } + + //System.out.println("Socket loop finished."); + } + } + } } diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPDBGEvalString.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPDBGEvalString.java index 4225702..40afdb0 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPDBGEvalString.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPDBGEvalString.java @@ -25,17 +25,17 @@ public class PHPDBGEvalString { String workStr; private PHPStackFrame fStackFrame; - + public PHPDBGEvalString(PHPStackFrame stack,String dataStr) { fStackFrame=stack; workStr=dataStr; } - + String ExtractSubStr(char chstart, char chend,int startIdx) throws DebugException { int idx=startIdx; String rslt; if (idx >= (workStr.length() - 1) || workStr.charAt(idx) != chstart) { - Status status= new Status(Status.ERROR,PHPDebugCorePlugin.getUniqueIdentifier(),Status.OK,"worng startIdx!",null); + Status status= new Status(Status.ERROR,PHPDebugCorePlugin.getUniqueIdentifier(),Status.OK,"worng startIdx!",null); throw new DebugException(status); } int i = ++idx; @@ -49,11 +49,11 @@ public class PHPDBGEvalString { workStr=workStr.substring(i+1); return rslt; } - + String ExtractQuotedSubStr(int slen,int startIdx) throws DebugException { int idx=startIdx; String rslt; - if (idx+slen+1 >= workStr.length() || + if (idx+slen+1 >= workStr.length() || workStr.charAt(idx)!= '"' || workStr.charAt(idx+slen+1) != '"') { Status status= new Status(Status.ERROR,PHPDebugCorePlugin.getUniqueIdentifier(),Status.OK,"no quoted substring found!",null); @@ -64,7 +64,7 @@ public class PHPDBGEvalString { return rslt; } - + int ExtractInt(char chstart, char chend,int startIdx) throws DebugException { String subs; int rslt; @@ -91,7 +91,7 @@ public class PHPDBGEvalString { if (arritems > 0) { subitems = new Vector(); } else - if (workStr.charAt(0)!='}') + if (workStr.charAt(0)!='}') { Status status= new Status(Status.ERROR,PHPDebugCorePlugin.getUniqueIdentifier(),Status.OK,"no array endcharecter!",null); throw new DebugException(status); @@ -106,18 +106,18 @@ public class PHPDBGEvalString { } // value parse(((PHPVariable)tmplst.elementAt(0)).getValue().getValueString(),item, subitems, var_list, true,0); - + } ((PHPValue)item.getValue()).addVariable(subitems); workStr=workStr.substring(1); return item; } - + void ParseEvalNULL(String name,PHPVariable parent,Vector list, Vector var_list, int startIdx) throws DebugException { int idx=startIdx; if (idx >= workStr.length() || workStr.charAt(idx) != ';') { Status status= new Status(Status.ERROR,PHPDebugCorePlugin.getUniqueIdentifier(),Status.OK,"NULL not found!",null); - throw new DebugException(status); + throw new DebugException(status); } workStr=workStr.substring(1); PHPVariable item= new PHPVariable(fStackFrame, name,parent,"NULL",PHPValue.PEVT_UNKNOWN,null); @@ -125,7 +125,7 @@ public class PHPDBGEvalString { if (var_list!=null) var_list.add(item); } - + boolean ParseEvalInt( String name, PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException { String subs=null; PHPVariable item; @@ -136,7 +136,7 @@ public class PHPDBGEvalString { var_list.add(item); return true; } - + boolean ParseEvalDouble(String name,PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException { String subs=null; PHPVariable item; @@ -147,7 +147,7 @@ public class PHPDBGEvalString { var_list.add(item); return true; } - + boolean ParseEvalString(String name,PHPVariable parent, Vector list, Vector var_list, boolean MakePhpStr, int startIdx) throws DebugException{ int slen; @@ -176,7 +176,7 @@ public class PHPDBGEvalString { var_list.add(item); return true; } - + boolean ParseEvalBool(String name,PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException{ long v; @@ -186,8 +186,8 @@ public class PHPDBGEvalString { if (var_list!=null) list.add(item); return true; - } - + } + boolean ParseEvalObject(String name,PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException{ int slen; @@ -199,7 +199,7 @@ public class PHPDBGEvalString { ParseEvalArray(name,parent, list, var_list, classname,PHPValue.PEVT_OBJECT); return true; } - + boolean ParseEvalResource(String name,PHPVariable parent, Vector list, Vector var_list, int startIdx) throws DebugException{ int v, slen; @@ -213,18 +213,18 @@ public class PHPDBGEvalString { return true; } - + boolean ParseEvalRef(String name,PHPVariable parent, Vector list, Vector var_list, boolean isSoftRef, int startIdx) throws DebugException{ int v; v=ExtractInt(':', ';',startIdx); - PHPVariable item= new PHPVariable(fStackFrame, name,parent,"",(isSoftRef)? (PHPValue.PEVT_SOFTREF): (PHPValue.PEVT_REF),null); + PHPVariable item= new PHPVariable(fStackFrame, name,parent,"",(isSoftRef)? (PHPValue.PEVT_SOFTREF): (PHPValue.PEVT_REF),null); v--; // ref ID is 1-based, EvalList is 0-based - if ((var_list==null) || (v<0) || (v >= var_list.size())) { + if ((var_list==null) || (v<0) || (v >= var_list.size())) { // item.ref = item; // self-resolving return true; } else { @@ -237,63 +237,77 @@ public class PHPDBGEvalString { // TODO Auto-generated catch block e.printStackTrace(); } - list.add(item); + list.add(item); } - + return true; } - - public PHPVariable[] getVars(){ - Vector list=new Vector(); - Vector var_list=new Vector(); - parse("",null,list,var_list,false,0); - return (PHPVariable[])list.toArray(new PHPVariable[list.size()]); + + /** + * + * @return The array of PHPVariables + */ + public PHPVariable[] getVars () { + Vector list = new Vector (); + Vector var_list = new Vector (); + + parse ("", null, list, var_list, false, 0); + + return (PHPVariable[]) list.toArray (new PHPVariable[list.size ()]); // Convert the list to an array and return the array + } + + /** + * + * @return The array of PHPVariables + */ + public Vector getVariables () { + Vector list = new Vector (); + Vector var_list = new Vector (); + + parse ("", null, list, var_list, false, 0); + + return list; // return the PHPVariable list } - - boolean parse(String name,PHPVariable parent, Vector list, Vector var_list, boolean MakePhpStr,int startIdx) { + + /** + * + * @param name + * @param parent + * @param list + * @param var_list + * @param MakePhpStr + * @param startIdx + */ + boolean parse (String name, PHPVariable parent, Vector list, Vector var_list, boolean MakePhpStr, int startIdx) { boolean ret_val = false; + char ch; + + if (startIdx >= workStr.length ()) { + return false; + } + + ch = workStr.charAt (startIdx); + workStr = workStr.substring (1); - if (startIdx >= workStr.length()) return false; - char ch = workStr.charAt(startIdx); - workStr=workStr.substring(1); try { switch (ch) { - case 'N': - ParseEvalNULL(name,parent, list, var_list, startIdx); - break; - case 'i': - ParseEvalInt(name,parent, list, var_list, startIdx); - break; - case 'd': - ParseEvalDouble(name,parent, list, var_list, startIdx); - break; - case 's': - ParseEvalString(name,parent, list, var_list, MakePhpStr, startIdx); - break; - case 'a': - ParseEvalArray(name,parent, list, var_list, "", PHPValue.PEVT_ARRAY); - break; - case 'O': - ParseEvalObject(name,parent, list, var_list, startIdx); - break; - case 'b': - ParseEvalBool(name,parent, list, var_list, startIdx); - break; - case 'z': - ParseEvalResource(name,parent, list, var_list, startIdx); - break; - case 'R': - ParseEvalRef(name,parent, list, var_list, false, startIdx); - break; - case 'r': - ParseEvalRef(name,parent, list, var_list, true, startIdx); - break; + case 'N': ParseEvalNULL (name, parent, list, var_list, startIdx); break; + case 'i': ParseEvalInt (name, parent, list, var_list, startIdx); break; + case 'd': ParseEvalDouble (name, parent, list, var_list, startIdx); break; + case 's': ParseEvalString (name, parent, list, var_list, MakePhpStr, startIdx); break; + case 'a': ParseEvalArray (name, parent, list, var_list, "", PHPValue.PEVT_ARRAY); break; + case 'O': ParseEvalObject (name, parent, list, var_list, startIdx); break; + case 'b': ParseEvalBool (name, parent, list, var_list, startIdx); break; + case 'z': ParseEvalResource (name, parent, list, var_list, startIdx); break; + case 'R': ParseEvalRef (name, parent, list, var_list, false, startIdx); break; + case 'r': ParseEvalRef (name, parent, list, var_list, true, startIdx); break; } } catch (DebugException e) { // TODO Auto-generated catch block e.printStackTrace(); } + /* if (!ret_val) { // try to recover unsigned int i=*startIdx; while (i 0; + + return variables.length > 0; // Is there something within the array? } public int getLineNumber() { return lineNumber; } + public void setLineNumber(int line) { + lineNumber = line; + } + public int getCharStart() throws DebugException { // not supported return -1; @@ -154,25 +212,43 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame { return false; } - public void stepInto() throws DebugException { - thread.prepareForResume() ; - this.getPHPDBGProxy().readStepIntoEnd(PHPStackFrame.this) ; - DebugEvent ev = new DebugEvent(this.getThread(), DebugEvent.RESUME, DebugEvent.STEP_INTO); - DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev }); + /** + * + */ + public void stepInto () throws DebugException { + DebugEvent ev; + + thread.prepareForResume (DebugEvent.STEP_INTO); // Don't know why, but this is necessary + this.getPHPDBGProxy ().readStepIntoEnd (PHPStackFrame.this); + + ev = new DebugEvent (this.getThread (), DebugEvent.RESUME, DebugEvent.STEP_INTO); + DebugPlugin.getDefault().fireDebugEventSet (new DebugEvent[] { ev }); } - public void stepOver() throws DebugException { - thread.prepareForResume() ; - this.getPHPDBGProxy().readStepOverEnd(PHPStackFrame.this) ; - DebugEvent ev = new DebugEvent(this.getThread(), DebugEvent.RESUME, DebugEvent.STEP_OVER); - DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev }); + /** + * + */ + public void stepOver () throws DebugException { + DebugEvent ev; + + thread.prepareForResume (DebugEvent.STEP_OVER); + this.getPHPDBGProxy ().readStepOverEnd (PHPStackFrame.this) ; + + ev = new DebugEvent (this.getThread (), DebugEvent.RESUME, DebugEvent.STEP_OVER); + DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev }); } - public void stepReturn() throws DebugException { - thread.prepareForResume() ; - this.getPHPDBGProxy().readStepReturnEnd(PHPStackFrame.this) ; - DebugEvent ev = new DebugEvent(this.getThread(), DebugEvent.RESUME, DebugEvent.STEP_RETURN); - DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev }); + /** + * + */ + public void stepReturn () throws DebugException { + DebugEvent ev; + + thread.prepareForResume (DebugEvent.STEP_RETURN); + this.getPHPDBGProxy ().readStepReturnEnd (PHPStackFrame.this) ; + + ev = new DebugEvent (this.getThread (), DebugEvent.RESUME, DebugEvent.STEP_RETURN); + DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev }); } @@ -213,8 +289,10 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame { public PHPDBGProxy getPHPDBGProxy() { PHPDebugTarget DebugTarget; - DebugTarget= (PHPDebugTarget)thread.getDebugTarget(); - return DebugTarget.getPHPDBGProxy(); + + DebugTarget = (PHPDebugTarget) thread.getDebugTarget (); + + return DebugTarget.getPHPDBGProxy (); } public void setFile(String file) { diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPThread.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPThread.java index efc55ea..c6508e8 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPThread.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPThread.java @@ -26,46 +26,49 @@ import org.eclipse.ui.model.IWorkbenchAdapter; public class PHPThread extends PHPDebugElement implements IThread { - private PHPStackFrame[] frames; - - private PHPDebugTarget target; - - private String name; - - private int id; + private PHPStackFrame[] frames; // The stackframes which belongs to this thread + private PHPDebugTarget target; // + private String name; // + private int id; // The port number through which we communicate to DBG private class State { - private boolean isSuspended = false; - + private boolean isSuspended = false; private boolean isTerminated = false; + private boolean isStepping = false; - private boolean isStepping = false; - - boolean isSuspended() { + boolean isSuspended () { return isSuspended; } - boolean isTerminated() { + boolean isTerminated () { return isTerminated; } - boolean isStepping() { + boolean isStepping () { return isStepping; } - void setSuspended(boolean suspended) { - if (isTerminated()) - throw new IllegalStateException(); - if (suspended && isStepping()) + void setSuspended (boolean suspended) { + if (isTerminated ()) { throw new IllegalStateException(); + } + + if (suspended && isStepping ()) { + throw new IllegalStateException (); + } + isSuspended = suspended; } - void setStepping(boolean stepping) { - if (stepping && !isSuspended()) - throw new IllegalStateException(); - if (isTerminated()) - throw new IllegalStateException(); + void setStepping (boolean stepping) { + if (stepping && !isSuspended ()) { + throw new IllegalStateException (); + } + + if (isTerminated ()) { + throw new IllegalStateException (); + } + isStepping = stepping; } @@ -74,34 +77,43 @@ public class PHPThread extends PHPDebugElement implements IThread { } } - private final State state = new State(); + private final State state = new State (); - public PHPThread (PHPDebugTarget target, int id) { + /** + * @param target + * @param id The port number through which we communicate to DBG + */ + public PHPThread (PHPDebugTarget target, int id) { super (target); + this.target = target; - this.setId(id); + this.setId (id); } - public IStackFrame[] getStackFrames() throws DebugException { + /** + * + */ + public IStackFrame[] getStackFrames () throws DebugException { return frames; } - public int getStackFramesSize() { + public int getStackFramesSize () { return frames.length; } - public boolean hasStackFrames() { + public boolean hasStackFrames () { if (frames == null) { return false; } + return frames.length > 0; } - public int getPriority() throws DebugException { + public int getPriority () throws DebugException { return 0; } - public IStackFrame getTopStackFrame() throws DebugException { + public IStackFrame getTopStackFrame () throws DebugException { if (frames == null || frames.length == 0) { return null; } @@ -140,19 +152,34 @@ public class PHPThread extends PHPDebugElement implements IThread { return state.isSuspended; } - protected void prepareForResume() { - state.setSuspended(false); - this.frames = null; - DebugEvent ev = new DebugEvent(this, DebugEvent.RESUME, - DebugEvent.CLIENT_REQUEST); - DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev }); + /** + * + * Is called from PHPstackframe whenever a stepInto, stepOver or stepReturn is + * to be performed + * + * @param de + */ + protected void prepareForResume (int de) { + DebugEvent ev; + + state.setSuspended (false); // We will leave the suspended state + this.frames = null; // Reset the stackframes + ev = new DebugEvent (this, DebugEvent.RESUME, de); // Create an event resume by stepping + + DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev }); // Fire the event } - public synchronized void resume() throws DebugException { - if (!isSuspended()) - return; - this.prepareForResume(); - ((PHPDebugTarget) this.getDebugTarget()).getPHPDBGProxy().resume(); + /** + * + */ + public synchronized void resume () throws DebugException { + if (!isSuspended ()) { // Is the thread in suspended state? + return; // No, leave here + } + + this.prepareForResume (DebugEvent.STEP_OVER); // Use a STEP_OVER here because a 0 leads to a collapsing variable tree in UI + + ((PHPDebugTarget) this.getDebugTarget ()).getPHPDBGProxy ().resume (); } /* @@ -161,82 +188,141 @@ public class PHPThread extends PHPDebugElement implements IThread { * this.createName(suspensionPoint) ; this.suspend() ; } */ - public synchronized void suspend() throws DebugException { - if (isSuspended()) - return; - state.setSuspended(true); - state.setStepping(false); - getDebugTarget().suspend(); - DebugEvent ev = new DebugEvent(this, DebugEvent.SUSPEND, - DebugEvent.BREAKPOINT); - DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev }); + public synchronized void suspend () throws DebugException { + DebugEvent ev; + + if (isSuspended ()) { // Is the thread in suspend state? + return; // Yes, leave here + } + + state.setSuspended (true); // Set thread to suspended state + state.setStepping (false); // Reset thread from stepping state + + getDebugTarget ().suspend (); // + + ev = new DebugEvent (this, DebugEvent.SUSPEND, DebugEvent.BREAKPOINT); + + DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev }); } - public boolean canStepInto() { - return isSuspended() && isStepping() && this.hasStackFrames(); + /** + * + */ + public boolean canStepInto () { + return isSuspended () && // Is the thread in suspended mode (stopped) + isStepping () && // and ??? + this.hasStackFrames (); // and does this thread have stack frames? } - public boolean canStepOver() { - return isSuspended() && isStepping() && this.hasStackFrames(); + /** + * + */ + public boolean canStepOver () { + return isSuspended () && // Is the thread in suspended mode (stopped) + isStepping () && // and ??? + this.hasStackFrames (); // and does this thread have stack frames? } - public boolean canStepReturn() { - return isSuspended() && isStepping() && this.hasStackFrames(); + /** + * + */ + public boolean canStepReturn () { + return isSuspended () && // Is the thread in suspended mode (stopped) + isStepping () && // and ??? + this.hasStackFrames (); // and does this thread have stack frames? } - public boolean isStepping() { - return state.isStepping(); + /** + * + */ + public boolean isStepping () { + return state.isStepping (); } - public void stepInto() throws DebugException { - try { state.setStepping(true); } + /** + * + */ + public void stepInto () throws DebugException { + try { + state.setStepping (true); // Store the info about what we do + } catch (IllegalStateException x) { - throw new DebugException(PHPeclipsePlugin.error(x)); + throw new DebugException (PHPeclipsePlugin.error (x)); } + this.frames = null; - frames[0].stepInto(); + + frames[0].stepInto (); } - public void stepOver() throws DebugException { - state.setStepping(true); + /** + * + */ + public void stepOver () throws DebugException { + state.setStepping (true); + this.frames = null; - frames[0].stepOver(); + + frames[0].stepOver (); } - public void stepReturn() throws DebugException { + /** + * + */ + public void stepReturn () throws DebugException { } - public boolean canTerminate() { - return !isTerminated(); + /** + * + */ + public boolean canTerminate () { + return !isTerminated (); } - public boolean isTerminated() { - return state.isTerminated(); + /** + * + */ + public boolean isTerminated () { + return state.isTerminated (); } - public synchronized void terminate() throws DebugException { - if (isTerminated()) + /** + * + */ + public synchronized void terminate () throws DebugException { + if (isTerminated ()) { return; - state.setTerminated(true); + } + + state.setTerminated (true); this.frames = null; - getDebugTarget().terminate(); + getDebugTarget ().terminate (); } - public Object getAdapter(Class arg0) { - if (IWorkbenchAdapter.class.equals(arg0)) { + /** + * + * @param arg0 + * @return + */ + public Object getAdapter (Class arg0) { + if (IWorkbenchAdapter.class.equals (arg0)) { return new IWorkbenchAdapter() { public Object[] getChildren(Object o) { Object[] children = null; + try { IStackFrame[] frames = getStackFrames(); + if (null != frames) { children = new Object[frames.length]; - for (int i = 0; i < frames.length; ++i) + for (int i = 0; i < frames.length; ++i) { children[i] = frames[i]; + } } } catch (DebugException x) { - PHPeclipsePlugin.log("Unable to get stack frames.", x); - } + PHPeclipsePlugin.log ("Unable to get stack frames.", x); + } + return children; } @@ -253,21 +339,33 @@ public class PHPThread extends PHPDebugElement implements IThread { } }; } + return null; } + /** + * + */ public void setStackFrames(PHPStackFrame[] frames) { this.frames = frames; } - public String getName() { - String name = this.name; - if (isSuspended()) + /** + * + */ + public String getName () { + String name; + + name = this.name; + + if (isSuspended ()) { name = name + " (suspended)"; + } + return name; } - public void setName(String name) { + public void setName (String name) { this.name = name; } diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPValue.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPValue.java index caecb89..bf97de2 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPValue.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPValue.java @@ -23,56 +23,93 @@ import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; +/** + * PHPValue object belongs to a PHPVariable (is a member of PHPVariable). + * A PHPValue itself can have PHPVariables as children. + * + */ public class PHPValue implements IValue { - - final static String[] PEV_NAMES={"undefined","long","double","string","array", - "object","boolean","resource","reference","soft reference"}; - final static int PEVT_UNKNOWN =0; - final static int PEVT_LONG = 1; - final static int PEVT_DOUBLE=2; - final static int PEVT_STRING=3; - final static int PEVT_ARRAY=4; - final static int PEVT_OBJECT=5; - final static int PEVT_BOOLEAN=6; - final static int PEVT_RESOURCE=7; - final static int PEVT_REF=8; - final static int PEVT_SOFTREF=9; - - private int fValueType; - private boolean hasChildren; - private String fValueString; - private Vector fVariables; - private PHPStackFrame fStackFrame; - - PHPValue() { - this(null,"",PEVT_UNKNOWN,null); - } - - PHPValue(PHPStackFrame frame,String value,int fValueType,Vector subitems) + + final static String[] PEV_NAMES = {"undefined", // 0 + "long", // 1 + "double", // 2 + "string", // 3 + "array", // 4 + "object", // 5 + "boolean", // 6 + "resource", // 7 + "reference", // 8 + "soft reference"}; // 9 + final static int PEVT_UNKNOWN = 0; + final static int PEVT_LONG = 1; + final static int PEVT_DOUBLE = 2; + final static int PEVT_STRING = 3; + final static int PEVT_ARRAY = 4; + final static int PEVT_OBJECT = 5; + final static int PEVT_BOOLEAN = 6; + final static int PEVT_RESOURCE = 7; + final static int PEVT_REF = 8; + final static int PEVT_SOFTREF = 9; + + private int fValueType; // The type of this value (see the PEVT_... values) + private boolean hasChildren; // This value (variable) has children (more variables) + private String fValueString; // The value of this variable as text + private Vector fVariables; // The children of this variable (other variables) if any + private PHPStackFrame fStackFrame; // The stackframe this value (variable) belongs to + // + + /** + * + */ + PHPValue () { + this (null, "", PEVT_UNKNOWN, null); // Creates an empty value + } + + /** + * + * @param frame The stackframe this value (and variable) belongs to. + * @param value The value of this value. + * @param fValueType The type of this value (see the PEVT_... values). + * @param subitems This value has subitems. + */ + PHPValue (PHPStackFrame frame, String value, int fValueType, Vector subitems) { - this.fValueType=fValueType; - this.fValueString=value; - this.fStackFrame=frame; - if (subitems !=null) - this.fVariables=new Vector(subitems); - else - this.fVariables = new Vector(); - } - - Vector addVariable(Vector item) - { - if (item!=null) - this.fVariables.addAll(item); + this.fValueType = fValueType; + this.fValueString = value; + this.fStackFrame = frame; + + if (subitems != null) { // If there are children for this value (variable) + this.fVariables = new Vector (subitems); // Then add the children to this value (variable) + } + else { + this.fVariables = new Vector (); // Create an empty vector + } + } + + /** + * + * @param item + */ + Vector addVariable (Vector item) + { + if (item != null) { // If there is something we want to add + this.fVariables.addAll (item); // + } + return this.fVariables; } - - public void setParent(PHPVariable parent) { - if (!fVariables.isEmpty()) { - Iterator iter=fVariables.iterator(); - while (iter.hasNext()) { - ((PHPVariable)iter.next()).setParent(parent); + + /** + * + * @param parent + */ + public void setParent (PHPVariable parent) { + if (!fVariables.isEmpty ()) { // If we have child variables + Iterator iter = fVariables.iterator (); // Create an iterator for the children + + while (iter.hasNext ()) { // As long as we have children + ((PHPVariable) iter.next ()).setParent (parent); // Set all child's parent } - } } @@ -82,13 +119,28 @@ public class PHPValue implements IValue { public String getReferenceTypeName(){ return PEV_NAMES[fValueType]; } - + + /** + * + */ public int getReferenceType(){ return fValueType; } - - public int setReferenceType(int type){ - return fValueType=type; + + /** + * @param type Set the reference type (see the PEVT_... values). + */ + public int setReferenceType (int type) { + return fValueType = type; + } + + /** + * This method is called whenever this value (variable) is changed. + * + * @param value The changed value for this variable. + */ + public void setValueString (String value) { + fValueString = value; } /** @@ -107,17 +159,33 @@ public class PHPValue implements IValue { /** * @see org.eclipse.debug.core.model.IValue#getVariables() + * + * @return The array of child variable for this value (variable). */ public IVariable[] getVariables() { - return (PHPVariable[])fVariables.toArray(new PHPVariable[fVariables.size()]); + return (PHPVariable[]) fVariables.toArray (new PHPVariable[fVariables.size ()]); // return (IVariable[])fVariables.toArray(); } /** + * + */ + public Vector getChildVariables () { + return (fVariables); + } + + /** * @see org.eclipse.debug.core.model.IValue#hasVariables() + * + * @return + *
    + *
  • true if this value (variable) has child variables + *
  • false if no child variable available + *
*/ public boolean hasVariables() throws DebugException { - return (!fVariables.isEmpty()); + // return (!fVariables.isEmpty ()); + return (fVariables.size () != 0); } /** @@ -128,7 +196,7 @@ public class PHPValue implements IValue { return null; } - /** + /** * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget() */ public IDebugTarget getDebugTarget() { diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPVariable.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPVariable.java index fdb3b81..0cdad2a 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPVariable.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPVariable.java @@ -21,48 +21,76 @@ import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; + +/** + * + */ public class PHPVariable implements IVariable { - - private PHPValue fValue; - private String fName; - private PHPStackFrame fStackFrame; - private PHPVariable fParent; - private String fLongName; - - PHPVariable(){ - this(null,"",null,"",PHPValue.PEVT_UNKNOWN,null); - } - - PHPVariable(PHPStackFrame frame,String name, PHPVariable parent,String value,int valueType,Vector subitems) + private PHPValue fValue; // The value of this variable + private String fName; // The name of the variable + private PHPStackFrame fStackFrame; // The stackframe this variable belongs to + private PHPVariable fParent; // The parent variable (a back link) + private String fLongName; // ??? + private boolean fHasChanged; // + + /** + * + */ + PHPVariable () { + this (null, "", null, "", PHPValue.PEVT_UNKNOWN, null); // create an empty variable (a simple dummy node?) + } + + /** + * + * @param frame The stackframe this variable belongs to + * @param name The name for this variable + * @param parent The parent variable if this is not the root + * @param value The value of this variable which is a simple value or again a variable + * @param valueType The type of the value (e.g. int, double, string etc.) @see PHPValue + * @param subitems + */ + PHPVariable (PHPStackFrame frame, String name, PHPVariable parent, String value, int valueType, Vector subitems) { - this.fStackFrame=frame; - this.fValue=new PHPValue(frame,value,valueType,subitems); - this.fParent=parent; - setName(name); + this.fStackFrame = frame; + this.fValue = new PHPValue (frame, value, valueType, subitems); + this.fParent = parent; + this.fHasChanged = false; + + setName (name); } - - private void setName(String name) { - if ((fParent==null) || (fParent.getName()=="")) { - fLongName=name; - fName=name; + + /** + * + * @param name + */ + private void setName (String name) { + if ((fParent == null) || // If we have no parent for this variable + (fParent.getName () == "")) { // or we have a parent which is just a simple node ??? + fLongName = name; // Set the long name + fName = name; // and set the name + return; } - switch (fParent.getReferenceType()) { - case PHPValue.PEVT_ARRAY : - fName="['"+name+"']"; - fLongName=fParent.getLongName()+fName; - break; - case PHPValue.PEVT_OBJECT : - fName=name; - fLongName=fParent.getLongName()+"."+fName; - break; - default : - fName=name; - fLongName=name; - break; + + switch (fParent.getReferenceType ()) { // Get the type of the parent variable + case PHPValue.PEVT_ARRAY : // It's an array + fName = "['" + name + "']"; // So set the variable name as [name] + fLongName = fParent.getLongName () + fName; // Set the longname to parentVariableLongname[name] + break; + + case PHPValue.PEVT_OBJECT : // It's an object + fName = name; // Set the name to name + fLongName = fParent.getLongName () + "." + fName; // Set the longname to parentVariableLongname.name + break; + + default : + fName = name; // Set the name to name + fLongName = name; // Set the Longname to name + break; } } + /** * @see org.eclipse.debug.core.model.IVariable#getValue() */ @@ -76,18 +104,27 @@ public class PHPVariable implements IVariable { public String getName() { return fName; } - + + /** + * + */ public PHPVariable getParent() { return fParent; } - + + /** + * + */ public void setParent(PHPVariable parent) { this.fParent=parent; fLongName=parent.getLongName()+fName; } - + + /** + * + */ public String getLongName() { return fLongName; } @@ -98,11 +135,17 @@ public class PHPVariable implements IVariable { public String getReferenceTypeName() { return fValue.getReferenceTypeName(); } - + + /** + * + */ public int getReferenceType() { return fValue.getReferenceType(); } - + + /** + * + */ public int setReferenceType(int type) { return ((PHPValue) getValue()).setReferenceType(type); } @@ -112,10 +155,22 @@ public class PHPVariable implements IVariable { */ public boolean hasValueChanged() throws DebugException { // TODO Auto-generated method stub - return false; + // return false; + return fHasChanged; } - - /** + + /** + * + * @param changed This method is called after a suspend when the list of + * variables is updated, to mark that this variable has a changed + * value. The variable view will show this variable in + * a different color. + */ + public void setValueChanged (boolean changed) { + fHasChanged = changed; + } + + /** * @see org.eclipse.debug.core.model.IDebugElement#getModelIdentifier() */ public String getModelIdentifier() { @@ -136,7 +191,6 @@ public class PHPVariable implements IVariable { return getDebugTarget().getLaunch(); } - /** * @see org.eclipse.debug.core.model.IValueModification#setValue(java.lang.String) */ @@ -187,40 +241,49 @@ public class PHPVariable implements IVariable { public Object getAdapter(Class adapter) { return Platform.getAdapterManager().getAdapter(this, adapter); } - - public String toString() { - int type=-1; - String str=""; - - switch (getReferenceType()) - { - case PHPValue.PEVT_ARRAY : - int elements=fValue.getVariables().length; - switch (elements) { - case 0: - str= this.getName() + " [no elements]"; - break; - case 1: - str= this.getName() + " [1 element]"; - break; - default: - str= this.getName() + " [" + elements + " elements]"; - break; + + /** + * This method is called from variable view and denominates the variables with + * a type specific explanation. + * + */ + public String toString () { + int type = -1; + String str = ""; + + switch (getReferenceType ()) { + case PHPValue.PEVT_ARRAY : // Variable is an array + int elements = fValue.getVariables ().length; // Get the number of child elements + + switch (elements) { // Switch for the number of child elements + case 0: // We have no child element + str = this.getName () + " [no elements]"; // string => 'varname [no elements]' + break; + + case 1: // We have exactly one child element + str = this.getName () + " [1 element]"; // string => 'varname [1 element]' + break; + + default: // We have more than one element + str = this.getName () + " [" + elements + " elements]"; // string => 'varname [x elements]' + break; } break; - case PHPValue.PEVT_OBJECT : - str =this.getName() + " [class: " + fValue.getValueString() + "]"; + + case PHPValue.PEVT_OBJECT : // Variable is an object + str = this.getName () + " [class: " + fValue.getValueString() + "]"; // string => 'varname [class: varvalue]' break; - case PHPValue.PEVT_STRING : - str =this.getName() + " = \"" + fValue.getValueString() +"\"" ; + + case PHPValue.PEVT_STRING : // Variable is a string + str = this.getName () + " = \"" + fValue.getValueString() +"\"" ; // string => 'varname = "varvalue"' break; - case PHPValue.PEVT_SOFTREF : - default : - str =this.getName() + " = " + fValue.getValueString(); + + case PHPValue.PEVT_SOFTREF : // Variable is a soft reference + default : // or anything else + str = this.getName () + " = " + fValue.getValueString(); // string => 'varname = varvalue' break; } - + return str; - } } -- 1.7.1