1) A temporary fix for the recursion problem with the $GLOBALS array.
[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 import java.io.RandomAccessFile;
30
31 /**
32  * The interface object are created by the proxy
33  *
34  */
35 public class PHPDBGInterface {
36
37         public boolean                  sessionEnded = false;
38         public int                              sessType         = -1;
39         public int                              BPUnderHit       = 0;
40         public String                   sessID           = new String ();
41
42         private int[]                   LastBPRead   = new int[10];
43         private Vector                  DBGBPList    = new Vector ();
44         private Vector          DBGVarList   = new Vector ();
45         private PHPStackFrame[] DBGStackList;
46         private Vector                  DBGMods          = new Vector ();                       // The module names and their numbers
47         private Vector          stackListOld = new Vector ();
48         private BufferedReader  in;
49         private OutputStream    os;                                                                             // The stream which goes to DBG
50         private boolean                 shouldStop       = false;
51         private String                  evalRet          = new String ("");
52         private String                  serGlobals       = new String ("");
53         private int                     rawCounter       = 1000;                                        // An rawData frame ID counter
54         private PHPDBGProxy     proxy            = null;
55         private int                     lastCmd          = -1;
56         private int                     sid                      = 0;
57         private boolean                 stopOnError      = false;
58         private char[]                  lastCommand      = new char[4];
59
60         /**
61          * @param in    The input stream (communication from DBG).
62          * @param os    The output stream (communication to DBG).
63          * @param proxy The proxy to which this interface belongs.
64          */
65         public PHPDBGInterface (BufferedReader in, OutputStream os, PHPDBGProxy proxy) {
66                 DBGBPList.clear ();
67
68                 this.in         = in;
69                 this.os         = os;
70                 this.proxy      = proxy;
71         }
72
73         /**
74          *
75          * @param mod_name The module (source file) to which we add the breakpoint.
76          * @param line     The line where the breakpoint is set.
77          * @return         Breakpoint ID ???.
78          */
79         public int addBreakpoint (String mod_name, int line) throws IOException {
80                 return setBreakpoint (mod_name, "", line, PHPDBGBase.BPS_ENABLED + PHPDBGBase.BPS_UNRESOLVED, 0, 0, 0, 0, 0);
81         }
82
83         /**
84          *
85          * @param mod_name The module (source file) to which we add the breakpoint.
86          * @param line     The line where the breakpoint is set.
87          * @param bpNo     The breakpoint ID ???.
88          */
89         public void removeBreakpoint (String mod_name, int line, int bpNo) throws IOException {
90                 setBreakpoint (mod_name, "", line, PHPDBGBase.BPS_DISABLED, 0, 0, 0, bpNo, 0);
91         }
92
93         /**
94          * Is this method used anywhere?
95          *
96          */
97         public void requestDBGVersion () throws IOException {
98                 PHPDBGPacket DBGPacket;                                     // A DBG message packet
99                 PHPDBGFrame  DBGFrame;                                      // A frame within a DBG packet
100
101                 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);     // A request for DBG
102                 DBGFrame  = new PHPDBGFrame (PHPDBGBase.FRAME_VER);         // We want the version of DBG
103
104                 DBGPacket.addFrame (DBGFrame);                              // Add the 'what we want' to the DBG packet
105
106                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
107                         return;                                                 //  No
108                 }
109
110                 DBGPacket.sendPacket (os);                                                                      // Send the request to DBG
111         }
112
113         /**
114          * Called by the proxy
115          *
116          */
117         public void getSourceTree () throws IOException {
118                 PHPDBGPacket DBGPacket;                                     // A DBG message packet
119                 PHPDBGFrame  DBGFrame;                                      // A frame within a DBG packet
120
121                 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);     // A request for DBG
122                 DBGFrame  = new PHPDBGFrame (PHPDBGBase.FRAME_SRC_TREE);        // We want a source tree from DBG
123
124                 DBGPacket.addFrame (DBGFrame);                              // Add the 'what we want' to the DBG packet
125
126                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
127                         return;                                                                                                 //  No
128                 }
129
130                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
131
132                 waitResponse (1000);                                        // Wait for the DBG response (1 second)
133                 flushAllPackets ();                                                                             // Read and process the response from DBG
134         }
135
136         /**
137          * Is this method called from anywhere?
138          *
139          * @param modName The modul (filename).
140          */
141         public void addDBGModName (String modName) throws IOException {
142                 PHPDBGPacket DBGPacket;                                     // A DBG message packet
143                 PHPDBGFrame  DBGFrame;                                      // A frame within a DBG packet
144
145                 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);     // A request for DBG
146                 DBGFrame  = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA);     // We want Module name from DBG
147
148                 rawCounter++;                                               // Increment the rawData ID counter
149                 DBGFrame.addInt (rawCounter);                                                           // FRAME_RAWDATA ID
150                 DBGFrame.addInt (modName.length () + 1);                                        // The length of rawdata string (incl. null char termination)
151                 DBGFrame.addString (modName);                                                           // The file name (module name)
152                 DBGFrame.addChar ('\0');                                                                        // Add the C-String null termination
153
154                 DBGPacket.addFrame (DBGFrame);
155
156                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
157                         return;                                                                                                 //  No
158                 }
159
160                 DBGPacket.sendPacket (os);
161         }
162
163         /**
164          * This method is called for adding or removing breakpoints.
165          *
166          * @param mod_name      The module name (file name).
167          * @param condition     Info about the condition when to break (not used at the moment).
168          * @param line          The breakpoints line.
169          * @param state         Info whether this breakpoint has to be dis- or enabled.
170          * @param istep         Always 0.
171          * @param hitcount      Always 0.
172          * @param skiphits      Always 0.
173          * @param bpno          The breakpoint ID.
174          * @param isunderhit    ???
175          * @return
176          */
177         private int setBreakpoint (String mod_name, String condition, int line, int state, int istemp, int hitcount, int skiphits, int bpno, int isunderhit) throws IOException {
178                 PHPDBGPacket    DBGPacket;
179                 PHPDBGFrame     DBGFrame1;
180                 PHPDBGFrame     DBGFrame2;
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
187                 modNo           = getModByName (mod_name);                                              // Get the module ID by name
188
189                 if (modNo >= 0) {                                           // Did we find a module ID for the module name?
190                         DBGFrame1.addInt (modNo);                                                               // Add the module ID to frame 1
191                 } else {
192                         DBGFrame1.addInt (0);                                                                   // mod number (0 use file name)
193                 }
194
195                 DBGFrame1.addInt (line);                                                                        // line number
196
197                 if (modNo >= 0) {                                           // Did we find a module ID for the module name?
198                         DBGFrame1.addInt (0);                                                                   // use mod number
199                 } else {
200                         rawCounter++;
201                         DBGFrame1.addInt (rawCounter);                                                  // ID of FRAME_RAWDATA to send file name
202                 }
203
204                 DBGFrame1.addInt (state);                                       // state BPS_*
205                 DBGFrame1.addInt (istemp);                                      // istep
206                 DBGFrame1.addInt (hitcount);                                // hit count
207                 DBGFrame1.addInt (skiphits);                                // skip hits
208                 DBGFrame1.addInt (0);                                           // ID of condition
209                 DBGFrame1.addInt (bpno);                                            // breakpoint number
210                 DBGFrame1.addInt (isunderhit);                                  // is under hit
211
212                 if (modNo < 0) {                                            // Did we find a module ID for the module name?
213                         DBGFrame2.addInt (rawCounter);                                      // FRAME_RAWDATA ID
214                         DBGFrame2.addInt (mod_name.length() + 1);                   // length of rawdata (+ null char)
215                         DBGFrame2.addString (mod_name);                                     // file name
216                         DBGFrame2.addChar ('\0');                                                   // null char
217
218                         DBGPacket.addFrame (DBGFrame2);                         // First add file name data
219                 }
220
221                 DBGPacket.addFrame (DBGFrame1);                                                         // Second add command data
222
223                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
224                         return 0;                                               //  No
225                 }
226
227                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
228
229                 clearLastBP ();
230
231                 waitResponse (1000);                                        // Wait for the DBG response (1 second)
232                 flushAllPackets ();                                         // Read and process the response from DBG
233
234                 return LastBPRead[8];                                                                           // Return what ???
235         }
236
237         /**
238          *
239          */
240         private void clearLastBP () {
241                 int i;
242
243                 for (i = 0; i < LastBPRead.length; i++) {
244                         LastBPRead[i] = 0;
245                 }
246         }
247
248         /**
249          *
250          */
251         private void copyToLastBP (int[] BPBody) {
252                 int i;
253
254                 for (i = 0; i < LastBPRead.length; i++) {
255                         LastBPRead[i] = BPBody[i];
256                 }
257         }
258
259         /**
260          *
261          */
262         public void continueExecution () throws IOException {
263                 PHPDBGPacket DBGPacket;
264
265                 BPUnderHit = 0;
266                 DBGPacket  = new PHPDBGPacket (PHPDBGBase.DBGA_CONTINUE);
267
268                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
269                         return;                                                 //  No
270                 }
271
272                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
273
274                 lastCommand = PHPDBGBase.DBGA_CONTINUE;                     // Store the info about the command we sent
275         }
276
277         /**
278          *
279          */
280         public void pauseExecution () throws IOException {
281                 PHPDBGPacket DBGPacket;
282
283                 DBGPacket = new PHPDBGPacket (PHPDBGBase.IntToChar4 (PHPDBGBase.DBGC_PAUSE));
284
285                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
286                          return;                                                //  No
287                 }
288
289                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
290         }
291
292         /**
293          *
294          */
295         private int getBPUnderHit () {
296                 int i;
297                 int BPUnder             = 0;
298                 int[] dbg_bpl_body      = new int[10];
299
300                 for (i = 0; i < DBGBPList.size (); i++) {                               // look for bp under hit
301                         dbg_bpl_body = (int[]) DBGBPList.get (i);
302
303                         if (dbg_bpl_body[9] == 1) {
304                                 BPUnder = dbg_bpl_body[8];
305                         }
306                 }
307
308                 return BPUnder;
309         }
310
311         public int getLastCmd()
312         {
313                 return lastCmd;
314         }
315
316         public int getSID()
317         {
318           return sid;
319         }
320
321         public void setLastCmd (int cmd)
322         {
323                 lastCmd = cmd;
324         }
325
326         /**
327          *
328          */
329         public void stepInto () throws IOException {
330                 PHPDBGPacket DBGPacket;
331
332                 BPUnderHit = 0;
333                 DBGPacket  = new PHPDBGPacket (PHPDBGBase.DBGA_STEPINTO);
334
335                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
336                         return;                                                 //  No
337                 }
338
339                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
340
341                 lastCommand = PHPDBGBase.DBGA_STEPINTO;                                         // Store the info about the command we sent
342         }
343
344         /**
345          *
346          */
347         public void stepOver () throws IOException {
348                 PHPDBGPacket DBGPacket;
349
350                 BPUnderHit = 0;
351                 DBGPacket  = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOVER);
352
353                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
354                         return;                                                 //  No
355                 }
356
357                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
358
359                 lastCommand = PHPDBGBase.DBGA_STEPOVER;                     // Store the info about the command we sent
360         }
361
362         /**
363          *
364          */
365         public void stepOut () throws IOException {
366                 PHPDBGPacket DBGPacket;
367
368                 BPUnderHit = 0;
369                 DBGPacket  = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOUT);
370
371                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
372                         return;                                                 //  No
373                 }
374
375                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
376
377                 lastCommand = PHPDBGBase.DBGA_STEPOUT;                      // Store the info about the command we sent
378         }
379
380         /**
381          *
382          */
383         public void stopExecution () throws IOException {
384                 PHPDBGPacket DBGPacket;
385
386                 BPUnderHit = 0;
387                 DBGPacket  = new PHPDBGPacket (PHPDBGBase.DBGA_STOP);
388
389                 if (proxy.getSocket ().isClosed ()) {                                           // Can we communiate with DBG?
390                         return;                                                 //  No
391                 }
392
393                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
394         }
395
396         /**
397          * Go up the tree of PHPVariables
398          * look whether the PHPValue is a reference to a parent PHPValue
399          *
400          * TODO Check where this recursion can come from.
401          * Whether this back reference is legal or a bug.
402          *
403          * @param var
404          * @return
405          * <ul>
406          * <li> false if the PHPValue is not a child of itself
407          * <li> true if the PHPValue is
408          * </ul>
409          */
410
411         private boolean hasRecursion (PHPVariable var) {
412                 PHPVariable parentVar;
413                 PHPValue    val;
414
415                 val = (PHPValue) var.getValue ();                                                       // Get the PHPValue from the current PHPVariable
416
417                 while (var != null) {                                                                           // As long as we have PHPVariable
418                         parentVar = var.getParent ();                                                   // Get the parent PHPVariable
419
420                         if (parentVar != null) {                                // Is there a parent?
421                                 if (parentVar.getValue ().equals (val)) {                       // Get the PHPValue for the parent PHPVariable and check
422                                                                                                                                         // whether it is the same
423                                         return true;                                                                    // Return, if we have recursion
424                                 }
425                         }
426
427                         var = parentVar;
428                 }
429
430                 return false;                                                                                           // No recursion found
431         }
432
433         /**
434          * This method updates the 'static' variables list.
435          * It does a replication between the 'static' list (the variable list which
436          * is a member of this DBG interface object) and the DBG variable list
437          * (the list of variables which is received from PHP via DBG with the current suspend)
438          * Replication is done in the following way:
439          * <ul>
440          * <li> It looks for new variables within the DBG variables list and
441          *      adds them to the 'static' list.
442          * <li> It looks for changed variables copies the current value to the variable within
443          *              the 'static list' and mark these variables as 'hasChanged' (which uses the UI
444          *              for showing the variable with a different color).
445          * <li> It looks for variables within the 'static' list, and removes them
446          *              from the 'static' list in case the do not appear within the DBG list.
447          * </ul>
448          *
449          * @param varListOld The 'static' list of variables which are to be updated.
450          * @param varListNew The new list of (current) variables from DBG.
451          */
452         private void updateVariableList (Vector varListOld, Vector varListNew)
453         {
454                 PHPVariable     varOld;                                                                                 // The variable from the 'static' list
455                 PHPVariable varNew;                                                                                     // The variable from the DBG list
456                 PHPValue    valOld;                                                                                     // The value of the current variable from 'static' list
457                 PHPValue    valNew;                                                                                     // The value of the current variable from DBG list
458                 int         n;                                                                                          // Index for the DBG list
459                 int         o;                                                                                          // Index for the static list
460
461                 // Add the variables (and childs) to the static list if they are new
462                 //  and update the values of variables which are already existend within
463                 //  the 'static' list.
464
465                 for (n = 0; n < varListNew.size (); n++) {                  // For every variable in 'DBG list'
466                         varNew = (PHPVariable) varListNew.get (n);                              // Get the DBG variable
467
468                         for (o = 0; o < varListOld.size (); o++) {                              // For every variable in static list
469                                 varOld = (PHPVariable) varListOld.get (o);                      // Get the static variable
470
471                                 if (varNew.getName ().equals (varOld.getName ())) { // Did we found the variable within the 'static' list?
472                                         valOld = (PHPValue) varOld.getValue ();         // Get the value from 'static'
473                                         valNew = (PHPValue) varNew.getValue ();         // Get the value from DBG
474
475                                         try {
476                                                 if (valOld.hasVariables () ||                           // If the 'static' value has child variables
477                                                     valNew.hasVariables ()) {                           //  or if the DBG value has child variables
478                                                         if (!hasRecursion (varOld) &&
479                                                             !hasRecursion (varNew)) {                   // Both branches should not have a recursion
480                                                                 updateVariableList (valOld.getChildVariables (),        // Update the variable list for the child variables
481                                                                                                         valNew.getChildVariables ());
482                                                         }
483                                                 }
484                                                 else if (!valOld.getValueString ().equals (valNew.getValueString ())) { // Has the value changed?
485                                                         valOld.setValueString (valNew.getValueString ());                   // Yes, set the 'static' value (variable) to the new value
486                                                         varOld.setValueChanged (true);                                                                          // and set the 'has changed' flag, so that the variable view
487                                                                                                                                                                                                 // could show the user the changed status with a different
488                                                                                                                                                                                                 // color
489                                                 }
490                                                 else {
491                                                         varOld.setValueChanged (false);                                     // Reset the 'has changed' flag
492                                                 }
493                                         }
494                                         catch (DebugException e) {                                                  // That's, because of the hasVariables method
495                                         }
496
497                                         break;                                          // Found the variable,
498                                 }
499                         }
500
501                         if (o == varListOld.size ()) {                          // Did we found the variable within the static list?
502                                 varListOld.add (varNew);                                                        //  No, then add the DBG variable to the static list
503                         }
504                 }
505
506                 // Look for the variables we can remove from the 'static' list
507
508                 for (o = 0; o < varListOld.size (); o++) {                                              // For every variable in 'static' list
509                         varOld = (PHPVariable) varListOld.get (o);                                                      // Get the static variable
510
511                         for (n = 0; n < varListNew.size (); n++) {                                                      // For all variables in 'DBG' list
512                                 varNew = (PHPVariable) varListNew.get (n);                                              // Get the variable from the 'DBG' list
513
514                                 if (varNew.getName ().equals (varOld.getName ())) {                     // Did we found the 'static' list variable within the 'DBG' list?
515                                         break;                                                                                                          // Yes we found the variable, then leave the loop
516                                 }
517                         }
518
519                         if (n == varListNew.size ()) {                                          // Did not find the 'static' list variable within the 'DBG' list?
520                                  varListOld.remove (o);                                         // then remove the 'static' list variable from list
521                                  o -= 1;                                                        // Adjust the 'static' list index
522                         }
523                 }
524         }
525
526         /**
527          * This method is called by the proxy.
528          * It sends a request to DBG to get the current variables
529          * with their values. It waits for the response and processes
530          * the input from DBG.
531          *
532          * @param stack The stackframe for which we want the variables.
533          * @return      The array of variables
534          */
535         public Vector getVariables (PHPStackFrame stack) throws IOException, DebugException  {
536                 PHPDBGPacket            DBGPacket;
537                 PHPDBGFrame             DBGFrame1;
538                 PHPDBGEvalString        evalStr;
539
540                 DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);     //
541             DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_EVAL);        //
542
543                 DBGFrame1.addInt (0);                                                                           // istr = raw data ID
544                 DBGFrame1.addInt (1);                                                                           // scope_id = -1 means current location, 0 never used, +1 first depth
545
546                 DBGPacket.addFrame (DBGFrame1);                             // Add command data
547
548                 if (proxy.getSocket ().isClosed ()) {                       // Do we have a socket for DBG communication?
549                         return null;                                                                                    //  No, then leave here
550                 }
551
552                 DBGPacket.sendPacket (os);                                  // Send the request to DBG
553
554                 waitResponse (1000);                                        // Wait for the DBG response (1 second)
555                 flushAllPackets ();                                         // Read and process the response from DBG
556
557                 evalStr         = new PHPDBGEvalString (stack, serGlobals); // Process serialized variables
558                 updateVariableList (DBGVarList, evalStr.getVariables ());       // Replicate the 'static' variable list and the via DBG received variable list
559
560                 return DBGVarList;                                                                                      // Return the variables as list
561         }
562
563         /**
564          *
565          * @param logString
566          */
567         public void log(String logString) throws IOException, DebugException  {
568                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
569                 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_LOG);
570                 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
571
572                 rawCounter++;
573                 DBGFrame1.addInt(rawCounter);                           // ilog
574                 DBGFrame1.addInt(1);                                            // type
575                 DBGFrame1.addInt(0);                                            // mod_no
576                 DBGFrame1.addInt(0);                                            // line_no
577                 DBGFrame1.addInt(0);                                            // imod_name
578                 DBGFrame1.addInt(0);                                            // ext_info
579
580                 DBGFrame2.addInt(rawCounter);                           // FRAME_RAWDATA ID
581                 DBGFrame2.addInt(logString.length() + 1);       // length of rawdata (+ null char)
582                 DBGFrame2.addString(logString);                         // log string
583                 DBGFrame2.addChar('\0');                                        // null char
584
585                 // Add raw data first
586                 DBGPacket.addFrame(DBGFrame2);
587                 // Add command data
588                 DBGPacket.addFrame(DBGFrame1);
589
590                 if(proxy.getSocket().isClosed()) return;
591                 DBGPacket.sendPacket(os);
592
593                 waitResponse(1000);
594                 flushAllPackets();
595         }
596
597         public PHPVariable[] evalBlock(PHPStackFrame stack, String evalString) throws IOException, DebugException  {
598                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
599                 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
600                 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
601
602                 rawCounter++;
603                 DBGFrame1.addInt(rawCounter);                           // istr = raw data ID
604                 DBGFrame1.addInt(1);                                            // scope_id = -1 means current location, 0 never used, +1 first depth
605
606                 DBGFrame2.addInt(rawCounter);                           // FRAME_RAWDATA ID
607                 DBGFrame2.addInt(evalString.length() + 1);      // length of rawdata (+ null char)
608                 DBGFrame2.addString(evalString);                        // eval block
609                 DBGFrame2.addChar('\0');                                        // null char
610
611                 // Add raw data first
612                 DBGPacket.addFrame(DBGFrame2);
613                 // Add command data
614                 DBGPacket.addFrame(DBGFrame1);
615
616                 if(proxy.getSocket().isClosed()) return null;
617                 DBGPacket.sendPacket(os);
618
619                 waitResponse(1000);
620                 flushAllPackets();
621
622                 PHPDBGEvalString evalStr=new PHPDBGEvalString(stack,evalRet);
623
624                 return evalStr.getVars();
625
626         }
627
628         /**
629          * Read and process everthing we got from DBG
630          */
631         public void flushAllPackets () throws IOException {
632                 while (readResponse() != 0);
633         }
634
635         /**
636          * Get the modules name by its number
637          *
638          * @param modNo The number (id) of the module
639          * @return      The name of the module
640          */
641         public String getModByNo (int modNo) {
642                 int             i;
643                 PHPDBGMod       dbg_mod;
644
645                 for (i = 0; i < DBGMods.size (); i++) {                         // For all the modules we have within the array
646                         dbg_mod = (PHPDBGMod) DBGMods.get (i);                      // Get the module
647
648                         if (dbg_mod.getNo () == modNo) {                            // Is the module from the array the module we want?
649                                 return dbg_mod.getName ();                              //  Yes, return the name of the module
650                         }
651                 }
652
653                 return "";                                                      // If nothing was found return emtpy string
654         }
655
656         /**
657          *
658          * @param  modName The name of the module for which we want the ID
659          * @return
660          * - The ID of the module
661          * - -1 if nothing was found
662          */
663         private int getModByName (String modName) {
664                 int             i;
665                 PHPDBGMod       dbg_mod;
666
667                 for (i = 0; i < DBGMods.size (); i++) {                         // For all the modules we have within the array
668                         dbg_mod = (PHPDBGMod) DBGMods.get (i);                      // Get the module
669
670                         if (dbg_mod.getName ().equalsIgnoreCase (modName)) {            // Is the module from the array the module we want?
671                                 return dbg_mod.getNo ();                                //  Yes, return the name of the module
672                         }
673                 }
674
675                 return -1;                                                      // If nothing was found return -1
676         }
677
678         /**
679          * Return the string for the given frame number
680          *
681          * @param framesInfo The buffer which is to read
682          * @param frameNo    The frame number
683          * @return
684          */
685         private String getRawFrameData (char[] framesInfo, int frameNo) {
686                 int   nextFrame = 0;                                                    // The current read position within the buffer
687                 int[] dbg_frame = new int[2];                                           // The two frame header numbers
688
689                 while (nextFrame < framesInfo.length) {                                 // As long we have something within the buffer
690                         dbg_frame[0] = PHPDBGBase.Char4ToInt (framesInfo, nextFrame);           // The frame type
691                         dbg_frame[1] = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4);       // The frame size
692
693                         nextFrame   += 8;                                                   // The current read position
694
695                         if (dbg_frame[1] == 0) {                                            // If frame size is 0
696                                 return "";                                                      //  return an emtpy string
697                         }
698
699                         switch (dbg_frame[0]) {                                                     // Switch for the frame type
700                                 case PHPDBGBase.FRAME_RAWDATA:                                                  // The only frame type we are interrested in
701                                         if (frameNo == PHPDBGBase.Char4ToInt (framesInfo, nextFrame)) {         // Is it correct  number of the frame
702                                                 int toRead;                                                     //
703
704                                                 toRead = PHPDBGBase.Char4ToInt (framesInfo, nextFrame + 4);     // The size of the string
705
706                                                 return String.copyValueOf (framesInfo, nextFrame + 8, toRead);  // Copy frame content to String and return
707                                         }
708                                         break;
709                         }
710
711                         nextFrame += dbg_frame[1];                                                                      // Go for the next frame (add the length of the current one)
712                 }
713
714                 return "";                                                                                                                                              // We did not found any FRAM_RAWDATA, so return an emtpy strin
715         }
716
717         /**
718          *
719          * The stackList contains the currently read stackframes which were sent
720          * from DBG. The DBG interface holds a list of the active stack frames.
721          * This method replicates the 'static' stackframe list with the DBG stackframe list
722          * Replication is done in the following way:
723          * <ul>
724          * <li> It looks for new stackframes within the DBG stackframe list and
725          *      adds them to the 'static' list.
726          * <li> It looks for stackframes within the 'static' list, and removes them
727          *              from the 'static' list in case the do not appear within the DBG list.
728          * <li> It looks for stackframes which are already existent and replicates the
729          *              line number and the index number.
730          * <li> At the end the 'static' stackfram list has to be sorted by the stackframes
731          *              index numbers.
732          * </ul>
733          *
734          * Removes the unused stackframes from the list, or adds stackframes which
735          * are not yet in the list.
736          *
737          *
738          * @param stackList
739          */
740         private void updateStackFrameList (Vector stackList) {
741                 int                     i;
742                 int             n;
743                 PHPStackFrame   stackFrameNew;
744                 PHPStackFrame   stackFrameOld;
745                 PHPStackFrame[] newStackList;
746
747                 for (i = 0; i < stackList.size (); i++) {                                                               // For all stackList entries
748                         stackFrameNew = (PHPStackFrame) stackList.get(i);
749
750                         for (n = 0; n < stackListOld.size (); n++) {                                    // For all StackFrames in the StackFrame list
751                                 stackFrameOld = (PHPStackFrame) stackListOld.get (n);                   // ---
752
753                                 if (stackFrameNew.getModNo () == stackFrameOld.getModNo ()) {   // Did we find the sent stackframe within the list of old stackframes?
754                                         stackFrameOld.setLineNumber (stackFrameNew.getLineNumber ());
755                                         stackFrameOld.setIndex (stackFrameNew.getIndex ());
756
757                                         break;                                                                  //  Yes, then break;
758                                 }
759                         }
760
761                         if (n == stackListOld.size ()) {                                    // Did not find the new stackframe within the list
762                                  stackListOld.add (stackFrameNew);                              //  then add the new stackframe
763                         }
764                 }
765
766                 // And now for removing unused stackframes from list
767
768                 for (n = 0; n < stackListOld.size (); n++) {                                            // For all StackFrames in the StackFrame list
769                         stackFrameOld = (PHPStackFrame) stackListOld.get (n);                           // ---
770
771                         for (i = 0; i < stackList.size (); i++) {                                                       // For all stackList entries
772                                 stackFrameNew = (PHPStackFrame) stackList.get (i);
773
774                                 if (stackFrameNew.getModNo () == stackFrameOld.getModNo ()) {   // Did we find the sent stackframe within the list of old stackframes?
775                                         break;                                                                  //  Yes, then break;
776                                 }
777                         }
778
779                         if (i == stackList.size ()) {                                           // Did not find the old stackframe within the list of new ones
780                                  stackListOld.remove (n);                                       //  then remove the old stackframe from list
781                                  n -= 1;                                                        // Adjust the stack list index
782                         }
783                 }
784
785                 Collections.sort (stackListOld);                                                                                // Sort the 'static' stackframe list by the stackframe index numbers.
786                                                                                                                                                                 //
787                 newStackList = new PHPStackFrame[stackListOld.size ()];
788                 newStackList = (PHPStackFrame[]) stackListOld.toArray (newStackList);
789                 DBGStackList = newStackList;
790         }
791
792     /**
793      * Read the response from DBG and process the frame
794      *
795          * @return
796          * - The received command
797          * - or 0 if something was wrong
798      */
799         public int readResponse () throws IOException {
800         int     bytesToRead            = 0;                         // The number of byte to read for the current DBG block
801         int     nextFrame              = 0;                         // The current read position within entirePack
802         int     i                      = 0;
803         int     cmdReceived            = 0;
804         int     stackIndex             = 0;
805         boolean errorStack             = false;
806         char[]  dbg_header_struct_read = new char[16];              // The buffer for the first 16 bytes of a block
807         int[]   dbg_header_struct      = new int[4];                // The first four numbers (long) of a block
808         int[]   dbg_bpl_tmp            = new int[10];
809         int[]   dbg_frame              = new int[2];
810         int[]   dbg_eval_tmp           = new int[3];
811         int[]   dbg_src_tree_tmp       = new int[4];                //
812         int[]   dbg_error_tmp          = new int[2];
813         Vector  rawList                = new Vector();
814         Vector  stackList              = new Vector();              // Intermediate stacklist which is build up in FRAME_STACK frame
815
816         rawList.clear ();
817         stackList.clear ();
818
819                 // Read from input
820         while (readInput (dbg_header_struct_read, 16) != 0) {                               // Read 16 byte from input stream
821                         dbg_header_struct[0] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 0);               // Debug sync header
822             dbg_header_struct[1] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 4);           // Command
823             dbg_header_struct[2] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 8);       //
824             dbg_header_struct[3] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 12);      // Bytes within this block
825
826             if (dbg_header_struct[0] != 0x5953) {                                           // Check DBG sync bytes
827                 return 0;                                                                   // Wrong header
828             }
829
830             cmdReceived = dbg_header_struct[1];                                             // Get the command
831             setLastCmd (cmdReceived);                                                                                                           // Store the info about the current command
832             bytesToRead = dbg_header_struct[3];                                                                                         // Get the number of bytes to read for this block
833
834                         //System.out.println("Response Received: " + cmdReceived);
835                         char[] entirePack = new char[bytesToRead];                                      // Store the block data into buffer 'entirePack'
836
837             if (bytesToRead > 0) {                                                          // If there is something within the frame
838                 if (readInput (entirePack, bytesToRead) < bytesToRead) {                    // Read the frame into the buffer
839                     return 0;                                                               // We did not read enough bytes, error
840                 }
841                         }
842
843                         nextFrame = 0;                                                                  // Start with the first frame
844
845                         while (nextFrame < bytesToRead) {                                               // As long as we have something within this block
846                                 dbg_frame[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame);                           // The name of the frame
847                                 dbg_frame[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4);               // The size of the frame
848                                 nextFrame   += 8;                                                           // The next read position
849
850                                 if (dbg_frame[1] == 0) {                                                    // Something within the frame?
851                                         return 0;                                                               //  Nothing to read, error
852                                 }
853
854                                 switch (dbg_frame[0]) {
855                                         case PHPDBGBase.FRAME_STACK:
856                                                 int[] dbg_stack_new = new int[4];                                       //
857
858                                                 dbg_stack_new[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0);   // Source line number
859                                                 dbg_stack_new[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4);   // Module number
860                                                 dbg_stack_new[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8);   // Scope id
861                                                 dbg_stack_new[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12);  // ID of description string
862
863                                                 if ((dbg_stack_new[1] != 0) && !errorStack) {
864                                                         PHPStackFrame newStack;
865
866                                                         stackIndex++;
867                                                         newStack = new PHPStackFrame (null,                                 // The thread
868                                                                                       getModByNo (dbg_stack_new[1]),        // The name of the module (file)
869                                                                                       dbg_stack_new[0],                     // The source line number
870                                                                                                                   stackIndex,
871                                                                                                                   getRawFrameData (entirePack,          // Get the string from this packet
872                                                                                                                                    dbg_stack_new[3]),   // The frame ID for which we want the string
873                                                                                                                   dbg_stack_new[1]);                                    // The module number
874                                                         stackList.add (newStack);
875                                                 }
876
877                                                 errorStack = false;
878                                                 break;
879
880                                         case PHPDBGBase.FRAME_SOURCE:                                                   // Nothing to be done here
881                                                 break;                                                                      // TODO: what's with that frame? Something interesting
882
883                                         case PHPDBGBase.FRAME_SRC_TREE:                                                 //
884                                                 dbg_src_tree_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0);        // The parent module number
885                                                 dbg_src_tree_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4);        // The parent line number (not used)
886                                                 dbg_src_tree_tmp[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8);        // The module number
887                                                 dbg_src_tree_tmp[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12);       // The filename number
888
889                                                 if (getModByNo (dbg_src_tree_tmp[2]).equals ("")) {
890                                                         String fileName;
891
892                                                         fileName = new String (getRawFrameData (entirePack, dbg_src_tree_tmp[3]));      // Get the filename
893
894                                                         if (fileName.length () > 0) {                                               // If we have a filename
895                                                                 fileName = fileName.substring (0, fileName.length () - 1);              // Remove '\0' char
896                                                         }
897
898                                                         if (dbg_src_tree_tmp[2] != 0) {                                             // If there is a module number
899                                                                 PHPDBGMod modNew;
900
901                                                                 modNew = new PHPDBGMod (dbg_src_tree_tmp[2], fileName);                 // Create a module object
902
903                                                                 DBGMods.add (modNew);                                                   // And store it to array
904                                                         }
905                                                 }
906                                                 break;
907
908                                         case PHPDBGBase.FRAME_RAWDATA:                                                      // Nothing to be done here
909                                                 break;                                                                          //  FRAME_RAWDATA are processed within getRawFrameData
910
911                                         case PHPDBGBase.FRAME_ERROR:                                                                                                            // An error frame
912                                                 errorStack       = true;                                                                                                                // Yes, we have an error stack
913                                                 dbg_error_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0);                   // Error type
914                                                 dbg_error_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4);                   // Error message ID
915
916                                                 String error = "\n";                                                            //
917
918                                                 switch (dbg_error_tmp[0]) {                                                                                                             // Switch on error type
919                                                         case PHPDBGBase.E_ERROR:                        error += "[Error]";                     break;
920                                                         case PHPDBGBase.E_WARNING:                      error += "[Warning]";                   break;
921                                                         case PHPDBGBase.E_PARSE:                        error += "[Parse Error]";               break;
922                                                         case PHPDBGBase.E_NOTICE:                       error += "[Notice]";                    break;
923                                                         case PHPDBGBase.E_CORE_ERROR:           error += "[Core Error]";                break;
924                                                         case PHPDBGBase.E_CORE_WARNING:         error += "[Core Warning]";              break;
925                                                         case PHPDBGBase.E_COMPILE_ERROR:        error += "[Compile Error]";             break;
926                                                         case PHPDBGBase.E_COMPILE_WARNING:      error += "[Compile Warning]";   break;
927                                                         case PHPDBGBase.E_USER_ERROR:           error += "[User Error]";                break;
928                                                         case PHPDBGBase.E_USER_WARNING:         error += "[User Warning]";              break;
929                                                         case PHPDBGBase.E_USER_NOTICE:          error += "[User Notice]";               break;
930                                                         default:                                                        error += "[Unexpected Error]";  break;
931                                                 }
932
933                                                 error += ": ";
934                                                 error += new String (getRawFrameData (entirePack, dbg_error_tmp[1]));                   // Add the error string for this error message ID
935
936                                                 if (error.length () > 0) {                                                                                                              // If we have a error message
937                                                          error = error.substring (0, error.length () - 1);                                                      //  Remove '\0' char
938                                                 }
939
940                                                 error += "\n";                                                                  // Append a CR
941
942                                                 PHPDebugCorePlugin.log (new DebugException (new Status (IStatus.WARNING,
943                                                                                                         PHPDebugCorePlugin.PLUGIN_ID,
944                                                                                                                                                                 IStatus.OK,
945                                                                                                                                                                 error, null)));
946
947                                                 // To print errors on the console, I must execute a code in the
948                                                 // php context, that write the stderr... I didn't found a better way
949                                                 // TODO: Find a better way????
950
951 //                                              String codeExec= "";
952 //                                              codeExec= "fwrite(fopen('php://stderr', 'w'),\\\"" + error + "\\\");";
953 //                                              try {
954 //                                                      evalBlock("eval(\"" + codeExec + "\");");
955 //                                              } catch (DebugException e) {
956 //                                                      PHPDebugCorePlugin.log(e);
957 //                                              }
958 //
959                                                 if (!stopOnError) {                                                             // Is always false (Did not see where this is set to true!?)
960                                                         if (lastCommand.equals (PHPDBGBase.DBGA_CONTINUE)) {                        // If last command for PHP was a 'continue',
961                                                                 continueExecution ();                                                   //  send continue again
962                                                         } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPINTO)) {                 // If last command for PHP was a 'step into',
963                                                                 stepInto ();                                                            //  send 'step into' again
964                                                         } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPOUT)) {                  // If last command for PHP was a 'step out',
965                                                                 stepOut ();                                                             //  send 'step out' again
966                                                         } else if (lastCommand.equals (PHPDBGBase.DBGA_STEPOVER)) {                 // If last command for PHP was a 'step over',
967                                                                 stepOver ();                                                            //  send 'step over' again
968                                                         }
969                                                 }
970                                                 break;
971
972                                         case PHPDBGBase.FRAME_EVAL:
973                                                 String evalString;
974
975                                                 evalString      = new String ("");
976                                                 dbg_eval_tmp[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0);                    // istr
977                                                 dbg_eval_tmp[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4);                    // iresult
978                                                 dbg_eval_tmp[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8);                    // ierror
979
980                                                 evalRet                 = getRawFrameData (entirePack, dbg_eval_tmp[1]);                //
981                                                 evalString              = getRawFrameData (entirePack, dbg_eval_tmp[0]);                //
982                                                 serGlobals              = evalRet;                                                      //
983                                                 break;
984
985                                         case PHPDBGBase.FRAME_BPS:                                                          //
986                                                 break;                                                                          //
987
988                                         case PHPDBGBase.FRAME_BPL:
989                                                 int[] dbg_bpl_new;
990
991                                                 dbg_bpl_new        = new int[10];
992                                                 dbg_bpl_new[0] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 0);
993                                                 dbg_bpl_new[1] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 4);
994                                                 dbg_bpl_new[2] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 8);
995                                                 dbg_bpl_new[3] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 12);
996                                                 dbg_bpl_new[4] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 16);
997                                                 dbg_bpl_new[5] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 20);
998                                                 dbg_bpl_new[6] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 24);
999                                                 dbg_bpl_new[7] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 28);
1000                                                 dbg_bpl_new[8] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 32);
1001                                                 dbg_bpl_new[9] = PHPDBGBase.Char4ToInt (entirePack, nextFrame + 36);
1002
1003                                                 // look if breakpoint already exists in vector
1004                                                 for (i = 0; i < DBGBPList.size (); i++) {
1005                                                         dbg_bpl_tmp = (int[]) DBGBPList.get (i);
1006
1007                                                         if (dbg_bpl_tmp[8] == dbg_bpl_new[8]) {
1008                                                                 DBGBPList.remove (i);
1009
1010                                                                 break;
1011                                                         }
1012                                                 }
1013
1014                                                 // add breakpoint to vector
1015                                                 DBGBPList.add (dbg_bpl_new);
1016                                                 copyToLastBP (dbg_bpl_new);
1017
1018                                                 // mod no returned?
1019                                                 if (getModByNo (dbg_bpl_new[0]).equals ("")) {
1020                                                         String fileName;
1021
1022                                                         fileName = new String (getRawFrameData (entirePack, dbg_bpl_new[2]));
1023
1024                                                         if (fileName.length () > 0) {                                               // If we have filename
1025                                                                 fileName = fileName.substring (0, fileName.length () - 1);                              //  Remove '\0' char
1026                                                         }
1027
1028                                                         if (dbg_bpl_new[0] != 0) {
1029                                                                 PHPDBGMod modNew;
1030
1031                                                                 modNew = new PHPDBGMod (dbg_bpl_new[0], fileName);
1032
1033                                                                 DBGMods.add (modNew);
1034                                                         }
1035                                                 }
1036                                                 break;
1037
1038                                         case PHPDBGBase.FRAME_VER:
1039                                                 break;
1040
1041                                         case PHPDBGBase.FRAME_SID:
1042                                                 sid = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
1043                                                 break;
1044
1045                                         case PHPDBGBase.FRAME_SRCLINESINFO:
1046                                                 break;
1047
1048                                         case PHPDBGBase.FRAME_SRCCTXINFO:
1049                                                 break;
1050
1051                                         case PHPDBGBase.FRAME_LOG:
1052                                                 break;
1053
1054                                         case PHPDBGBase.FRAME_PROF:
1055                                                 break;
1056
1057                                         case PHPDBGBase.FRAME_PROF_C:
1058                                                 break;
1059
1060                                         case PHPDBGBase.FRAME_SET_OPT:
1061                                                 break;
1062                                 }
1063
1064                                 nextFrame += dbg_frame[1];                                                      // go to next frame
1065                         }
1066
1067                         // Now process command
1068                         switch(cmdReceived) {
1069                                 case PHPDBGBase.DBGC_REPLY:
1070                                         break;
1071
1072                                 case PHPDBGBase.DBGC_STARTUP:
1073                                         break;
1074
1075                                 case PHPDBGBase.DBGC_END:
1076                                         sessionEnded = true;
1077                                         break;
1078
1079                                 case PHPDBGBase.DBGC_BREAKPOINT:
1080                                         BPUnderHit   = getBPUnderHit ();
1081                                         updateStackFrameList (stackList);
1082                                         break;
1083
1084                                 case PHPDBGBase.DBGC_STEPINTO_DONE:
1085                                 case PHPDBGBase.DBGC_STEPOVER_DONE:
1086                                 case PHPDBGBase.DBGC_STEPOUT_DONE:
1087                                 case PHPDBGBase.DBGC_EMBEDDED_BREAK:
1088                                 case PHPDBGBase.DBGC_PAUSE:
1089                                         BPUnderHit   = 1;
1090                                         updateStackFrameList (stackList);
1091                                         break;
1092
1093                                 case PHPDBGBase.DBGC_ERROR:
1094                                         stackList.clear ();
1095                                         updateStackFrameList (stackList);
1096                                         break;
1097
1098                                 case PHPDBGBase.DBGC_LOG:
1099                                         break;
1100
1101                                 case PHPDBGBase.DBGC_SID:
1102                                         break;
1103                         }
1104                 }
1105
1106                 return cmdReceived;                                         // Return the command we received with this block
1107         }
1108
1109     /**
1110      *
1111      */
1112
1113         public PHPStackFrame[] getStackList() {
1114                 return DBGStackList;
1115         }
1116
1117         /**
1118          * Reads from input buffer (response sent from DBG) the given number of chars
1119          * into frame buffer.
1120          *
1121          * @param buffer  The frame buffer where to store the read data from DBG.
1122          * @param bytes   The number of bytes (chars) which are to read from input stream.
1123          * @return        The number of bytes actually read.
1124          */
1125         private int readInput (char[] buffer, int bytes) throws IOException {
1126                 int bytesRead = 0;                                                                                      // Reset the bytes read counter
1127
1128                 for (int i = 0; i < bytes; i++) {                           // For the number of bytes we should read
1129                         if (in.ready ()) {                                                                              // If input stream is ready for reading
1130                                 buffer[i] = (char) (in.read () & 0x00FF);           // Read a char and store only the least significant 8-bits
1131                                 bytesRead++;                                        // Increment the bytes read counter
1132                         }
1133                         else {                                                  // Input stream is not ready
1134                                 break;                                              // Break the loop
1135                         }
1136                 }
1137
1138                 return bytesRead;                                                                                       // Return the number of bytes actually read
1139         }
1140
1141         /**
1142          * PHPProxy could stop the waiting for a response with this method.
1143          *
1144          */
1145         public void setShouldStop () {
1146                 this.shouldStop = true;
1147         }
1148
1149         /**
1150          * @param milliseconds The maximum time in milliseconds we wait for something
1151          *                     to be send from DBG.
1152          * @return             - true if something was received from DBG
1153          *                                         - false if nothing was send from DBG within the given time
1154          *
1155          */
1156         public boolean waitResponse (long milliseconds) throws IOException {
1157                 long timeout;
1158
1159                 timeout = System.currentTimeMillis () + milliseconds;           // Calculate the system time till we wait.
1160
1161                 while (System.currentTimeMillis () < timeout) {             // Is waiting time running out?
1162                         if (in.ready () || shouldStop) {                        //  No, so did we get something or should we stop now
1163                                 break;                                              //   Yes, break the waiting
1164                         }
1165                 }
1166
1167                 return in.ready ();                                         // true if we got something from DBG
1168         }
1169 }