modification to debug on a remote server
[phpeclipse.git] / net.sourceforge.phpeclipse.debug.core / src / net / sourceforge / phpdt / internal / debug / core / PHPDBGInterface.java
index 40b27b4..0f574b7 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;
 
 public class PHPDBGInterface {
 
@@ -43,12 +46,19 @@ public class PHPDBGInterface {
        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 finalPos=0, refCounter=0, 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 +74,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 +154,7 @@ public class PHPDBGInterface {
                // Second add command data
                DBGPacket.addFrame(DBGFrame1);
 
+               if(proxy.getSocket().isClosed()) return 0;
                DBGPacket.sendPacket(os);
 
                clearLastBP();
@@ -141,6 +183,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,50 +207,64 @@ 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);
@@ -212,6 +276,36 @@ public class PHPDBGInterface {
                return DBGVariableList;
        }
 
+       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 void evalBlock(String evalString) throws IOException, DebugException  {
                PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
                PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
@@ -219,7 +313,7 @@ public class PHPDBGInterface {
 
                rawCounter++;
                DBGFrame1.addInt(rawCounter);                           // istr = raw data ID
-               DBGFrame1.addInt(1);                                            // scope_id = -1 means current location, 0 never used, +1 first depth
+               DBGFrame1.addInt(-1);                                           // scope_id = -1 means current location, 0 never used, +1 first depth
 
                DBGFrame2.addInt(rawCounter);                           // FRAME_RAWDATA ID
                DBGFrame2.addInt(evalString.length() + 1);      // length of rawdata (+ null char)
@@ -227,10 +321,11 @@ 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;
                DBGPacket.sendPacket(os);
 
                waitResponse(1000);
@@ -241,7 +336,7 @@ public class PHPDBGInterface {
                while(readResponse() != 0);
        }
 
-       private String getModByNo(int modNo) {
+       public String getModByNo(int modNo) {
                int i;
                PHPDBGMod dbg_mod;
 
@@ -454,6 +549,7 @@ public class PHPDBGInterface {
                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;
 
@@ -472,6 +568,17 @@ public class PHPDBGInterface {
                        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("")) {
@@ -506,11 +613,14 @@ public class PHPDBGInterface {
 
        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 +638,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 +663,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 +807,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 +854,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 +870,8 @@ public class PHPDBGInterface {
                                        break;
                                case PHPDBGBase.DBGC_SID:
                                        break;
-                               case PHPDBGBase.DBGC_PAUSE:
-                                       break;
                        }
                }
-
                return cmdReceived;
        }
 
@@ -698,12 +897,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
+}