Changes for variablemodificatin
[phpeclipse.git] / net.sourceforge.phpeclipse.debug.core / src / net / sourceforge / phpdt / internal / debug / core / PHPDBGInterface.java
index 72edfed..e0e19cc 100644 (file)
@@ -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,16 +38,18 @@ 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();
@@ -177,6 +182,13 @@ public class PHPDBGInterface {
                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() {
@@ -192,12 +204,28 @@ 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 {
@@ -205,6 +233,7 @@ public class PHPDBGInterface {
                PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOVER);
                if(proxy.getSocket().isClosed()) return;
                DBGPacket.sendPacket(os);
+               lastCommand= PHPDBGBase.DBGA_STEPOVER;
        }
 
        public void stepOut() throws IOException {
@@ -212,6 +241,7 @@ public class PHPDBGInterface {
                PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOUT);
                if(proxy.getSocket().isClosed()) return;
                DBGPacket.sendPacket(os);
+               lastCommand= PHPDBGBase.DBGA_STEPOUT;
        }
 
        public void stopExecution() throws IOException {
@@ -224,18 +254,9 @@ public class PHPDBGInterface {
        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);
@@ -247,12 +268,44 @@ public class PHPDBGInterface {
                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);
@@ -267,15 +320,20 @@ 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;
+               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 {
@@ -335,236 +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("");
-               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;
@@ -582,6 +421,7 @@ 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);
@@ -606,11 +446,12 @@ 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(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;
@@ -634,6 +475,77 @@ public class PHPDBGInterface {
                                        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("");
@@ -687,6 +599,7 @@ public class PHPDBGInterface {
                                        case PHPDBGBase.FRAME_VER:
                                                break;
                                        case PHPDBGBase.FRAME_SID:
+                                         sid = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
                                                break;
                                        case PHPDBGBase.FRAME_SRCLINESINFO:
                                                break;
@@ -724,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;
@@ -738,11 +653,8 @@ public class PHPDBGInterface {
                                        break;
                                case PHPDBGBase.DBGC_SID:
                                        break;
-                               case PHPDBGBase.DBGC_PAUSE:
-                                       break;
                        }
                }
-
                return cmdReceived;
        }
 
@@ -768,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
+}