Contributors:
Vicente Fernando - www.alfersoft.com.ar - Initial implementation
+ Christian Perkonig - remote debug
**********************************************************************/
package net.sourceforge.phpdt.internal.debug.core;
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 {
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=1000;
+ 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, PHPDBGProxy proxy) {
DBGBPList.clear();
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);
}
private int getBPUnderHit() {
}
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 {
PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOVER);
if(proxy.getSocket().isClosed()) return;
DBGPacket.sendPacket(os);
+ lastCommand= PHPDBGBase.DBGA_STEPOVER;
}
public void stepOut() throws IOException {
PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOUT);
if(proxy.getSocket().isClosed()) return;
DBGPacket.sendPacket(os);
+ lastCommand= PHPDBGBase.DBGA_STEPOUT;
}
public void stopExecution() throws IOException {
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);
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);
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;
+ 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 {
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("");
- String[] tmpSplit;
-
- 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));
- // replaceAll doesn't work, why???
- tmpSplit= value.split("\\\\");
- value= "";
- for(i= 0; i < tmpSplit.length; i++) {
- value= value + tmpSplit[i];
- if(!tmpSplit[i].equals("")) {
- if(i < (tmpSplit.length - 1)) {
- value= value + "\\";
- }
- }
- }
- }
-
- 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;
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);
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(dbg_stack_new[1] != 0) {
+ 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_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("");
case PHPDBGBase.FRAME_VER:
break;
case PHPDBGBase.FRAME_SID:
+ sid = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
break;
case PHPDBGBase.FRAME_SRCLINESINFO:
break;
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;
break;
case PHPDBGBase.DBGC_SID:
break;
- case PHPDBGBase.DBGC_PAUSE:
- break;
}
}
-
return cmdReceived;
}
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
+}