1 /**********************************************************************
2 Copyright (c) 2000, 2002 IBM Corp. and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Common Public License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/legal/cpl-v10.html
9 Vicente Fernando - www.alfersoft.com.ar - Initial implementation
10 Christian Perkonig - remote debug
11 **********************************************************************/
12 package net.sourceforge.phpdt.internal.debug.core;
14 import java.io.BufferedReader;
15 import java.io.IOException;
16 import java.io.OutputStream;
17 import java.util.Vector;
19 import net.sourceforge.phpdt.internal.debug.core.model.PHPDBGEvalString;
20 import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
21 import net.sourceforge.phpdt.internal.debug.core.model.PHPVariable;
22 import net.sourceforge.phpdt.internal.debug.core.model.PHPValue;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.core.runtime.Status;
26 import org.eclipse.debug.core.DebugException;
28 import java.io.RandomAccessFile;
31 * The interface object are created by the proxy
34 public class PHPDBGInterface {
36 public boolean sessionEnded = false;
37 public int sessType = -1;
38 public int BPUnderHit = 0;
39 public String sessID = new String ();
41 private int[] LastBPRead = new int[10];
42 private Vector DBGBPList = new Vector ();
43 private Vector DBGVarList = new Vector ();
44 private PHPStackFrame[] DBGStackList;
45 private Vector DBGMods = new Vector (); // The module names and their numbers
46 private Vector stackListOld = new Vector ();
47 private BufferedReader in;
48 private OutputStream os; // The stream which goes to DBG
49 private boolean shouldStop = false;
50 private String evalRet = new String ("");
51 private String serGlobals = new String ("");
52 private int rawCounter = 1000; // An rawData frame ID counter
53 private PHPDBGProxy proxy = null;
54 private int lastCmd = -1;
56 private boolean stopOnError = false;
57 private char[] lastCommand = new char[4];
60 * @param in The input stream (communication from DBG).
61 * @param os The output stream (communication to DBG).
62 * @param proxy The proxy to which this interface belongs.
64 public PHPDBGInterface (BufferedReader in, OutputStream os, PHPDBGProxy proxy) {
74 * @param mod_name The module (source file) to which we add the breakpoint.
75 * @param line The line where the breakpoint is set.
76 * @return Breakpoint ID ???.
78 public int addBreakpoint (String mod_name, int line) throws IOException {
79 return setBreakpoint (mod_name, "", line, PHPDBGBase.BPS_ENABLED + PHPDBGBase.BPS_UNRESOLVED, 0, 0, 0, 0, 0);
84 * @param mod_name The module (source file) to which we add the breakpoint.
85 * @param line The line where the breakpoint is set.
86 * @param bpNo The breakpoint ID ???.
88 public void removeBreakpoint (String mod_name, int line, int bpNo) throws IOException {
89 setBreakpoint (mod_name, "", line, PHPDBGBase.BPS_DISABLED, 0, 0, 0, bpNo, 0);
93 * Is this method used anywhere?
96 public void requestDBGVersion () throws IOException {
97 PHPDBGPacket DBGPacket; // A DBG message packet
98 PHPDBGFrame DBGFrame; // A frame within a DBG packet
100 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); // A request for DBG
101 DBGFrame = new PHPDBGFrame (PHPDBGBase.FRAME_VER); // We want the version of DBG
103 DBGPacket.addFrame (DBGFrame); // Add the 'what we want' to the DBG packet
105 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
109 DBGPacket.sendPacket (os); // Send the request to DBG
113 * Called by the proxy
116 public void getSourceTree () throws IOException {
117 PHPDBGPacket DBGPacket; // A DBG message packet
118 PHPDBGFrame DBGFrame; // A frame within a DBG packet
120 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); // A request for DBG
121 DBGFrame = new PHPDBGFrame (PHPDBGBase.FRAME_SRC_TREE); // We want a source tree from DBG
123 DBGPacket.addFrame (DBGFrame); // Add the 'what we want' to the DBG packet
125 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
129 DBGPacket.sendPacket (os); // Send the request to DBG
131 waitResponse (1000); // Wait for the DBG response (1 second)
132 flushAllPackets (); // Read and process the response from DBG
136 * Is this method called from anywhere?
138 * @param modName The modul (filename).
140 public void addDBGModName (String modName) throws IOException {
141 PHPDBGPacket DBGPacket; // A DBG message packet
142 PHPDBGFrame DBGFrame; // A frame within a DBG packet
144 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); // A request for DBG
145 DBGFrame = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA); // We want Module name from DBG
147 rawCounter++; // Increment the rawData ID counter
148 DBGFrame.addInt (rawCounter); // FRAME_RAWDATA ID
149 DBGFrame.addInt (modName.length () + 1); // The length of rawdata string (incl. null char termination)
150 DBGFrame.addString (modName); // The file name (module name)
151 DBGFrame.addChar ('\0'); // Add the C-String null termination
153 DBGPacket.addFrame (DBGFrame);
155 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
159 DBGPacket.sendPacket (os);
163 * This method is called for adding or removing breakpoints.
165 * @param mod_name The module name (file name).
166 * @param condition Info about the condition when to break (not used at the moment).
167 * @param line The breakpoints line.
168 * @param state Info whether this breakpoint has to be dis- or enabled.
169 * @param istep Always 0.
170 * @param hitcount Always 0.
171 * @param skiphits Always 0.
172 * @param bpno The breakpoint ID.
173 * @param isunderhit ???
176 private int setBreakpoint (String mod_name, String condition, int line, int state, int istemp, int hitcount, int skiphits, int bpno, int isunderhit) throws IOException {
177 PHPDBGPacket DBGPacket;
178 PHPDBGFrame DBGFrame1;
179 PHPDBGFrame DBGFrame2;
182 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);
183 DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_BPS);
184 DBGFrame2 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA);
186 modNo = getModByName (mod_name); // Get the module ID by name
188 if (modNo >= 0) { // Did we find a module ID for the module name?
189 DBGFrame1.addInt (modNo); // Add the module ID to frame 1
191 DBGFrame1.addInt (0); // mod number (0 use file name)
194 DBGFrame1.addInt (line); // line number
196 if (modNo >= 0) { // Did we find a module ID for the module name?
197 DBGFrame1.addInt (0); // use mod number
200 DBGFrame1.addInt (rawCounter); // ID of FRAME_RAWDATA to send file name
203 DBGFrame1.addInt (state); // state BPS_*
204 DBGFrame1.addInt (istemp); // istep
205 DBGFrame1.addInt (hitcount); // hit count
206 DBGFrame1.addInt (skiphits); // skip hits
207 DBGFrame1.addInt (0); // ID of condition
208 DBGFrame1.addInt (bpno); // breakpoint number
209 DBGFrame1.addInt (isunderhit); // is under hit
211 if (modNo < 0) { // Did we find a module ID for the module name?
212 DBGFrame2.addInt (rawCounter); // FRAME_RAWDATA ID
213 DBGFrame2.addInt (mod_name.length() + 1); // length of rawdata (+ null char)
214 DBGFrame2.addString (mod_name); // file name
215 DBGFrame2.addChar ('\0'); // null char
217 DBGPacket.addFrame (DBGFrame2); // First add file name data
220 DBGPacket.addFrame (DBGFrame1); // Second add command data
222 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
226 DBGPacket.sendPacket (os); // Send the request to DBG
230 waitResponse (1000); // Wait for the DBG response (1 second)
231 flushAllPackets (); // Read and process the response from DBG
233 return LastBPRead[8]; // Return what ???
239 private void clearLastBP () {
242 for (i = 0; i < LastBPRead.length; i++) {
250 private void copyToLastBP (int[] BPBody) {
253 for (i = 0; i < LastBPRead.length; i++) {
254 LastBPRead[i] = BPBody[i];
261 public void continueExecution () throws IOException {
262 PHPDBGPacket DBGPacket;
265 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_CONTINUE);
267 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
271 DBGPacket.sendPacket (os); // Send the request to DBG
273 lastCommand = PHPDBGBase.DBGA_CONTINUE; // Store the info about the command we sent
279 public void pauseExecution () throws IOException {
280 PHPDBGPacket DBGPacket;
282 DBGPacket = new PHPDBGPacket (PHPDBGBase.IntToChar4 (PHPDBGBase.DBGC_PAUSE));
284 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
288 DBGPacket.sendPacket (os); // Send the request to DBG
294 private int getBPUnderHit () {
297 int[] dbg_bpl_body = new int[10];
299 for (i = 0; i < DBGBPList.size (); i++) { // look for bp under hit
300 dbg_bpl_body = (int[]) DBGBPList.get (i);
302 if (dbg_bpl_body[9] == 1) {
303 BPUnder = dbg_bpl_body[8];
310 public int getLastCmd()
320 public void setLastCmd (int cmd)
328 public void stepInto () throws IOException {
329 PHPDBGPacket DBGPacket;
332 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPINTO);
334 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
338 DBGPacket.sendPacket (os); // Send the request to DBG
340 lastCommand = PHPDBGBase.DBGA_STEPINTO; // Store the info about the command we sent
346 public void stepOver () throws IOException {
347 PHPDBGPacket DBGPacket;
350 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOVER);
352 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
356 DBGPacket.sendPacket (os); // Send the request to DBG
358 lastCommand = PHPDBGBase.DBGA_STEPOVER; // Store the info about the command we sent
364 public void stepOut () throws IOException {
365 PHPDBGPacket DBGPacket;
368 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOUT);
370 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
374 DBGPacket.sendPacket (os); // Send the request to DBG
376 lastCommand = PHPDBGBase.DBGA_STEPOUT; // Store the info about the command we sent
382 public void stopExecution () throws IOException {
383 PHPDBGPacket DBGPacket;
386 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STOP);
388 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
392 DBGPacket.sendPacket (os); // Send the request to DBG
396 * This method updates the 'static' variables list.
397 * It does a replication between the 'static' list (the variable list which
398 * is a member of this DBG interface object) and the DBG variable list
399 * (the list of variables which is received from PHP via DBG with the current suspend)
400 * Replication is done in the following way:
402 * <li> It looks for new variables within the DBG variables list and
403 * adds them to the 'static' list.
404 * <li> It looks for changed variables copies the current value to the variable within
405 * the 'static list' and mark these variables as 'hasChanged' (which uses the UI
406 * for showing the variable with a different color).
407 * <li> It looks for variables within the 'static' list, and removes them
408 * from the 'static' list in case the do not appear within the DBG list.
411 * @param varListOld The 'static' list of variables which are to be updated.
412 * @param varListNew The new list of (current) variables from DBG.
414 private void updateVariableList (Vector varListOld, Vector varListNew)
416 PHPVariable varOld; // The variable from the 'static' list
417 PHPVariable varNew; // The variable from the DBG list
418 PHPValue valOld; // The value of the current variable from 'static' list
419 PHPValue valNew; // The value of the current variable from DBG list
420 int n; // Index for the DBG list
421 int o; // Index for the static list
423 // Add the variables (and childs) to the static list if they are new
424 // and update the values of variables which are already existend within
425 // the 'static' list.
427 for (n = 0; n < varListNew.size (); n++) { // For every variable in 'DBG list'
428 varNew = (PHPVariable) varListNew.get (n); // Get the DBG variable
430 for (o = 0; o < varListOld.size (); o++) { // For every variable in static list
431 varOld = (PHPVariable) varListOld.get (o); // Get the static variable
433 if (varNew.getName ().equals (varOld.getName ())) { // Did we found the variable within the 'static' list?
434 valOld = (PHPValue) varOld.getValue (); // Get the value from 'static'
435 valNew = (PHPValue) varNew.getValue (); // Get the value from DBG
438 if (valOld.hasVariables () || // If the 'static' value has child variables
439 valNew.hasVariables ()) { // or if the DBG value has child variables
440 updateVariableList (valOld.getChildVariables (), // Update the variable list for the child variables
441 valNew.getChildVariables ());
443 else if (!valOld.getValueString ().equals (valNew.getValueString ())) { // Has the value changed?
444 valOld.setValueString (valNew.getValueString ()); // Yes, set the 'static' value (variable) to the new value
445 varOld.setValueChanged (true); // and set the 'has changed' flag, so that the variable view
446 // could show the user the changed status with a different
450 varOld.setValueChanged (false); // Reset the 'has changed' flag
453 catch (DebugException e) { // That's, because of the hasVariables method
456 break; // Found the variable,
460 if (o == varListOld.size ()) { // Did we found the variable within the static list?
461 varListOld.add (varNew); // No, then add the DBG variable to the static list
465 // Look for the variables we can remove from the 'static' list
467 for (o = 0; o < varListOld.size (); o++) { // For every variable in 'static' list
468 varOld = (PHPVariable) varListOld.get (o); // Get the static variable
470 for (n = 0; n < varListNew.size (); n++) { // For all variables in 'DBG' list
471 varNew = (PHPVariable) varListNew.get (n); // Get the variable from the 'DBG' list
473 if (varNew.getName ().equals (varOld.getName ())) { // Did we found the 'static' list variable within the 'DBG' list?
474 break; // Yes we found the variable, then leave the loop
478 if (n == varListNew.size ()) { // Did not find the 'static' list variable within the 'DBG' list?
479 varListOld.remove (o); // then remove the 'static' list variable from list
480 o -= 1; // Adjust the 'static' list index
486 * This method is called by the proxy.
487 * It sends a request to DBG to get the current variables
488 * with their values. It waits for the response and processes
489 * the input from DBG.
491 * @param stack The stackframe for which we want the variables.
492 * @return The array of variables
494 public PHPVariable[] getVariables (PHPStackFrame stack) throws IOException, DebugException {
495 PHPDBGPacket DBGPacket;
496 PHPDBGFrame DBGFrame1;
497 PHPDBGEvalString evalStr;
499 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); //
500 DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_EVAL); //
502 DBGFrame1.addInt (0); // istr = raw data ID
503 DBGFrame1.addInt (1); // scope_id = -1 means current location, 0 never used, +1 first depth
505 DBGPacket.addFrame (DBGFrame1); // Add command data
507 if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication?
508 return null; // No, then leave here
511 DBGPacket.sendPacket (os); // Send the request to DBG
513 waitResponse (1000); // Wait for the DBG response (1 second)
514 flushAllPackets (); // Read and process the response from DBG
516 evalStr = new PHPDBGEvalString (stack, serGlobals); // Process serialized variables
517 updateVariableList (DBGVarList, evalStr.getVariables ()); // Replicate the 'static' variable list and the via DBG received variable list
519 return (PHPVariable[]) DBGVarList.toArray (new PHPVariable[DBGVarList.size ()]); // Convert the list to an array and return the array
526 public void log(String logString) throws IOException, DebugException {
527 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
528 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_LOG);
529 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
532 DBGFrame1.addInt(rawCounter); // ilog
533 DBGFrame1.addInt(1); // type
534 DBGFrame1.addInt(0); // mod_no
535 DBGFrame1.addInt(0); // line_no
536 DBGFrame1.addInt(0); // imod_name
537 DBGFrame1.addInt(0); // ext_info
539 DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID
540 DBGFrame2.addInt(logString.length() + 1); // length of rawdata (+ null char)
541 DBGFrame2.addString(logString); // log string
542 DBGFrame2.addChar('\0'); // null char
544 // Add raw data first
545 DBGPacket.addFrame(DBGFrame2);
547 DBGPacket.addFrame(DBGFrame1);
549 if(proxy.getSocket().isClosed()) return;
550 DBGPacket.sendPacket(os);
556 public PHPVariable[] evalBlock(PHPStackFrame stack, String evalString) throws IOException, DebugException {
557 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
558 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
559 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
562 DBGFrame1.addInt(rawCounter); // istr = raw data ID
563 DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth
565 DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID
566 DBGFrame2.addInt(evalString.length() + 1); // length of rawdata (+ null char)
567 DBGFrame2.addString(evalString); // eval block
568 DBGFrame2.addChar('\0'); // null char
570 // Add raw data first
571 DBGPacket.addFrame(DBGFrame2);
573 DBGPacket.addFrame(DBGFrame1);
575 if(proxy.getSocket().isClosed()) return null;
576 DBGPacket.sendPacket(os);
581 PHPDBGEvalString evalStr=new PHPDBGEvalString(stack,evalRet);
583 return evalStr.getVars();
588 * Read and process everthing we got from DBG
590 public void flushAllPackets () throws IOException {
591 while (readResponse() != 0);
595 * Get the modules name by its number
597 * @param modNo The number (id) of the module
598 * @return The name of the module
600 public String getModByNo (int modNo) {
604 for (i = 0; i < DBGMods.size (); i++) { // For all the modules we have within the array
605 dbg_mod = (PHPDBGMod) DBGMods.get (i); // Get the module
607 if (dbg_mod.getNo () == modNo) { // Is the module from the array the module we want?
608 return dbg_mod.getName (); // Yes, return the name of the module
612 return ""; // If nothing was found return emtpy string
617 * @param modName The name of the module for which we want the ID
619 * - The ID of the module
620 * - -1 if nothing was found
622 private int getModByName (String modName) {
626 for (i = 0; i < DBGMods.size (); i++) { // For all the modules we have within the array
627 dbg_mod = (PHPDBGMod) DBGMods.get (i); // Get the module
629 if (dbg_mod.getName ().equalsIgnoreCase (modName)) { // Is the module from the array the module we want?
630 return dbg_mod.getNo (); // Yes, return the name of the module
634 return -1; // If nothing was found return -1
638 * Return the string for the given frame number
640 * @param framesInfo The buffer which is to read
641 * @param frameNo The frame number
644 private String getRawFrameData (char[] framesInfo, int frameNo) {
645 int nextFrame = 0; // The current read position within the buffer
646 int[] dbg_frame = new int[2]; // The two frame header numbers
648 while (nextFrame < framesInfo.length) { // As long we have something within the buffer
649 dbg_frame[0] = PHPDBGBase.Char4ToInt (framesInfo, nextFrame); // The frame type
650 dbg_frame[1] = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4); // The frame size
652 nextFrame += 8; // The current read position
654 if (dbg_frame[1] == 0) { // If frame size is 0
655 return ""; // return an emtpy string
658 switch (dbg_frame[0]) { // Switch for the frame type
659 case PHPDBGBase.FRAME_RAWDATA: // The only frame type we are interrested in
660 if (frameNo == PHPDBGBase.Char4ToInt (framesInfo, nextFrame)) { // Is it correct number of the frame
663 toRead = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4); // The size of the string
665 return String.copyValueOf (framesInfo, nextFrame + 8, toRead); // Copy frame content to String and return
670 nextFrame += dbg_frame[1]; // Go for the next frame (add the length of the current one)
673 return ""; // We did not found any FRAM_RAWDATA, so return an emtpy strin
678 * The stackList contains the currently read stackframes which were sent
679 * from DBG. The DBG interface holds a list of the active stack frames.
680 * This method looks whether the sent stackframes are already in the list.
681 * Removes the unused stackframes from the list, or adds stackframes which
682 * are not yet in the list.
686 private void updateStackFrameList (Vector stackList) {
689 PHPStackFrame stackFrameNew;
690 PHPStackFrame stackFrameOld;
691 PHPStackFrame[] newStackList;
693 for (i = 0; i < stackList.size (); i++) { // For all stackList entries
694 stackFrameNew = (PHPStackFrame) stackList.get(i);
696 for (n = 0; n < stackListOld.size (); n++) { // For all StackFrames in the StackFrame list
697 stackFrameOld = (PHPStackFrame) stackListOld.get (n); // ---
699 if (stackFrameNew.getModNo () == stackFrameOld.getModNo ()) { // Did we find the sent stackframe within the list of old stackframes?
700 stackFrameOld.setLineNumber (stackFrameNew.getLineNumber());
702 break; // Yes, then break;
706 if (n == stackListOld.size ()) { // Did not find the new stackframe within the list
707 stackListOld.add (stackFrameNew); // then add the new stackframe
711 // And now for removing unused stackframes from list
713 for (n = 0; n < stackListOld.size (); n++) { // For all StackFrames in the StackFrame list
714 stackFrameOld = (PHPStackFrame) stackListOld.get (n); // ---
716 for (i = 0; i < stackList.size (); i++) { // For all stackList entries
717 stackFrameNew = (PHPStackFrame) stackList.get (i);
719 if (stackFrameNew.getModNo () == stackFrameOld.getModNo ()) { // Did we find the sent stackframe within the list of old stackframes?
720 break; // Yes, then break;
724 if (i == stackList.size ()) { // Did not find the old stackframe within the list of new ones
725 stackListOld.remove (n); // then remove the old stackframe from list
726 n -= 1; // Adjust the stack list index
730 newStackList = new PHPStackFrame[stackListOld.size ()];
731 newStackList = (PHPStackFrame[]) stackListOld.toArray (newStackList);
732 DBGStackList = newStackList;
736 * Read the response from DBG and process the frame
739 * - The received command
740 * - or 0 if something was wrong
742 public int readResponse () throws IOException {
743 int bytesToRead = 0; // The number of byte to read for the current DBG block
744 int nextFrame = 0; // The current read position within entirePack
748 boolean errorStack = false;
749 char[] dbg_header_struct_read = new char[16]; // The buffer for the first 16 bytes of a block
750 int[] dbg_header_struct = new int[4]; // The first four numbers (long) of a block
751 int[] dbg_bpl_tmp = new int[10];
752 int[] dbg_frame = new int[2];
753 int[] dbg_eval_tmp = new int[3];
754 int[] dbg_src_tree_tmp = new int[4]; //
755 int[] dbg_error_tmp = new int[2];
756 Vector rawList = new Vector();
757 Vector stackList = new Vector(); // Intermediate stacklist which is build up in FRAME_STACK frame
763 while (readInput (dbg_header_struct_read, 16) != 0) { // Read 16 byte from input stream
764 dbg_header_struct[0] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 0); // Debug sync header
765 dbg_header_struct[1] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 4); // Command
766 dbg_header_struct[2] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 8); //
767 dbg_header_struct[3] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 12); // Bytes within this block
769 if (dbg_header_struct[0] != 0x5953) { // Check DBG sync bytes
770 return 0; // Wrong header
773 cmdReceived = dbg_header_struct[1]; // Get the command
774 setLastCmd (cmdReceived); // Store the info about the current command
775 bytesToRead = dbg_header_struct[3]; // Get the number of bytes to read for this block
777 //System.out.println("Response Received: " + cmdReceived);
778 char[] entirePack = new char[bytesToRead]; // Store the block data into buffer 'entirePack'
780 if (bytesToRead > 0) { // If there is something within the frame
781 if (readInput (entirePack, bytesToRead) < bytesToRead) { // Read the frame into the buffer
782 return 0; // We did not read enough bytes, error
786 nextFrame = 0; // Start with the first frame
788 while (nextFrame < bytesToRead) { // As long as we have something within this block
789 dbg_frame[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame); // The name of the frame
790 dbg_frame[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // The size of the frame
791 nextFrame += 8; // The next read position
793 if (dbg_frame[1] == 0) { // Something within the frame?
794 return 0; // Nothing to read, error
797 switch (dbg_frame[0]) {
798 case PHPDBGBase.FRAME_STACK:
799 int[] dbg_stack_new = new int[4]; //
801 dbg_stack_new[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // Source line number
802 dbg_stack_new[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // Module number
803 dbg_stack_new[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8); // Scope id
804 dbg_stack_new[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12); // ID of description string
806 if ((dbg_stack_new[1] != 0) && !errorStack) {
807 PHPStackFrame newStack;
810 newStack = new PHPStackFrame (null, // The thread
811 getModByNo (dbg_stack_new[1]), // The name of the module (file)
812 dbg_stack_new[0], // The source line number
814 getRawFrameData (entirePack, // Get the string from this packet
815 dbg_stack_new[3]), // The frame ID for which we want the string
816 dbg_stack_new[1]); // The module number
817 stackList.add (newStack);
823 case PHPDBGBase.FRAME_SOURCE: // Nothing to be done here
824 break; // TODO: what's with that frame? Something interesting
826 case PHPDBGBase.FRAME_SRC_TREE: //
827 dbg_src_tree_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // The parent module number
828 dbg_src_tree_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // The parent line number (not used)
829 dbg_src_tree_tmp[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8); // The module number
830 dbg_src_tree_tmp[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12); // The filename number
832 if (getModByNo (dbg_src_tree_tmp[2]).equals ("")) {
835 fileName = new String (getRawFrameData (entirePack, dbg_src_tree_tmp[3])); // Get the filename
837 if (fileName.length () > 0) { // If we have a filename
838 fileName = fileName.substring (0, fileName.length () - 1); // Remove '\0' char
841 if (dbg_src_tree_tmp[2] != 0) { // If there is a module number
844 modNew = new PHPDBGMod (dbg_src_tree_tmp[2], fileName); // Create a module object
846 DBGMods.add (modNew); // And store it to array
851 case PHPDBGBase.FRAME_RAWDATA: // Nothing to be done here
852 break; // FRAME_RAWDATA are processed within getRawFrameData
854 case PHPDBGBase.FRAME_ERROR: // An error frame
855 errorStack = true; // Yes, we have an error stack
856 dbg_error_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // Error type
857 dbg_error_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // Error message ID
859 String error = "\n"; //
861 switch (dbg_error_tmp[0]) { // Switch on error type
862 case PHPDBGBase.E_ERROR: error += "[Error]"; break;
863 case PHPDBGBase.E_WARNING: error += "[Warning]"; break;
864 case PHPDBGBase.E_PARSE: error += "[Parse Error]"; break;
865 case PHPDBGBase.E_NOTICE: error += "[Notice]"; break;
866 case PHPDBGBase.E_CORE_ERROR: error += "[Core Error]"; break;
867 case PHPDBGBase.E_CORE_WARNING: error += "[Core Warning]"; break;
868 case PHPDBGBase.E_COMPILE_ERROR: error += "[Compile Error]"; break;
869 case PHPDBGBase.E_COMPILE_WARNING: error += "[Compile Warning]"; break;
870 case PHPDBGBase.E_USER_ERROR: error += "[User Error]"; break;
871 case PHPDBGBase.E_USER_WARNING: error += "[User Warning]"; break;
872 case PHPDBGBase.E_USER_NOTICE: error += "[User Notice]"; break;
873 default: error += "[Unexpected Error]"; break;
877 error += new String (getRawFrameData (entirePack, dbg_error_tmp[1])); // Add the error string for this error message ID
879 if (error.length () > 0) { // If we have a error message
880 error = error.substring (0, error.length () - 1); // Remove '\0' char
883 error += "\n"; // Append a CR
885 PHPDebugCorePlugin.log (new DebugException (new Status (IStatus.WARNING,
886 PHPDebugCorePlugin.PLUGIN_ID,
890 // To print errors on the console, I must execute a code in the
891 // php context, that write the stderr... I didn't found a better way
892 // TODO: Find a better way????
894 // String codeExec= "";
895 // codeExec= "fwrite(fopen('php://stderr', 'w'),\\\"" + error + "\\\");";
897 // evalBlock("eval(\"" + codeExec + "\");");
898 // } catch (DebugException e) {
899 // PHPDebugCorePlugin.log(e);
902 if (!stopOnError) { // Is always false (Did not see where this is set to true!?)
903 if (lastCommand.equals (PHPDBGBase.DBGA_CONTINUE)) { // If last command for PHP was a 'continue',
904 continueExecution (); // send continue again
905 } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPINTO)) { // If last command for PHP was a 'step into',
906 stepInto (); // send 'step into' again
907 } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPOUT)) { // If last command for PHP was a 'step out',
908 stepOut (); // send 'step out' again
909 } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPOVER)) { // If last command for PHP was a 'step over',
910 stepOver (); // send 'step over' again
915 case PHPDBGBase.FRAME_EVAL:
918 evalString = new String ("");
919 dbg_eval_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // istr
920 dbg_eval_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // iresult
921 dbg_eval_tmp[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8); // ierror
923 evalRet = getRawFrameData (entirePack, dbg_eval_tmp[1]); //
924 evalString = getRawFrameData (entirePack, dbg_eval_tmp[0]); //
925 serGlobals = evalRet; //
928 case PHPDBGBase.FRAME_BPS: //
931 case PHPDBGBase.FRAME_BPL:
934 dbg_bpl_new = new int[10];
935 dbg_bpl_new[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0);
936 dbg_bpl_new[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4);
937 dbg_bpl_new[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8);
938 dbg_bpl_new[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12);
939 dbg_bpl_new[4] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 16);
940 dbg_bpl_new[5] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 20);
941 dbg_bpl_new[6] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 24);
942 dbg_bpl_new[7] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 28);
943 dbg_bpl_new[8] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 32);
944 dbg_bpl_new[9] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 36);
946 // look if breakpoint already exists in vector
947 for (i = 0; i < DBGBPList.size (); i++) {
948 dbg_bpl_tmp = (int[]) DBGBPList.get (i);
950 if (dbg_bpl_tmp[8] == dbg_bpl_new[8]) {
951 DBGBPList.remove (i);
957 // add breakpoint to vector
958 DBGBPList.add (dbg_bpl_new);
959 copyToLastBP (dbg_bpl_new);
962 if (getModByNo (dbg_bpl_new[0]).equals ("")) {
965 fileName = new String (getRawFrameData (entirePack, dbg_bpl_new[2]));
967 if (fileName.length () > 0) { // If we have filename
968 fileName = fileName.substring (0, fileName.length () - 1); // Remove '\0' char
971 if (dbg_bpl_new[0] != 0) {
974 modNew = new PHPDBGMod (dbg_bpl_new[0], fileName);
976 DBGMods.add (modNew);
981 case PHPDBGBase.FRAME_VER:
984 case PHPDBGBase.FRAME_SID:
985 sid = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
988 case PHPDBGBase.FRAME_SRCLINESINFO:
991 case PHPDBGBase.FRAME_SRCCTXINFO:
994 case PHPDBGBase.FRAME_LOG:
997 case PHPDBGBase.FRAME_PROF:
1000 case PHPDBGBase.FRAME_PROF_C:
1003 case PHPDBGBase.FRAME_SET_OPT:
1007 nextFrame += dbg_frame[1]; // go to next frame
1010 // Now process command
1011 switch(cmdReceived) {
1012 case PHPDBGBase.DBGC_REPLY:
1015 case PHPDBGBase.DBGC_STARTUP:
1018 case PHPDBGBase.DBGC_END:
1019 sessionEnded = true;
1022 case PHPDBGBase.DBGC_BREAKPOINT:
1023 BPUnderHit = getBPUnderHit ();
1024 updateStackFrameList (stackList);
1027 case PHPDBGBase.DBGC_STEPINTO_DONE:
1028 case PHPDBGBase.DBGC_STEPOVER_DONE:
1029 case PHPDBGBase.DBGC_STEPOUT_DONE:
1030 case PHPDBGBase.DBGC_EMBEDDED_BREAK:
1031 case PHPDBGBase.DBGC_PAUSE:
1033 updateStackFrameList (stackList);
1036 case PHPDBGBase.DBGC_ERROR:
1038 updateStackFrameList (stackList);
1041 case PHPDBGBase.DBGC_LOG:
1044 case PHPDBGBase.DBGC_SID:
1049 return cmdReceived; // Return the command we received with this block
1056 public PHPStackFrame[] getStackList() {
1057 return DBGStackList;
1061 * Reads from input buffer (response sent from DBG) the given number of chars
1062 * into frame buffer.
1064 * @param buffer The frame buffer where to store the read data from DBG.
1065 * @param bytes The number of bytes (chars) which are to read from input stream.
1066 * @return The number of bytes actually read.
1068 private int readInput (char[] buffer, int bytes) throws IOException {
1069 int bytesRead = 0; // Reset the bytes read counter
1071 for (int i = 0; i < bytes; i++) { // For the number of bytes we should read
1072 if (in.ready ()) { // If input stream is ready for reading
1073 buffer[i] = (char) (in.read () & 0x00FF); // Read a char and store only the least significant 8-bits
1074 bytesRead++; // Increment the bytes read counter
1076 else { // Input stream is not ready
1077 break; // Break the loop
1081 return bytesRead; // Return the number of bytes actually read
1085 * PHPProxy could stop the waiting for a response with this method.
1088 public void setShouldStop () {
1089 this.shouldStop = true;
1093 * @param milliseconds The maximum time in milliseconds we wait for something
1094 * to be send from DBG.
1095 * @return - true if something was received from DBG
1096 * - false if nothing was send from DBG within the given time
1099 public boolean waitResponse (long milliseconds) throws IOException {
1102 timeout = System.currentTimeMillis () + milliseconds; // Calculate the system time till we wait.
1104 while (System.currentTimeMillis () < timeout) { // Is waiting time running out?
1105 if (in.ready () || shouldStop) { // No, so did we get something or should we stop now
1106 break; // Yes, break the waiting
1110 return in.ready (); // true if we got something from DBG