1) Made getVariables and evalBlock methods in PHPDBGInterface synchronized (At least...
[phpeclipse.git] / net.sourceforge.phpeclipse.debug.core / src / net / sourceforge / phpdt / internal / debug / core / PHPDBGInterface.java
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
7
8 Contributors:
9         Vicente Fernando - www.alfersoft.com.ar - Initial implementation
10         Christian Perkonig - remote debug
11 **********************************************************************/
12 package net.sourceforge.phpdt.internal.debug.core;
13
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;
19
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;
24
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.core.runtime.Status;
27 import org.eclipse.debug.core.DebugException;
28
29 /**
30  * The interface object are created by the proxy
31  *
32  */
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 ();
38
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;
53         private int                     sid                      = 0;
54         private boolean                 stopOnError      = false;
55         private char[]                  lastCommand      = new char[4];
56
57         /**
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.
61          */
62         public PHPDBGInterface (BufferedReader in, OutputStream os, PHPDBGProxy proxy) {
63                 DBGBPList.clear ();
64
65                 this.in         = in;
66                 this.os         = os;
67                 this.proxy      = proxy;
68         }
69
70         /**
71          *
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 ???.
77          */
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);
80         }
81
82         /**
83          *
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 ???.
87          */
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);
90         }
91
92         /**
93          * Is this method used anywhere?
94          *
95          */
96         public void requestDBGVersion () throws IOException {
97                 PHPDBGPacket DBGPacket;                                     // A DBG message packet
98                 PHPDBGFrame  DBGFrame;                                      // A frame within a DBG packet
99
100                 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);     // A request for DBG
101                 DBGFrame  = new PHPDBGFrame (PHPDBGBase.FRAME_VER);         // We want the version of DBG
102
103                 DBGPacket.addFrame (DBGFrame);                              // Add the 'what we want' to the DBG packet
104
105                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
106                         return;                                                 //  No
107                 }
108
109                 DBGPacket.sendPacket (os);                                                                      // Send the request to DBG
110         }
111
112         /**
113          * Called by the proxy
114          *
115          */
116         public void getSourceTree () throws IOException {
117                 PHPDBGPacket DBGPacket;                                     // A DBG message packet
118                 PHPDBGFrame  DBGFrame;                                      // A frame within a DBG packet
119
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
122
123                 DBGPacket.addFrame (DBGFrame);                              // Add the 'what we want' to the DBG packet
124
125                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
126                         return;                                                                                                 //  No
127                 }
128
129                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
130
131                 waitResponse (1000);                                        // Wait for the DBG response (1 second)
132                 flushAllPackets ();                                                                             // Read and process the response from DBG
133         }
134
135         /**
136          * Is this method called from anywhere?
137          *
138          * @param modName The modul (filename).
139          */
140         public void addDBGModName (String modName) throws IOException {
141                 PHPDBGPacket DBGPacket;                                     // A DBG message packet
142                 PHPDBGFrame  DBGFrame;                                      // A frame within a DBG packet
143
144                 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);     // A request for DBG
145                 DBGFrame  = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA);     // We want Module name from DBG
146
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
152
153                 DBGPacket.addFrame (DBGFrame);
154
155                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
156                         return;                                                                                                 //  No
157                 }
158
159                 DBGPacket.sendPacket (os);
160         }
161
162         /**
163          * This method is called for adding or removing breakpoints.
164          *
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    ???
174          * @return
175          */
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;
181                 int                     modNo;
182
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);
187
188                 modNo           = getModByName (mod_name);                                              // Get the module ID by name
189
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
192                 } else {
193                         DBGFrame1.addInt (0);                                                                   // mod number (0 use file name)
194                 }
195
196                 DBGFrame1.addInt (line);                                                                        // line number
197
198                 if (modNo >= 0) {                                           // Did we find a module ID for the module name?
199                         DBGFrame1.addInt (0);                                                                   // use mod number
200                 } else {
201                         rawCounter++;
202                         DBGFrame1.addInt (rawCounter);                                                  // ID of FRAME_RAWDATA to send file name
203                 }
204
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
210
211                         DBGPacket.addFrame (DBGFrame2);                         // First add file name data
212                 }
213
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.
218
219                 if (!condition.equals ("")) {                                                           // Do we have a condition for breakpoint
220                         rawCounter++;                                                                                   // Set to new ID
221                         DBGFrame1.addInt (rawCounter);                          // ID of condition
222
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
227
228                         DBGPacket.addFrame (DBGFrame3);                         // First add break condition
229                 }
230                 else {
231                         DBGFrame1.addInt (0);                                           // ID of condition is 0, because there is no condition
232                 }
233
234                 DBGFrame1.addInt (bpno);                                            // breakpoint number
235                 DBGFrame1.addInt (isunderhit);                                  // is under hit
236
237                 DBGPacket.addFrame (DBGFrame1);                                                         // Second add command data
238
239                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
240                         return 0;                                               //  No
241                 }
242
243                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
244
245                 clearLastBP ();
246
247                 waitResponse (1000);                                        // Wait for the DBG response (1 second)
248                 flushAllPackets ();                                         // Read and process the response from DBG
249
250                 return LastBPRead[8];                                                                           // Return what ???
251         }
252
253         /**
254          *
255          */
256         private void clearLastBP () {
257                 int i;
258
259                 for (i = 0; i < LastBPRead.length; i++) {
260                         LastBPRead[i] = 0;
261                 }
262         }
263
264         /**
265          *
266          */
267         private void copyToLastBP (int[] BPBody) {
268                 int i;
269
270                 for (i = 0; i < LastBPRead.length; i++) {
271                         LastBPRead[i] = BPBody[i];
272                 }
273         }
274
275         /**
276          *
277          */
278         public void continueExecution () throws IOException {
279                 PHPDBGPacket DBGPacket;
280
281                 BPUnderHit = 0;
282                 DBGPacket  = new PHPDBGPacket (PHPDBGBase.DBGA_CONTINUE);
283
284                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
285                         return;                                                 //  No
286                 }
287
288                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
289
290                 lastCommand = PHPDBGBase.DBGA_CONTINUE;                     // Store the info about the command we sent
291         }
292
293         /**
294          *
295          */
296         public void pauseExecution () throws IOException {
297                 PHPDBGPacket DBGPacket;
298
299                 DBGPacket = new PHPDBGPacket (PHPDBGBase.IntToChar4 (PHPDBGBase.DBGC_PAUSE));
300
301                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
302                          return;                                                //  No
303                 }
304
305                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
306         }
307
308         /**
309          *
310          */
311         private int getBPUnderHit () {
312                 int i;
313                 int BPUnder             = 0;
314                 int[] dbg_bpl_body      = new int[10];
315
316                 for (i = 0; i < DBGBPList.size (); i++) {                               // look for bp under hit
317                         dbg_bpl_body = (int[]) DBGBPList.get (i);
318
319                         if (dbg_bpl_body[9] == 1) {
320                                 BPUnder = dbg_bpl_body[8];
321                         }
322                 }
323
324                 return BPUnder;
325         }
326
327         public int getLastCmd()
328         {
329                 return lastCmd;
330         }
331
332         public int getSID()
333         {
334           return sid;
335         }
336
337         public void setLastCmd (int cmd)
338         {
339                 lastCmd = cmd;
340         }
341
342         /**
343          *
344          */
345         public void stepInto () throws IOException {
346                 PHPDBGPacket DBGPacket;
347
348                 BPUnderHit = 0;
349                 DBGPacket  = new PHPDBGPacket (PHPDBGBase.DBGA_STEPINTO);
350
351                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
352                         return;                                                 //  No
353                 }
354
355                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
356
357                 lastCommand = PHPDBGBase.DBGA_STEPINTO;                                         // Store the info about the command we sent
358         }
359
360         /**
361          *
362          */
363         public void stepOver () throws IOException {
364                 PHPDBGPacket DBGPacket;
365
366                 BPUnderHit = 0;
367                 DBGPacket  = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOVER);
368
369                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
370                         return;                                                 //  No
371                 }
372
373                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
374
375                 lastCommand = PHPDBGBase.DBGA_STEPOVER;                     // Store the info about the command we sent
376         }
377
378         /**
379          *
380          */
381         public void stepOut () throws IOException {
382                 PHPDBGPacket DBGPacket;
383
384                 BPUnderHit = 0;
385                 DBGPacket  = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOUT);
386
387                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
388                         return;                                                 //  No
389                 }
390
391                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
392
393                 lastCommand = PHPDBGBase.DBGA_STEPOUT;                      // Store the info about the command we sent
394         }
395
396         /**
397          *
398          */
399         public void stopExecution () throws IOException {
400                 PHPDBGPacket DBGPacket;
401
402                 BPUnderHit = 0;
403                 DBGPacket  = new PHPDBGPacket (PHPDBGBase.DBGA_STOP);
404
405                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
406                         return;                                                 //  No
407                 }
408
409                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
410         }
411
412         /**
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.
417          *
418          * @param stack The stackframe for which we want the variables.
419          * @return      The array of variables
420          */
421         public synchronized Vector getVariables (PHPStackFrame stack) throws IOException, DebugException  {
422                 PHPDBGPacket            DBGPacket;
423                 PHPDBGFrame             DBGFrame1;
424                 PHPDBGEvalString        evalStr;
425
426                 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);     //
427             DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_EVAL);        //
428
429                 DBGFrame1.addInt (0);                                                                           // istr = raw data ID
430                 DBGFrame1.addInt (1);                                                                           // scope_id = -1 means current location, 0 never used, +1 first depth
431
432                 DBGPacket.addFrame (DBGFrame1);                             // Add command data
433
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 
436                 }
437
438                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
439
440                 waitResponse (1000);                                        // Wait for the DBG response (1 second)
441                 flushAllPackets ();                                         // Read and process the response from DBG
442
443                 evalStr         = new PHPDBGEvalString (stack, serGlobals); // Process serialized variables
444                 DBGVarList      = evalStr.getVariables ();
445
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
449
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.
455
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.
461                 }
462
463                 return DBGVarList;                                                                                      // Return the variables as list
464         }
465
466         /**
467          *
468          * @param logString
469          */
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);
474
475                 rawCounter++;
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
482
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
487
488                 // Add raw data first
489                 DBGPacket.addFrame(DBGFrame2);
490                 // Add command data
491                 DBGPacket.addFrame(DBGFrame1);
492
493                 if (proxy.getSocket ().isClosed ()) {                   // Do we have a socket for DBG communication?
494                         return;                                                                                         //  No, then leave here
495                 }
496
497                 DBGPacket.sendPacket(os);
498
499                 waitResponse(1000);
500                 flushAllPackets();
501         }
502
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);
507
508                 rawCounter++;
509                 DBGFrame1.addInt(rawCounter);                           // istr = raw data ID
510                 DBGFrame1.addInt(1);                                            // scope_id = -1 means current location, 0 never used, +1 first depth
511
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
516
517                 // Add raw data first
518                 DBGPacket.addFrame(DBGFrame2);
519                 // Add command data
520                 DBGPacket.addFrame(DBGFrame1);
521
522                 if (proxy.getSocket ().isClosed ()) {                       // Do we have a socket for DBG communication?
523                         return null;                                                                                    //  No, then leave here
524                 }
525                 DBGPacket.sendPacket(os);
526
527                 waitResponse(1000);
528                 flushAllPackets();
529
530                 PHPDBGEvalString evalStr=new PHPDBGEvalString(stack,evalRet);
531
532                 return evalStr.getVars();
533
534         }
535
536         /**
537          * Read and process everthing we got from DBG
538          */
539         public void flushAllPackets () throws IOException {
540                 while (readResponse() != 0);
541         }
542
543         /**
544          * Get the modules name by its number
545          *
546          * @param modNo The number (id) of the module
547          * @return      The name of the module
548          */
549         public String getModByNo (int modNo) {
550                 int             i;
551                 PHPDBGMod       dbg_mod;
552
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
555
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
558                         }
559                 }
560
561                 return "";                                                      // If nothing was found return emtpy string
562         }
563
564         /**
565          *
566          * @param  modName The name of the module for which we want the ID
567          * @return
568          * - The ID of the module
569          * - -1 if nothing was found
570          */
571         private int getModByName (String modName) {
572                 int             i;
573                 PHPDBGMod       dbg_mod;
574
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
577
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
580                         }
581                 }
582
583                 return -1;                                                      // If nothing was found return -1
584         }
585
586         /**
587          * Return the string for the given frame number
588          *
589          * @param framesInfo The buffer which is to read
590          * @param frameNo    The frame number
591          * @return
592          */
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
596
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
600
601                         nextFrame   += 8;                                                   // The current read position
602
603                         if (dbg_frame[1] == 0) {                                            // If frame size is 0
604                                 return "";                                                      //  return an emtpy string
605                         }
606
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
610                                                 int toRead;                                                     //
611
612                                                 toRead = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4);     // The size of the string
613
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
616                                                 }
617
618                                                 return String.copyValueOf (framesInfo, nextFrame + 8, toRead);  // Copy frame content to String and return
619                                         }
620                                         break;
621                         }
622
623                         nextFrame += dbg_frame[1];                                                                      // Go for the next frame (add the length of the current one)
624                 }
625
626                 return "";                                                                                                                                              // We did not found any FRAM_RAWDATA, so return an emtpy strin
627         }
628
629         /**
630          * Reset the availability flag for all stackframes in the list.
631          *
632          * @param list          The list of old stackframes
633          */
634         private void resetAvailability (Vector list) {
635                 int             i;
636
637                 for (i = 0; i < list.size (); i++) {
638                         ((PHPStackFrame) list.get(i)).setAvailable (false);                                     //
639                 }
640         }
641
642         /**
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).
645          *
646          * @param stackFrameNew The stackframe to check whether he is already within the old stackframe list
647          * @param list          The list of old stackframes
648          * @return
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
651          */
652         private boolean isStackFrameInList (PHPStackFrame stackFrameNew, Vector list) {
653                 int             i;
654                 PHPStackFrame   stackFrameOld;
655
656                 for (i = 0; i < list.size (); i++) {
657                         stackFrameOld = (PHPStackFrame) list.get (i);                                           //
658
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
664                         }
665                 }
666
667                 return false;
668         }
669
670         /**
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).
673          *
674          * @param stackFrameNew The stackframe to check whether he is already within the old stackframe list
675          * @param list          The list of old stackframes
676          * @return
677          *  - true if we have exactly this stackframe within the list
678          *  - false if we did not find the exact stackframe within the list
679          */
680         private void markIdenticalStackFrames (Vector oldList, Vector newList) {
681                 int             i;
682                 PHPStackFrame   stackFrameNew;
683
684                 resetAvailability (oldList);                                                    // Reset the availability flag of the old stack frames
685                 resetAvailability (newList);                                                    // Reset the availability flag of the old stack frames
686
687                 for (i = 0; i < newList.size (); i++) {                                                                                 // For all stackList entries
688                         stackFrameNew = (PHPStackFrame) newList.get (i);
689
690                         if (isStackFrameInList (stackFrameNew, oldList)) {                          // Is this stackframe in the list
691                                 stackFrameNew.setAvailable (true);                                                                              //
692                                                                                                                                                                                 //
693                                 break;
694                         }
695                 }
696         }
697
698         /**
699          *
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:
704          * <ul>
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
712          *              index numbers.
713          * </ul>
714          *
715          * Removes the unused stackframes from the list, or adds stackframes which
716          * are not yet in the list.
717          *
718          *
719          * @param stackList
720          */
721         private void updateStackFrameList (Vector stackList) {
722                 int                     i;
723                 int             n;
724                 PHPStackFrame   stackFrameNew;
725                 PHPStackFrame   stackFrameOld;
726                 PHPStackFrame[] newStackList;
727
728                 markIdenticalStackFrames (stackListOld, stackList);                     // Check whether the newly send stack frames can be found in the list
729                                                                                                                                                                 // of old stack frames
730
731                 for (i = 0; i < stackList.size (); i++) {                                                               // For all stackList entries
732                         stackFrameNew = (PHPStackFrame) stackList.get(i);
733
734                         for (n = 0; n < stackListOld.size (); n++) {                                    // For all StackFrames in the StackFrame list
735                                 stackFrameOld = (PHPStackFrame) stackListOld.get (n);                   //
736
737                                 if (stackFrameOld.isAvailable ()) {                             // If this stack frame was already found in the new list skip it
738                                         continue;
739                                 }
740
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 ());
744
745                                         stackFrameOld.setAvailable (true);                                                      // And mark this stack frame as available
746                                         stackFrameNew.setAvailable (true);                                                      // And mark this stack frame as available
747
748                                         break;                                                                  //  Yes, then break;
749                                 }
750                         }
751
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
755                         }
756                 }
757
758                 // And now for removing unused stackframes from list
759
760                 for (n = 0; n < stackListOld.size (); n++) {                                            // For all StackFrames in the StackFrame list
761                         stackFrameOld = (PHPStackFrame) stackListOld.get (n);                           //
762
763                         i = 0;
764                         if (!stackFrameOld.isAvailable ()) {
765                                 i = stackList.size ();
766                         }
767
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
771                         }
772                 }
773
774                 Collections.sort (stackListOld);                                                                                // Sort the 'static' stackframe list by the stackframe index numbers.
775                                                                                                                                                                 //
776                 newStackList = new PHPStackFrame[stackListOld.size ()];
777                 newStackList = (PHPStackFrame[]) stackListOld.toArray (newStackList);
778                 DBGStackList = newStackList;
779         }
780
781     /**
782      * Read the response from DBG and process the frame
783      *
784          * @return
785          * - The received command
786          * - or 0 if something was wrong
787      */
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
791         int     i                      = 0;
792         int     cmdReceived            = 0;
793         int     stackIndex             = 0;
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
804
805         rawList.clear ();
806         stackList.clear ();
807
808                 // Read from input
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
814
815             if (dbg_header_struct[0] != 0x5953) {                                           // Check DBG sync bytes
816                 return 0;                                                                   // Wrong header
817             }
818
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
822
823                         //System.out.println("Response Received: " + cmdReceived);
824                         char[] entirePack = new char[bytesToRead];                                      // Store the block data into buffer 'entirePack'
825
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
829                 }
830                         }
831                         
832                         nextFrame = 0;                                                                  // Start with the first frame
833
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
838
839                                 if (dbg_frame[1] == 0) {                                                    // Something within the frame?
840                                         return 0;                                                               //  Nothing to read, error
841                                 }
842
843                                 switch (dbg_frame[0]) {
844                                         case PHPDBGBase.FRAME_STACK:
845                                                 int[] dbg_stack_new = new int[4];                                       //
846
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
851
852                                                 if ((dbg_stack_new[1] != 0) && !errorStack) {
853                                                         PHPStackFrame newStack;
854
855                                                         stackIndex++;
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
859                                                                                                                   stackIndex,
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);
864                                                 }
865
866                                                 errorStack = false;
867                                                 break;
868
869                                         case PHPDBGBase.FRAME_SOURCE:                                                   // Nothing to be done here
870                                                 break;                                                                      // TODO: what's with that frame? Something interesting
871
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
877
878                                                 if (getModByNo (dbg_src_tree_tmp[2]).equals ("")) {
879                                                         String fileName;
880
881                                                         fileName = new String (getRawFrameData (entirePack, dbg_src_tree_tmp[3]));      // Get the filename
882
883                                                         if (dbg_src_tree_tmp[2] != 0) {                                             // If there is a module number
884                                                                 PHPDBGMod modNew;
885
886                                                                 modNew = new PHPDBGMod (dbg_src_tree_tmp[2], fileName);                 // Create a module object
887
888                                                                 DBGMods.add (modNew);                                                   // And store it to array
889                                                         }
890                                                 }
891                                                 break;
892
893                                         case PHPDBGBase.FRAME_RAWDATA:                                                      // Nothing to be done here
894                                                 break;                                                                          //  FRAME_RAWDATA are processed within getRawFrameData
895
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
900
901                                                 String error = "\n";                                                            //
902
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;
916                                                 }
917
918                                                 error += ": ";
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
921
922                                                 PHPDebugCorePlugin.log (new DebugException (new Status (IStatus.WARNING,
923                                                                                                         PHPDebugCorePlugin.PLUGIN_ID,
924                                                                                                                                                                 IStatus.OK,
925                                                                                                                                                                 error, null)));
926
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????
930
931 //                                              String codeExec= "";
932 //                                              codeExec= "fwrite(fopen('php://stderr', 'w'),\\\"" + error + "\\\");";
933 //                                              try {
934 //                                                      evalBlock("eval(\"" + codeExec + "\");");
935 //                                              } catch (DebugException e) {
936 //                                                      PHPDebugCorePlugin.log(e);
937 //                                              }
938 //
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
948                                                         }
949                                                 }
950                                                 break;
951
952                                         case PHPDBGBase.FRAME_EVAL:
953                                                 String evalString;
954
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
959
960                                                 evalRet                 = getRawFrameData (entirePack, dbg_eval_tmp[1]);                //
961                                                 evalString              = getRawFrameData (entirePack, dbg_eval_tmp[0]);                //
962                                                 serGlobals              = evalRet;                                                      //
963                                                 break;
964
965                                         case PHPDBGBase.FRAME_BPS:                                                          //
966                                                 break;                                                                          //
967
968                                         case PHPDBGBase.FRAME_BPL:
969                                                 int[] dbg_bpl_new;
970
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);
982
983                                                 // look if breakpoint already exists in vector
984                                                 for (i = 0; i < DBGBPList.size (); i++) {
985                                                         dbg_bpl_tmp = (int[]) DBGBPList.get (i);
986
987                                                         if (dbg_bpl_tmp[8] == dbg_bpl_new[8]) {
988                                                                 DBGBPList.remove (i);
989
990                                                                 break;
991                                                         }
992                                                 }
993
994                                                 // add breakpoint to vector
995                                                 DBGBPList.add (dbg_bpl_new);
996                                                 copyToLastBP (dbg_bpl_new);
997
998                                                 // mod no returned?
999                                                 if (getModByNo (dbg_bpl_new[0]).equals ("")) {
1000                                                         String fileName;
1001
1002                                                         fileName = new String (getRawFrameData (entirePack, dbg_bpl_new[2]));
1003
1004                                                         if (dbg_bpl_new[0] != 0) {
1005                                                                 PHPDBGMod modNew;
1006
1007                                                                 modNew = new PHPDBGMod (dbg_bpl_new[0], fileName);
1008
1009                                                                 DBGMods.add (modNew);
1010                                                         }
1011                                                 }
1012                                                 break;
1013
1014                                         case PHPDBGBase.FRAME_VER:
1015                                                 break;
1016
1017                                         case PHPDBGBase.FRAME_SID:
1018                                                 sid = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
1019                                                 break;
1020
1021                                         case PHPDBGBase.FRAME_SRCLINESINFO:
1022                                                 break;
1023
1024                                         case PHPDBGBase.FRAME_SRCCTXINFO:
1025                                                 break;
1026
1027                                         case PHPDBGBase.FRAME_LOG:
1028                                                 break;
1029
1030                                         case PHPDBGBase.FRAME_PROF:
1031                                                 break;
1032
1033                                         case PHPDBGBase.FRAME_PROF_C:
1034                                                 break;
1035
1036                                         case PHPDBGBase.FRAME_SET_OPT:
1037                                                 break;
1038                                 }
1039
1040                                 nextFrame += dbg_frame[1];                                                      // go to next frame
1041                         }
1042
1043                         // Now process command
1044                         switch(cmdReceived) {
1045                                 case PHPDBGBase.DBGC_REPLY:
1046                                         break;
1047
1048                                 case PHPDBGBase.DBGC_STARTUP:
1049                                         break;
1050
1051                                 case PHPDBGBase.DBGC_END:
1052                                         sessionEnded = true;
1053                                         this.proxy.setTerminated();
1054                                         break;
1055
1056                                 case PHPDBGBase.DBGC_BREAKPOINT:
1057                                         BPUnderHit   = getBPUnderHit ();
1058                                         updateStackFrameList (stackList);
1059                                         break;
1060
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:
1066                                         BPUnderHit   = 1;
1067                                         updateStackFrameList (stackList);
1068                                         break;
1069
1070                                 case PHPDBGBase.DBGC_ERROR:
1071                                         stackList.clear ();
1072                                         updateStackFrameList (stackList);
1073                                         break;
1074
1075                                 case PHPDBGBase.DBGC_LOG:
1076                                         break;
1077
1078                                 case PHPDBGBase.DBGC_SID:
1079                                         break;
1080                         }
1081                 }
1082
1083                 return cmdReceived;                                         // Return the command we received with this block
1084         }
1085
1086     /**
1087      *
1088      */
1089
1090         public PHPStackFrame[] getStackList() {
1091                 return DBGStackList;
1092         }
1093
1094         /**
1095          * Reads from input buffer (response sent from DBG) the given number of chars
1096          * into frame buffer.
1097          *
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.
1101          */
1102         private int readInput (char[] buffer, int bytes) throws IOException {
1103                 int bytesRead = 0;                                                                                      // Reset the bytes read counter
1104
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
1109                         }
1110                         else {                                                  // Input stream is not ready
1111                                 break;                                              // Break the loop
1112                         }
1113                 }
1114
1115                 return bytesRead;                                                                                       // Return the number of bytes actually read
1116         }
1117
1118         /**
1119          * PHPProxy could stop the waiting for a response with this method.
1120          *
1121          */
1122         public void setShouldStop () {
1123                 this.shouldStop = true;
1124         }
1125
1126         /**
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
1131          *
1132          */
1133         public boolean waitResponse (long milliseconds) throws IOException {
1134                 long timeout;
1135
1136                 timeout = System.currentTimeMillis () + milliseconds;           // Calculate the system time till we wait.
1137
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
1141                         }
1142                 }
1143
1144                 return in.ready ();                                         // true if we got something from DBG
1145         }
1146 }