X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGInterface.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGInterface.java index 40b27b4..e0e19cc 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 @@ -7,6 +7,7 @@ http://www.eclipse.org/legal/cpl-v10.html Contributors: Vicente Fernando - www.alfersoft.com.ar - Initial implementation + Christian Perkonig - remote debug **********************************************************************/ package net.sourceforge.phpdt.internal.debug.core; @@ -14,12 +15,14 @@ import java.io.IOException; import java.io.BufferedReader; import java.io.OutputStream; import java.util.Vector; -import java.lang.System; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugException; + import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame; import net.sourceforge.phpdt.internal.debug.core.model.PHPVariable; -import net.sourceforge.phpdt.internal.debug.core.model.PHPValue; -import net.sourceforge.phpdt.internal.debug.core.PHPDBGMod; +import net.sourceforge.phpdt.internal.debug.core.model.PHPDBGEvalString; public class PHPDBGInterface { @@ -35,20 +38,24 @@ public class PHPDBGInterface { private PHPStackFrame[] DBGStackList; private PHPVariable[] DBGVariableList; private Vector DBGMods= new Vector(); - private Vector DBGVars= new Vector(); private BufferedReader in; private OutputStream os; - private boolean shouldStop= false, isRef= false, hasChildren= false, isObject= false; + private boolean shouldStop= false; private String evalRet= new String(""); private String serGlobals= new String(""); - private String typeRead= new String(""); - private String className= new String(""); - private int finalPos=0, refCounter=0, rawCounter=0; + private int rawCounter=1000; + private PHPDBGProxy proxy= null; + + private int lastCmd=-1; + private int sid=0; + private boolean stopOnError= false; + private char[] lastCommand= new char[4]; - public PHPDBGInterface(BufferedReader in, OutputStream os) { + 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 { @@ -64,7 +71,38 @@ public class PHPDBGInterface { PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_VER); DBGPacket.addFrame(DBGFrame); + + if(proxy.getSocket().isClosed()) return; + DBGPacket.sendPacket(os); + } + + 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); + + // Wait response (1 second) and read response + waitResponse(1000); + flushAllPackets(); + } + + 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 + + DBGPacket.addFrame(DBGFrame); + if(proxy.getSocket().isClosed()) return; DBGPacket.sendPacket(os); } @@ -113,6 +151,7 @@ public class PHPDBGInterface { // Second add command data DBGPacket.addFrame(DBGFrame1); + if(proxy.getSocket().isClosed()) return 0; DBGPacket.sendPacket(os); clearLastBP(); @@ -141,6 +180,14 @@ public class PHPDBGInterface { 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 pauseExecution() throws IOException { + PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.IntToChar4(PHPDBGBase.DBGC_PAUSE)); + if(proxy.getSocket().isClosed()) return; DBGPacket.sendPacket(os); } @@ -157,62 +204,108 @@ public class PHPDBGInterface { } return BPUnder; } + + public int getLastCmd() + { + return lastCmd; + } + + public int getSID() + { + return sid; + } + + public void setLastCmd(int 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 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 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 stopExecution() throws IOException { BPUnderHit= 0; PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STOP); + if(proxy.getSocket().isClosed()) return; DBGPacket.sendPacket(os); } public PHPVariable[] getVariables(PHPStackFrame stack) throws IOException, DebugException { PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL); - //PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA); DBGFrame1.addInt(0); // istr = raw data ID DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth - - /* - String evalBlock= new String("$GLOBALS"); - DBGFrame2.addInt(1); // FRAME_RAWDATA ID - DBGFrame2.addInt(evalBlock.length() + 1); // length of rawdata (+ null char) - DBGFrame2.addString(evalBlock); // eval block - DBGFrame2.addChar('\0'); // null char - */ // Add command data DBGPacket.addFrame(DBGFrame1); + if(proxy.getSocket().isClosed()) return null; DBGPacket.sendPacket(os); waitResponse(1000); flushAllPackets(); // Process serialized variables - DBGVariableList= procVars(stack); + PHPDBGEvalString evalStr=new PHPDBGEvalString(stack,serGlobals); + + DBGVariableList= evalStr.getVars(); return DBGVariableList; } - public void evalBlock(String evalString) throws IOException, DebugException { + public void log(String logString) throws IOException, DebugException { + PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); + PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_LOG); + PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA); + + rawCounter++; + DBGFrame1.addInt(rawCounter); // ilog + DBGFrame1.addInt(1); // type + DBGFrame1.addInt(0); // mod_no + DBGFrame1.addInt(0); // line_no + DBGFrame1.addInt(0); // imod_name + DBGFrame1.addInt(0); // ext_info + + DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID + DBGFrame2.addInt(logString.length() + 1); // length of rawdata (+ null char) + DBGFrame2.addString(logString); // log string + DBGFrame2.addChar('\0'); // null char + + // Add raw data first + DBGPacket.addFrame(DBGFrame2); + // Add command data + DBGPacket.addFrame(DBGFrame1); + + if(proxy.getSocket().isClosed()) return; + DBGPacket.sendPacket(os); + + waitResponse(1000); + flushAllPackets(); + } + + public PHPVariable[] evalBlock(PHPStackFrame stack, String evalString) throws IOException, DebugException { PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL); PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA); @@ -227,21 +320,27 @@ public class PHPDBGInterface { DBGFrame2.addChar('\0'); // null char // Add raw data first - DBGPacket.addFrame(DBGFrame2); + 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); } - private String getModByNo(int modNo) { + public String getModByNo(int modNo) { int i; PHPDBGMod dbg_mod; @@ -294,223 +393,17 @@ public class PHPDBGInterface { return ""; } - public PHPVariable[] getInstVars(PHPVariable phpVar) throws DebugException { - Vector vecVars= new Vector(); - PHPVariable localPHPVar; - int i=0; - - // already unserialized - for(i=0; i < DBGVars.size(); i++) { - localPHPVar= (PHPVariable)DBGVars.get(i); - if(localPHPVar.getParent() == phpVar) { - vecVars.add(localPHPVar); - } - } - PHPVariable[] arrVars= new PHPVariable[vecVars.size()]; - arrVars= (PHPVariable[]) vecVars.toArray(arrVars); - - return arrVars; - } - - private PHPVariable[] procVars(PHPStackFrame stack) throws DebugException { - Vector vecVars= new Vector(); - - // unserialize - finalPos= 0; - refCounter= 0; - doUnserialize(stack, vecVars, null); - - DBGVars= vecVars; - - return(getInstVars(null)); - } - - private String readValue(String serialVars) throws DebugException { - int startPos=0, endPos=0, lenStr=0, i=0, elements=0; - String ret= new String(""); - - switch(serialVars.charAt(0)) { - case 'a': // associative array, a:elements:{[index][value]...} - typeRead= "hash"; - startPos= 1; - endPos= serialVars.indexOf(':', startPos + 1); - if(endPos == -1) return ""; - finalPos += endPos + 2; - ret= new String(serialVars.substring(startPos + 1, endPos)); - - hasChildren= true; - break; - case 'O': // object, O:name_len:"name":elements:{[attribute][value]...} - typeRead= "object"; - - startPos= 1; - endPos= serialVars.indexOf(':', startPos + 1); - if(endPos == -1) return ""; - - // get object class - lenStr= Integer.parseInt(serialVars.substring(startPos + 1, endPos)); - startPos= endPos + 2; - endPos= lenStr + startPos; - className= new String(serialVars.substring(startPos, endPos).toString()); - - // get num of elements - startPos= endPos + 1; - endPos= serialVars.indexOf(':', startPos + 1); - if(endPos == -1) return ""; - finalPos += endPos + 2; - ret= new String(serialVars.substring(startPos + 1, endPos)); - - isObject= true; - hasChildren= true; - break; - case 's': // string, s:length:"data"; - typeRead= "string"; - startPos= 1; - endPos= serialVars.indexOf(':', startPos + 1); - if(endPos == -1) return ""; - - lenStr= Integer.parseInt(serialVars.substring(startPos + 1, endPos)); - startPos= endPos + 2; - endPos= lenStr + startPos; - ret= new String(serialVars.substring(startPos, endPos).toString()); - finalPos += endPos + 2; - break; - case 'i': // integer, i:123; - typeRead= "integer"; - startPos= 1; - endPos= serialVars.indexOf(';', startPos + 1); - if(endPos == -1) return ""; - - ret= new String(serialVars.substring(startPos + 1, endPos).toString()); - finalPos += endPos + 1; - break; - case 'd': // double (float), d:1.23; - typeRead= "double"; - startPos= 1; - endPos= serialVars.indexOf(';', startPos + 1); - if(endPos == -1) return ""; - - ret= new String(serialVars.substring(startPos + 1, endPos).toString()); - finalPos += endPos + 1; - break; - case 'N': // NULL, N; - typeRead= "null"; - ret= "nil"; - finalPos += 2; - break; - case 'b': // bool, b:0 or 1 - typeRead= "boolean"; - ret= (serialVars.charAt(2) == '1')?"true":"false"; - finalPos += endPos + 4; - break; - case 'z': // resource, z:typename_len:"typename":valres; - typeRead= "resource"; - - startPos= 1; - endPos= serialVars.indexOf(':', startPos + 1); - if(endPos == -1) return ""; - - // get resource type name - lenStr= Integer.parseInt(serialVars.substring(startPos + 1, endPos)); - startPos= endPos + 2; - endPos= lenStr + startPos; - className= new String(serialVars.substring(startPos, endPos).toString()); - - // get resource value - startPos= endPos + 1; - endPos= serialVars.indexOf(';', startPos + 1); - if(endPos == -1) return ""; - ret= new String(serialVars.substring(startPos + 1, endPos)); - finalPos += endPos + 1; - break; - case 'r': - case 'R': - typeRead= "reference"; - startPos= 1; - endPos= serialVars.indexOf(';', startPos + 1); - if(endPos == -1) return "0"; - - ret= new String(serialVars.substring(startPos + 1, endPos)); - finalPos += endPos + 1; - isRef= true; - break; - case ';': - typeRead= "unknown"; - finalPos+= 1; - break; - case '?': - finalPos+= 1; - default: - finalPos+= 1; - typeRead= "unknown"; - break; - } - return ret; - } - - private void doUnserialize(PHPStackFrame stack, Vector vecVars, PHPVariable parent) throws DebugException { - int i, elements= 0; - PHPVariable newVar= null; - String value= new String(""); - String name= new String(""); - String tmp= new String(""); - - if(finalPos > serGlobals.length() || serGlobals.equals("") || serGlobals.substring(finalPos).equals("")) return; - - isRef= false; - hasChildren= false; - isObject= false; - name= readValue(serGlobals.substring(finalPos)); - - if(hasChildren) { - // main array - if(refCounter == 0) { - value= name; - name= ""; - } - } else { - hasChildren= false; - isRef= false; - value= readValue(serGlobals.substring(finalPos)); - } - - if(!name.equals("")) { - if(isRef) { - PHPVariable varPHP; - for(i=0; i < vecVars.size(); i++) { - varPHP= (PHPVariable) vecVars.get(i); - if(varPHP.getObjectId().equals(value)) { - newVar= new PHPVariable(stack, name, "local", true, (PHPValue)varPHP.getValue()); - break; - } - } - if(newVar == null) { - newVar= new PHPVariable(stack, name, "local", false, null); - } - } else { - refCounter++; - newVar= new PHPVariable(stack, name, "local", value, typeRead, hasChildren, Integer.toString(refCounter), className); - } - newVar.setParent(parent); - vecVars.add(newVar); - } - if(hasChildren) { - elements= Integer.parseInt(value); - for(i=0; i < elements; i++) - doUnserialize(stack, vecVars, newVar); - - // skip "}" - finalPos += 1; - } - } 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(); PHPStackFrame[] newStackList; @@ -528,10 +421,10 @@ public class PHPDBGInterface { if(dbg_header_struct[0] != 0x5953) return 0; cmdReceived= dbg_header_struct[1]; + setLastCmd(cmdReceived); bytesToRead= dbg_header_struct[3]; - System.out.println("Response Received: " + cmdReceived); - + //System.out.println("Response Received: " + cmdReceived); char[] entirePack= new char[bytesToRead]; if(bytesToRead > 0) { @@ -553,19 +446,106 @@ public class PHPDBGInterface { dbg_stack_new[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8); // scope id dbg_stack_new[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12); // id of description string - stackIndex++; - if(!getModByNo(dbg_stack_new[1]).equals("")) { - PHPStackFrame newStack= new PHPStackFrame(null, getModByNo(dbg_stack_new[1]), dbg_stack_new[0], stackIndex, getRawFrameData(entirePack, dbg_stack_new[3])); + 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); } + errorStack= false; break; case PHPDBGBase.FRAME_SOURCE: 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); + } + } 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; + } + 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))); + // To print errors on the console, I must execute a code in the + // php context, that write the stderr... I didn't found a better way + // TODO: Find a better way???? + String codeExec= ""; + codeExec= "fwrite(fopen('php://stderr', 'w'),\\\"" + error + "\\\");"; +// try { +// evalBlock("eval(\"" + codeExec + "\");"); +// } catch (DebugException e) { +// PHPDebugCorePlugin.log(e); +// } + if(!stopOnError) { + 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(); + } + } break; case PHPDBGBase.FRAME_EVAL: String evalString= new String(""); @@ -610,13 +590,16 @@ public class PHPDBGInterface { String fileName= new String(getRawFrameData(entirePack, dbg_bpl_new[2])); // Remove '\0' char if(fileName.length() > 0) fileName= fileName.substring(0, fileName.length() - 1); - PHPDBGMod modNew= new PHPDBGMod(dbg_bpl_new[0], fileName); - DBGMods.add(modNew); + if(dbg_bpl_new[0] != 0) { + PHPDBGMod modNew= new PHPDBGMod(dbg_bpl_new[0], fileName); + DBGMods.add(modNew); + } } break; case PHPDBGBase.FRAME_VER: break; case PHPDBGBase.FRAME_SID: + sid = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); break; case PHPDBGBase.FRAME_SRCLINESINFO: break; @@ -654,12 +637,14 @@ public class PHPDBGInterface { 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; break; case PHPDBGBase.DBGC_ERROR: + stackList.clear(); newStackList= new PHPStackFrame[stackList.size()]; newStackList= (PHPStackFrame[]) stackList.toArray(newStackList); DBGStackList= newStackList; @@ -668,11 +653,8 @@ public class PHPDBGInterface { break; case PHPDBGBase.DBGC_SID: break; - case PHPDBGBase.DBGC_PAUSE: - break; } } - return cmdReceived; } @@ -698,12 +680,13 @@ public class PHPDBGInterface { this.shouldStop= true; } - public void waitResponse(long milliseconds) throws IOException { + public boolean waitResponse(long milliseconds) throws IOException { long timeout= System.currentTimeMillis() + milliseconds; while(System.currentTimeMillis() < timeout) { if(in.ready() || shouldStop) { break; } } + return in.ready(); } -} \ No newline at end of file +}