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;
18 import java.util.Collections;
20 import net.sourceforge.phpdt.internal.debug.core.model.PHPDBGEvalString;
21 import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
22 import net.sourceforge.phpdt.internal.debug.core.model.PHPVariable;
23 import net.sourceforge.phpdt.internal.debug.core.model.PHPValue;
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.core.runtime.Status;
27 import org.eclipse.debug.core.DebugException;
30 * The interface object are created by the proxy
33 public class PHPDBGInterface {
34 public boolean sessionEnded = false;
35 public int sessType = -1;
36 public int BPUnderHit = 0;
37 public String sessID = new String ();
39 private int[] LastBPRead = new int[10];
40 private Vector DBGBPList = new Vector ();
41 private Vector DBGVarList = new Vector ();
42 private PHPStackFrame[] DBGStackList;
43 private Vector DBGMods = new Vector (); // The module names and their numbers
44 private Vector stackListOld = new Vector ();
45 private BufferedReader in;
46 private OutputStream os; // The stream which goes to DBG
47 private boolean shouldStop = false;
48 private String evalRet = new String ("");
49 private String serGlobals = new String ("");
50 private int rawCounter = 1000; // An rawData frame ID counter
51 private PHPDBGProxy proxy = null;
52 private int lastCmd = -1;
54 private boolean stopOnError = false;
55 private char[] lastCommand = new char[4];
58 * @param in The input stream (communication from DBG).
59 * @param os The output stream (communication to DBG).
60 * @param proxy The proxy to which this interface belongs.
62 public PHPDBGInterface (BufferedReader in, OutputStream os, PHPDBGProxy proxy) {
72 * @param mod_name The module (source file) to which we add the breakpoint.
73 * @param line The line where the breakpoint is set.
74 * @param hitCount The number of hit counts before suspend.
75 * @param condition The break condition
76 * @return Breakpoint ID ???.
78 public int addBreakpoint (String mod_name, int line, int hitCount, String condition) throws IOException {
79 return setBreakpoint (mod_name, condition, line, PHPDBGBase.BPS_ENABLED + PHPDBGBase.BPS_UNRESOLVED, 0, hitCount, 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;
180 PHPDBGFrame DBGFrame3;
183 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);
184 DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_BPS);
185 DBGFrame2 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA);
186 DBGFrame3 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA);
188 modNo = getModByName (mod_name); // Get the module ID by name
190 if (modNo >= 0) { // Did we find a module ID for the module name?
191 DBGFrame1.addInt (modNo); // Add the module ID to frame 1
193 DBGFrame1.addInt (0); // mod number (0 use file name)
196 DBGFrame1.addInt (line); // line number
198 if (modNo >= 0) { // Did we find a module ID for the module name?
199 DBGFrame1.addInt (0); // use mod number
202 DBGFrame1.addInt (rawCounter); // ID of FRAME_RAWDATA to send file name
205 if (modNo < 0) { // Did we find a module ID for the module name?
206 DBGFrame2.addInt (rawCounter); // FRAME_RAWDATA ID
207 DBGFrame2.addInt (mod_name.length() + 1); // length of rawdata (+ null char)
208 DBGFrame2.addString (mod_name); // file name
209 DBGFrame2.addChar ('\0'); // null char
211 DBGPacket.addFrame (DBGFrame2); // First add file name data
214 DBGFrame1.addInt (state); // state BPS_*
215 DBGFrame1.addInt (istemp); // istemp
216 DBGFrame1.addInt (0); // hit count; this is not supported as one might think
217 DBGFrame1.addInt (hitcount); // skip hits is what we think is hit count.
219 if (!condition.equals ("")) { // Do we have a condition for breakpoint
220 rawCounter++; // Set to new ID
221 DBGFrame1.addInt (rawCounter); // ID of condition
223 DBGFrame3.addInt (rawCounter); // FRAME_RAWDATA ID
224 DBGFrame3.addInt (condition.length() + 1); // length of rawdata (+ null char)
225 DBGFrame3.addString (condition); // The break condition
226 DBGFrame3.addChar ('\0'); // null char
228 DBGPacket.addFrame (DBGFrame3); // First add break condition
231 DBGFrame1.addInt (0); // ID of condition is 0, because there is no condition
234 DBGFrame1.addInt (bpno); // breakpoint number
235 DBGFrame1.addInt (isunderhit); // is under hit
237 DBGPacket.addFrame (DBGFrame1); // Second add command data
239 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
243 DBGPacket.sendPacket (os); // Send the request to DBG
247 waitResponse (1000); // Wait for the DBG response (1 second)
248 flushAllPackets (); // Read and process the response from DBG
250 return LastBPRead[8]; // Return what ???
256 private void clearLastBP () {
259 for (i = 0; i < LastBPRead.length; i++) {
267 private void copyToLastBP (int[] BPBody) {
270 for (i = 0; i < LastBPRead.length; i++) {
271 LastBPRead[i] = BPBody[i];
278 public void continueExecution () throws IOException {
279 PHPDBGPacket DBGPacket;
282 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_CONTINUE);
284 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
288 DBGPacket.sendPacket (os); // Send the request to DBG
290 lastCommand = PHPDBGBase.DBGA_CONTINUE; // Store the info about the command we sent
296 public void pauseExecution () throws IOException {
297 PHPDBGPacket DBGPacket;
299 DBGPacket = new PHPDBGPacket (PHPDBGBase.IntToChar4 (PHPDBGBase.DBGC_PAUSE));
301 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
305 DBGPacket.sendPacket (os); // Send the request to DBG
311 private int getBPUnderHit () {
314 int[] dbg_bpl_body = new int[10];
316 for (i = 0; i < DBGBPList.size (); i++) { // look for bp under hit
317 dbg_bpl_body = (int[]) DBGBPList.get (i);
319 if (dbg_bpl_body[9] == 1) {
320 BPUnder = dbg_bpl_body[8];
327 public int getLastCmd()
337 public void setLastCmd (int cmd)
345 public void stepInto () throws IOException {
346 PHPDBGPacket DBGPacket;
349 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPINTO);
351 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
355 DBGPacket.sendPacket (os); // Send the request to DBG
357 lastCommand = PHPDBGBase.DBGA_STEPINTO; // Store the info about the command we sent
363 public void stepOver () throws IOException {
364 PHPDBGPacket DBGPacket;
367 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOVER);
369 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
373 DBGPacket.sendPacket (os); // Send the request to DBG
375 lastCommand = PHPDBGBase.DBGA_STEPOVER; // Store the info about the command we sent
381 public void stepOut () throws IOException {
382 PHPDBGPacket DBGPacket;
385 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOUT);
387 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
391 DBGPacket.sendPacket (os); // Send the request to DBG
393 lastCommand = PHPDBGBase.DBGA_STEPOUT; // Store the info about the command we sent
399 public void stopExecution () throws IOException {
400 PHPDBGPacket DBGPacket;
403 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STOP);
405 if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
409 DBGPacket.sendPacket (os); // Send the request to DBG
413 * This method is called by the proxy.
414 * It sends a request to DBG to get the current variables
415 * with their values. It waits for the response and processes
416 * the input from DBG.
418 * @param stack The stackframe for which we want the variables.
419 * @return The array of variables
421 public synchronized Vector getVariables (PHPStackFrame stack) throws IOException, DebugException {
422 PHPDBGPacket DBGPacket;
423 PHPDBGFrame DBGFrame1;
424 PHPDBGEvalString evalStr;
426 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); //
427 DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_EVAL); //
429 DBGFrame1.addInt (0); // istr = raw data ID
430 DBGFrame1.addInt (1); // scope_id = -1 means current location, 0 never used, +1 first depth
432 DBGPacket.addFrame (DBGFrame1); // Add command data
434 if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication?
435 return new Vector (); // No, then leave here with an empty vector
438 DBGPacket.sendPacket (os); // Send the request to DBG
440 waitResponse (1000); // Wait for the DBG response (1 second)
441 flushAllPackets (); // Read and process the response from DBG
443 evalStr = new PHPDBGEvalString (stack, serGlobals); // Process serialized variables
444 DBGVarList = evalStr.getVariables ();
446 if (DBGVarList.size () > 0) { // Did we get back variables?
447 PHPVariable var = (PHPVariable) DBGVarList.get (0); // Yes, then get the first PHPVariable
448 PHPValue val = (PHPValue) var.getValue (); // Get the value
450 if (var.getName ().equals ("")) { // Is the root node an empty node (usually it is)
451 DBGVarList = val.getChildVariables (); // Then remove the empty node.
452 // With removing the empty root node, it wouldn't be necessary to
453 // set the name to an empty string. So the code below is just for
454 // info or in case the users want to have the empty root node.
456 // The eclipse variable view cannot handle Variables which have an empty name
457 // when it comes to variable tree restore operation. Without a name, no restore!
458 var.setName (" "); // Give a name to the variable root node. Even if it is only a space :-)
459 } // TODO the best would be to remove the empty root node, but this would
460 // require a understanding and reworking of the PHPDBGEvalstring class.
463 return DBGVarList; // Return the variables as list
470 public void log(String logString) throws IOException, DebugException {
471 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
472 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_LOG);
473 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
476 DBGFrame1.addInt(rawCounter); // ilog
477 DBGFrame1.addInt(1); // type
478 DBGFrame1.addInt(0); // mod_no
479 DBGFrame1.addInt(0); // line_no
480 DBGFrame1.addInt(0); // imod_name
481 DBGFrame1.addInt(0); // ext_info
483 DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID
484 DBGFrame2.addInt(logString.length() + 1); // length of rawdata (+ null char)
485 DBGFrame2.addString(logString); // log string
486 DBGFrame2.addChar('\0'); // null char
488 // Add raw data first
489 DBGPacket.addFrame(DBGFrame2);
491 DBGPacket.addFrame(DBGFrame1);
493 if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication?
494 return; // No, then leave here
497 DBGPacket.sendPacket(os);
503 public synchronized PHPVariable[] evalBlock(PHPStackFrame stack, String evalString) throws IOException, DebugException {
504 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
505 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
506 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
509 DBGFrame1.addInt(rawCounter); // istr = raw data ID
510 DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth
512 DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID
513 DBGFrame2.addInt(evalString.length() + 1); // length of rawdata (+ null char)
514 DBGFrame2.addString(evalString); // eval block
515 DBGFrame2.addChar('\0'); // null char
517 // Add raw data first
518 DBGPacket.addFrame(DBGFrame2);
520 DBGPacket.addFrame(DBGFrame1);
522 if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication?
523 return null; // No, then leave here
525 DBGPacket.sendPacket(os);
530 PHPDBGEvalString evalStr=new PHPDBGEvalString(stack,evalRet);
532 return evalStr.getVars();
537 * Read and process everthing we got from DBG
539 public void flushAllPackets () throws IOException {
540 while (readResponse() != 0);
544 * Get the modules name by its number
546 * @param modNo The number (id) of the module
547 * @return The name of the module
549 public String getModByNo (int modNo) {
553 for (i = 0; i < DBGMods.size (); i++) { // For all the modules we have within the array
554 dbg_mod = (PHPDBGMod) DBGMods.get (i); // Get the module
556 if (dbg_mod.getNo () == modNo) { // Is the module from the array the module we want?
557 return dbg_mod.getName (); // Yes, return the name of the module
561 return ""; // If nothing was found return emtpy string
566 * @param modName The name of the module for which we want the ID
568 * - The ID of the module
569 * - -1 if nothing was found
571 private int getModByName (String modName) {
575 for (i = 0; i < DBGMods.size (); i++) { // For all the modules we have within the array
576 dbg_mod = (PHPDBGMod) DBGMods.get (i); // Get the module
578 if (dbg_mod.getName ().equalsIgnoreCase (modName)) { // Is the module from the array the module we want?
579 return dbg_mod.getNo (); // Yes, return the name of the module
583 return -1; // If nothing was found return -1
587 * Return the string for the given frame number
589 * @param framesInfo The buffer which is to read
590 * @param frameNo The frame number
593 private String getRawFrameData (char[] framesInfo, int frameNo) {
594 int nextFrame = 0; // The current read position within the buffer
595 int[] dbg_frame = new int[2]; // The two frame header numbers
597 while (nextFrame < framesInfo.length) { // As long we have something within the buffer
598 dbg_frame[0] = PHPDBGBase.Char4ToInt (framesInfo, nextFrame); // The frame type
599 dbg_frame[1] = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4); // The frame size
601 nextFrame += 8; // The current read position
603 if (dbg_frame[1] == 0) { // If frame size is 0
604 return ""; // return an emtpy string
607 switch (dbg_frame[0]) { // Switch for the frame type
608 case PHPDBGBase.FRAME_RAWDATA: // The only frame type we are interrested in
609 if (frameNo == PHPDBGBase.Char4ToInt (framesInfo, nextFrame)) { // Is it correct number of the frame
612 toRead = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4); // The size of the string
614 if ((int) framesInfo[nextFrame + 8 + toRead - 1] == 0) { // Is there a string termination at the end?
615 return String.copyValueOf (framesInfo, nextFrame + 8, toRead - 1); // Then copy frame content to String without the \0 and return
618 return String.copyValueOf (framesInfo, nextFrame + 8, toRead); // Copy frame content to String and return
623 nextFrame += dbg_frame[1]; // Go for the next frame (add the length of the current one)
626 return ""; // We did not found any FRAM_RAWDATA, so return an emtpy strin
630 * Reset the availability flag for all stackframes in the list.
632 * @param list The list of old stackframes
634 private void resetAvailability (Vector list) {
637 for (i = 0; i < list.size (); i++) {
638 ((PHPStackFrame) list.get(i)).setAvailable (false); //
643 * Check whether the new stackframe is in the list of old stackframes.
644 * Test for identical stackframe (identical means same description and same line number).
646 * @param stackFrameNew The stackframe to check whether he is already within the old stackframe list
647 * @param list The list of old stackframes
649 * - true if we have found the identical stackframe within the list
650 * - false if we did not find the identical stackframe within the list
652 private boolean isStackFrameInList (PHPStackFrame stackFrameNew, Vector list) {
654 PHPStackFrame stackFrameOld;
656 for (i = 0; i < list.size (); i++) {
657 stackFrameOld = (PHPStackFrame) list.get (i); //
659 if (stackFrameNew.getDescription ().equals (stackFrameOld.getDescription ()) &&
660 stackFrameNew.getLineNumber () == stackFrameOld.getLineNumber ()) { // Did we find the sent stackframe within the list of old stackframes?
661 stackFrameOld.setAvailable (true); // We found the new stackframe in the list of old stack frames
662 stackFrameOld.setIndex (stackFrameNew.getIndex ());
663 return true; // The stackframe was found in the list
671 * Check whether the new stackframe is in the list of old stackframes.
672 * Test for exact stackframe (exact means same description and same line number).
674 * @param stackFrameNew The stackframe to check whether he is already within the old stackframe list
675 * @param list The list of old stackframes
677 * - true if we have exactly this stackframe within the list
678 * - false if we did not find the exact stackframe within the list
680 private void markIdenticalStackFrames (Vector oldList, Vector newList) {
682 PHPStackFrame stackFrameNew;
684 resetAvailability (oldList); // Reset the availability flag of the old stack frames
685 resetAvailability (newList); // Reset the availability flag of the old stack frames
687 for (i = 0; i < newList.size (); i++) { // For all stackList entries
688 stackFrameNew = (PHPStackFrame) newList.get (i);
690 if (isStackFrameInList (stackFrameNew, oldList)) { // Is this stackframe in the list
691 stackFrameNew.setAvailable (true); //
700 * The stackList contains the currently read stackframes which were sent
701 * from DBG. The DBG interface holds a list of the active stack frames.
702 * This method replicates the 'static' stackframe list with the DBG stackframe list
703 * Replication is done in the following way:
705 * <li> It looks for new stackframes within the DBG stackframe list and
706 * adds them to the 'static' list.
707 * <li> It looks for stackframes within the 'static' list, and removes them
708 * from the 'static' list in case they do not appear within the DBG list.
709 * <li> It looks for stackframes which are already existent and replicates the
710 * line number and the index number.
711 * <li> At the end, the 'static' stackframe list has to be sorted by the stackframes
715 * Removes the unused stackframes from the list, or adds stackframes which
716 * are not yet in the list.
721 private void updateStackFrameList (Vector stackList) {
724 PHPStackFrame stackFrameNew;
725 PHPStackFrame stackFrameOld;
726 PHPStackFrame[] newStackList;
728 markIdenticalStackFrames (stackListOld, stackList); // Check whether the newly send stack frames can be found in the list
729 // of old stack frames
731 for (i = 0; i < stackList.size (); i++) { // For all stackList entries
732 stackFrameNew = (PHPStackFrame) stackList.get(i);
734 for (n = 0; n < stackListOld.size (); n++) { // For all StackFrames in the StackFrame list
735 stackFrameOld = (PHPStackFrame) stackListOld.get (n); //
737 if (stackFrameOld.isAvailable ()) { // If this stack frame was already found in the new list skip it
741 if (stackFrameNew.getDescription ().equals (stackFrameOld.getDescription ())) {// Did we find the sent stackframe within the list of old stackframes?
742 stackFrameOld.setLineNumber (stackFrameNew.getLineNumber ());
743 stackFrameOld.setIndex (stackFrameNew.getIndex ());
745 stackFrameOld.setAvailable (true); // And mark this stack frame as available
746 stackFrameNew.setAvailable (true); // And mark this stack frame as available
748 break; // Yes, then break;
752 if (!stackFrameNew.isAvailable ()) { // Did not find the new stackframe within the list?
753 stackFrameNew.setAvailable (true); // Mark the stack frame as available and
754 stackListOld.add (stackFrameNew); // then add the new stackframe
758 // And now for removing unused stackframes from list
760 for (n = 0; n < stackListOld.size (); n++) { // For all StackFrames in the StackFrame list
761 stackFrameOld = (PHPStackFrame) stackListOld.get (n); //
764 if (!stackFrameOld.isAvailable ()) {
765 i = stackList.size ();
768 if (i == stackList.size ()) { // Did not find the old stackframe within the list of new ones
769 stackListOld.remove (n); // then remove the old stackframe from list
770 n -= 1; // Adjust the stack list index
774 Collections.sort (stackListOld); // Sort the 'static' stackframe list by the stackframe index numbers.
776 newStackList = new PHPStackFrame[stackListOld.size ()];
777 newStackList = (PHPStackFrame[]) stackListOld.toArray (newStackList);
778 DBGStackList = newStackList;
782 * Read the response from DBG and process the frame
785 * - The received command
786 * - or 0 if something was wrong
788 public int readResponse () throws IOException {
789 int bytesToRead = 0; // The number of byte to read for the current DBG block
790 int nextFrame = 0; // The current read position within entirePack
794 boolean errorStack = false;
795 char[] dbg_header_struct_read = new char[16]; // The buffer for the first 16 bytes of a block
796 int[] dbg_header_struct = new int[4]; // The first four numbers (long) of a block
797 int[] dbg_bpl_tmp = new int[10];
798 int[] dbg_frame = new int[2];
799 int[] dbg_eval_tmp = new int[3];
800 int[] dbg_src_tree_tmp = new int[4]; //
801 int[] dbg_error_tmp = new int[2];
802 Vector rawList = new Vector();
803 Vector stackList = new Vector(); // Intermediate stacklist which is build up in FRAME_STACK frame
809 while (readInput (dbg_header_struct_read, 16) != 0) { // Read 16 byte from input stream
810 dbg_header_struct[0] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 0); // Debug sync header
811 dbg_header_struct[1] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 4); // Command
812 dbg_header_struct[2] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 8); //
813 dbg_header_struct[3] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 12); // Bytes within this block
815 if (dbg_header_struct[0] != 0x5953) { // Check DBG sync bytes
816 return 0; // Wrong header
819 cmdReceived = dbg_header_struct[1]; // Get the command
820 setLastCmd (cmdReceived); // Store the info about the current command
821 bytesToRead = dbg_header_struct[3]; // Get the number of bytes to read for this block
823 //System.out.println("Response Received: " + cmdReceived);
824 char[] entirePack = new char[bytesToRead]; // Store the block data into buffer 'entirePack'
826 if (bytesToRead > 0) { // If there is something within the frame
827 if (readInput (entirePack, bytesToRead) < bytesToRead) { // Read the frame into the buffer
828 return 0; // We did not read enough bytes, error
832 nextFrame = 0; // Start with the first frame
834 while (nextFrame < bytesToRead) { // As long as we have something within this block
835 dbg_frame[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame); // The name of the frame
836 dbg_frame[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // The size of the frame
837 nextFrame += 8; // The next read position
839 if (dbg_frame[1] == 0) { // Something within the frame?
840 return 0; // Nothing to read, error
843 switch (dbg_frame[0]) {
844 case PHPDBGBase.FRAME_STACK:
845 int[] dbg_stack_new = new int[4]; //
847 dbg_stack_new[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // Source line number
848 dbg_stack_new[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // Module number
849 dbg_stack_new[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8); // Scope id
850 dbg_stack_new[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12); // ID of description string
852 if ((dbg_stack_new[1] != 0) && !errorStack) {
853 PHPStackFrame newStack;
856 newStack = new PHPStackFrame (null, // The thread
857 getModByNo (dbg_stack_new[1]), // The name of the module (file)
858 dbg_stack_new[0], // The source line number
860 getRawFrameData (entirePack, // Get the string from this packet
861 dbg_stack_new[3]), // The frame ID for which we want the string
862 dbg_stack_new[1]); // The module number
863 stackList.add (newStack);
869 case PHPDBGBase.FRAME_SOURCE: // Nothing to be done here
870 break; // TODO: what's with that frame? Something interesting
872 case PHPDBGBase.FRAME_SRC_TREE: //
873 dbg_src_tree_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // The parent module number
874 dbg_src_tree_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // The parent line number (not used)
875 dbg_src_tree_tmp[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8); // The module number
876 dbg_src_tree_tmp[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12); // The filename number
878 if (getModByNo (dbg_src_tree_tmp[2]).equals ("")) {
881 fileName = new String (getRawFrameData (entirePack, dbg_src_tree_tmp[3])); // Get the filename
883 if (dbg_src_tree_tmp[2] != 0) { // If there is a module number
886 modNew = new PHPDBGMod (dbg_src_tree_tmp[2], fileName); // Create a module object
888 DBGMods.add (modNew); // And store it to array
893 case PHPDBGBase.FRAME_RAWDATA: // Nothing to be done here
894 break; // FRAME_RAWDATA are processed within getRawFrameData
896 case PHPDBGBase.FRAME_ERROR: // An error frame
897 errorStack = true; // Yes, we have an error stack
898 dbg_error_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // Error type
899 dbg_error_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // Error message ID
901 String error = "\n"; //
903 switch (dbg_error_tmp[0]) { // Switch on error type
904 case PHPDBGBase.E_ERROR: error += "[Error]"; break;
905 case PHPDBGBase.E_WARNING: error += "[Warning]"; break;
906 case PHPDBGBase.E_PARSE: error += "[Parse Error]"; break;
907 case PHPDBGBase.E_NOTICE: error += "[Notice]"; break;
908 case PHPDBGBase.E_CORE_ERROR: error += "[Core Error]"; break;
909 case PHPDBGBase.E_CORE_WARNING: error += "[Core Warning]"; break;
910 case PHPDBGBase.E_COMPILE_ERROR: error += "[Compile Error]"; break;
911 case PHPDBGBase.E_COMPILE_WARNING: error += "[Compile Warning]"; break;
912 case PHPDBGBase.E_USER_ERROR: error += "[User Error]"; break;
913 case PHPDBGBase.E_USER_WARNING: error += "[User Warning]"; break;
914 case PHPDBGBase.E_USER_NOTICE: error += "[User Notice]"; break;
915 default: error += "[Unexpected Error]"; break;
919 error += new String (getRawFrameData (entirePack, dbg_error_tmp[1])); // Add the error string for this error message ID
920 error += "\n"; // Append a CR
922 PHPDebugCorePlugin.log (new DebugException (new Status (IStatus.WARNING,
923 PHPDebugCorePlugin.PLUGIN_ID,
927 // To print errors on the console, I must execute a code in the
928 // php context, that write the stderr... I didn't found a better way
929 // TODO: Find a better way????
931 // String codeExec= "";
932 // codeExec= "fwrite(fopen('php://stderr', 'w'),\\\"" + error + "\\\");";
934 // evalBlock("eval(\"" + codeExec + "\");");
935 // } catch (DebugException e) {
936 // PHPDebugCorePlugin.log(e);
939 if (!stopOnError) { // Is always false (Did not see where this is set to true!?)
940 if (lastCommand.equals (PHPDBGBase.DBGA_CONTINUE)) { // If last command for PHP was a 'continue',
941 continueExecution (); // send continue again
942 } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPINTO)) { // If last command for PHP was a 'step into',
943 stepInto (); // send 'step into' again
944 } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPOUT)) { // If last command for PHP was a 'step out',
945 stepOut (); // send 'step out' again
946 } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPOVER)) { // If last command for PHP was a 'step over',
947 stepOver (); // send 'step over' again
952 case PHPDBGBase.FRAME_EVAL:
955 evalString = new String ("");
956 dbg_eval_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0); // istr
957 dbg_eval_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4); // iresult
958 dbg_eval_tmp[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8); // ierror
960 evalRet = getRawFrameData (entirePack, dbg_eval_tmp[1]); //
961 evalString = getRawFrameData (entirePack, dbg_eval_tmp[0]); //
962 serGlobals = evalRet; //
965 case PHPDBGBase.FRAME_BPS: //
968 case PHPDBGBase.FRAME_BPL:
971 dbg_bpl_new = new int[10];
972 dbg_bpl_new[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0);
973 dbg_bpl_new[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4);
974 dbg_bpl_new[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8);
975 dbg_bpl_new[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12);
976 dbg_bpl_new[4] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 16);
977 dbg_bpl_new[5] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 20);
978 dbg_bpl_new[6] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 24);
979 dbg_bpl_new[7] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 28);
980 dbg_bpl_new[8] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 32);
981 dbg_bpl_new[9] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 36);
983 // look if breakpoint already exists in vector
984 for (i = 0; i < DBGBPList.size (); i++) {
985 dbg_bpl_tmp = (int[]) DBGBPList.get (i);
987 if (dbg_bpl_tmp[8] == dbg_bpl_new[8]) {
988 DBGBPList.remove (i);
994 // add breakpoint to vector
995 DBGBPList.add (dbg_bpl_new);
996 copyToLastBP (dbg_bpl_new);
999 if (getModByNo (dbg_bpl_new[0]).equals ("")) {
1002 fileName = new String (getRawFrameData (entirePack, dbg_bpl_new[2]));
1004 if (dbg_bpl_new[0] != 0) {
1007 modNew = new PHPDBGMod (dbg_bpl_new[0], fileName);
1009 DBGMods.add (modNew);
1014 case PHPDBGBase.FRAME_VER:
1017 case PHPDBGBase.FRAME_SID:
1018 sid = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
1021 case PHPDBGBase.FRAME_SRCLINESINFO:
1024 case PHPDBGBase.FRAME_SRCCTXINFO:
1027 case PHPDBGBase.FRAME_LOG:
1030 case PHPDBGBase.FRAME_PROF:
1033 case PHPDBGBase.FRAME_PROF_C:
1036 case PHPDBGBase.FRAME_SET_OPT:
1040 nextFrame += dbg_frame[1]; // go to next frame
1043 // Now process command
1044 switch(cmdReceived) {
1045 case PHPDBGBase.DBGC_REPLY:
1048 case PHPDBGBase.DBGC_STARTUP:
1051 case PHPDBGBase.DBGC_END:
1052 sessionEnded = true;
1053 this.proxy.setTerminated();
1056 case PHPDBGBase.DBGC_BREAKPOINT:
1057 BPUnderHit = getBPUnderHit ();
1058 updateStackFrameList (stackList);
1061 case PHPDBGBase.DBGC_STEPINTO_DONE:
1062 case PHPDBGBase.DBGC_STEPOVER_DONE:
1063 case PHPDBGBase.DBGC_STEPOUT_DONE:
1064 case PHPDBGBase.DBGC_EMBEDDED_BREAK:
1065 case PHPDBGBase.DBGC_PAUSE:
1067 updateStackFrameList (stackList);
1070 case PHPDBGBase.DBGC_ERROR:
1072 updateStackFrameList (stackList);
1075 case PHPDBGBase.DBGC_LOG:
1078 case PHPDBGBase.DBGC_SID:
1083 return cmdReceived; // Return the command we received with this block
1090 public PHPStackFrame[] getStackList() {
1091 return DBGStackList;
1095 * Reads from input buffer (response sent from DBG) the given number of chars
1096 * into frame buffer.
1098 * @param buffer The frame buffer where to store the read data from DBG.
1099 * @param bytes The number of bytes (chars) which are to read from input stream.
1100 * @return The number of bytes actually read.
1102 private int readInput (char[] buffer, int bytes) throws IOException {
1103 int bytesRead = 0; // Reset the bytes read counter
1105 for (int i = 0; i < bytes; i++) { // For the number of bytes we should read
1106 if (in.ready ()) { // If input stream is ready for reading
1107 buffer[i] = (char) (in.read () & 0x00FF); // Read a char and store only the least significant 8-bits
1108 bytesRead++; // Increment the bytes read counter
1110 else { // Input stream is not ready
1111 break; // Break the loop
1115 return bytesRead; // Return the number of bytes actually read
1119 * PHPProxy could stop the waiting for a response with this method.
1122 public void setShouldStop () {
1123 this.shouldStop = true;
1127 * @param milliseconds The maximum time in milliseconds we wait for something
1128 * to be send from DBG.
1129 * @return - true if something was received from DBG
1130 * - false if nothing was send from DBG within the given time
1133 public boolean waitResponse (long milliseconds) throws IOException {
1136 timeout = System.currentTimeMillis () + milliseconds; // Calculate the system time till we wait.
1138 while (System.currentTimeMillis () < timeout) { // Is waiting time running out?
1139 if (in.ready () || shouldStop) { // No, so did we get something or should we stop now
1140 break; // Yes, break the waiting
1144 return in.ready (); // true if we got something from DBG