modification to debug on a remote server
[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.IOException;
15 import java.io.BufferedReader;
16 import java.io.OutputStream;
17 import java.util.Vector;
18
19 import org.eclipse.core.runtime.IStatus;
20 import org.eclipse.core.runtime.Status;
21 import org.eclipse.debug.core.DebugException;
22
23 import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
24 import net.sourceforge.phpdt.internal.debug.core.model.PHPVariable;
25 import net.sourceforge.phpdt.internal.debug.core.model.PHPValue;
26
27 public class PHPDBGInterface {
28
29         // Public
30         public boolean sessionEnded= false;
31         public int sessType= -1;        
32         public int BPUnderHit= 0;
33         public String sessID= new String();
34         
35         // Private
36         private int[] LastBPRead= new int[10];
37         private Vector DBGBPList= new Vector();
38         private PHPStackFrame[] DBGStackList;
39         private PHPVariable[] DBGVariableList;
40         private Vector DBGMods= new Vector();
41         private Vector DBGVars= new Vector();
42         private BufferedReader in;
43         private OutputStream os;
44         private boolean shouldStop= false, isRef= false, hasChildren= false, isObject= false;
45         private String evalRet= new String("");
46         private String serGlobals= new String("");
47         private String typeRead= new String("");
48         private String className= new String("");
49         private int finalPos=0, refCounter=0, rawCounter=1000;
50         private PHPDBGProxy proxy= null;
51
52         private int lastCmd=-1;
53         private int sid=0;
54         private boolean stopOnError= false;
55         private char[] lastCommand= new char[4];
56          
57         public PHPDBGInterface(BufferedReader in, OutputStream os, PHPDBGProxy proxy) {
58                 DBGBPList.clear();
59                 this.in= in;
60                 this.os= os;
61                 this.proxy= proxy;
62         }
63
64         public int addBreakpoint(String mod_name, int line) throws IOException {
65                 return setBreakpoint(mod_name, "", line, PHPDBGBase.BPS_ENABLED + PHPDBGBase.BPS_UNRESOLVED, 0, 0, 0, 0, 0);
66         }
67
68         public void removeBreakpoint(String mod_name, int line, int bpNo) throws IOException {
69                 setBreakpoint(mod_name, "", line, PHPDBGBase.BPS_DISABLED, 0, 0, 0, bpNo, 0);
70         }
71
72         public void requestDBGVersion() throws IOException {
73                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
74                 PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_VER);
75                 
76                 DBGPacket.addFrame(DBGFrame);
77
78                 if(proxy.getSocket().isClosed()) return;
79                 DBGPacket.sendPacket(os);
80         }
81
82         public void getSourceTree() throws IOException {
83                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
84                 PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_SRC_TREE);
85                 
86                 DBGPacket.addFrame(DBGFrame);
87                 
88                 if(proxy.getSocket().isClosed()) return;
89                 DBGPacket.sendPacket(os);
90
91                 // Wait response (1 second) and read response
92                 waitResponse(1000);
93                 flushAllPackets();
94         }
95
96         public void addDBGModName(String modName) throws IOException {
97                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
98                 PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
99                 
100                 rawCounter++;
101                 DBGFrame.addInt(rawCounter);                            // FRAME_RAWDATA ID
102                 DBGFrame.addInt(modName.length() + 1);          // length of rawdata (+ null char)
103                 DBGFrame.addString(modName);                            // file name
104                 DBGFrame.addChar('\0');                                         // null char
105
106                 DBGPacket.addFrame(DBGFrame);
107                 
108                 if(proxy.getSocket().isClosed()) return;
109                 DBGPacket.sendPacket(os);
110         }
111
112         // Returns DBG Breakpoint ID
113         private int setBreakpoint(String mod_name, String condition, int line, int state, int istemp, int hitcount, int skiphits, int bpno, int isunderhit) throws IOException {
114                 int modNo= 0;
115
116                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
117                 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_BPS);
118                 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
119
120                 modNo= getModByName(mod_name);
121                 
122                 if(modNo >= 0) {
123                         DBGFrame1.addInt(modNo);        // mod number
124                 } else {
125                         DBGFrame1.addInt(0);            // mod number (0 use file name)
126                 }
127                 
128                 DBGFrame1.addInt(line);                 // line number
129                 
130                 if(modNo >= 0) {
131                         DBGFrame1.addInt(0);                    // use mod number
132                 } else {
133                         rawCounter++;
134                         DBGFrame1.addInt(rawCounter);   // ID of FRAME_RAWDATA to send file name
135                 }
136
137                 DBGFrame1.addInt(state);                // state BPS_*
138                 DBGFrame1.addInt(istemp);               // istemp
139                 DBGFrame1.addInt(hitcount);             // hit count
140                 DBGFrame1.addInt(skiphits);             // skip hits
141                 DBGFrame1.addInt(0);                    // ID of condition
142                 DBGFrame1.addInt(bpno);                 // breakpoint number
143                 DBGFrame1.addInt(isunderhit);   // is under hit
144                 
145                 if(modNo < 0) {
146                         DBGFrame2.addInt(rawCounter);                           // FRAME_RAWDATA ID
147                         DBGFrame2.addInt(mod_name.length() + 1);        // length of rawdata (+ null char)
148                         DBGFrame2.addString(mod_name);                          // file name
149                         DBGFrame2.addChar('\0');                                        // null char
150                         // First add file name data
151                         DBGPacket.addFrame(DBGFrame2);
152                 }
153
154                 // Second add command data
155                 DBGPacket.addFrame(DBGFrame1);
156
157                 if(proxy.getSocket().isClosed()) return 0;
158                 DBGPacket.sendPacket(os);
159
160                 clearLastBP();
161
162                 // Wait response (1 second) and read response
163                 waitResponse(1000);
164                 flushAllPackets();
165
166                 return LastBPRead[8];
167         }
168
169         private void clearLastBP() {
170                 int i;
171
172                 for(i=0; i < LastBPRead.length; i++)
173                         LastBPRead[i]= 0;
174         }
175
176         private void copyToLastBP(int[] BPBody) {
177                 int i;
178
179                 for(i=0; i < LastBPRead.length; i++)
180                         LastBPRead[i]= BPBody[i];
181         }
182
183         public void continueExecution() throws IOException {
184                 BPUnderHit= 0;
185                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_CONTINUE);
186                 if(proxy.getSocket().isClosed()) return;
187                 DBGPacket.sendPacket(os);
188                 lastCommand= PHPDBGBase.DBGA_CONTINUE;
189         }
190
191         public void pauseExecution() throws IOException {
192                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.IntToChar4(PHPDBGBase.DBGC_PAUSE));
193                 if(proxy.getSocket().isClosed()) return;
194                 DBGPacket.sendPacket(os);
195         }
196
197         private int getBPUnderHit() {
198                 int i, BPUnder=0;
199                 int[] dbg_bpl_body= new int[10];
200
201                 // look for bp under hit
202                 for(i=0; i < DBGBPList.size(); i++) {
203                         dbg_bpl_body= (int[]) DBGBPList.get(i);
204                         if(dbg_bpl_body[9] == 1) {
205                                 BPUnder= dbg_bpl_body[8];
206                         }
207                 }
208                 return BPUnder;
209         }
210         
211         public int getLastCmd()
212         {
213                 return lastCmd;
214         }
215         
216         public int getSID()
217         {
218           return sid;
219   }
220         
221         public void setLastCmd(int cmd)
222         {
223                 lastCmd=cmd;
224         }
225
226         public void stepInto() throws IOException {
227                 BPUnderHit= 0;
228                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPINTO);
229                 if(proxy.getSocket().isClosed()) return;
230                 DBGPacket.sendPacket(os);
231                 lastCommand= PHPDBGBase.DBGA_STEPINTO;
232         }
233
234         public void stepOver() throws IOException {
235                 BPUnderHit= 0;
236                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOVER);
237                 if(proxy.getSocket().isClosed()) return;
238                 DBGPacket.sendPacket(os);
239                 lastCommand= PHPDBGBase.DBGA_STEPOVER;
240         }
241
242         public void stepOut() throws IOException {
243                 BPUnderHit= 0;
244                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOUT);
245                 if(proxy.getSocket().isClosed()) return;
246                 DBGPacket.sendPacket(os);
247                 lastCommand= PHPDBGBase.DBGA_STEPOUT;
248         }
249
250         public void stopExecution() throws IOException {
251                 BPUnderHit= 0;
252                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STOP);
253                 if(proxy.getSocket().isClosed()) return;
254                 DBGPacket.sendPacket(os);
255         }
256
257         public PHPVariable[] getVariables(PHPStackFrame stack) throws IOException, DebugException  {
258                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
259                 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
260         
261                 DBGFrame1.addInt(0);                                            // istr = raw data ID
262                 DBGFrame1.addInt(1);                                            // scope_id = -1 means current location, 0 never used, +1 first depth
263                 
264                 // Add command data
265                 DBGPacket.addFrame(DBGFrame1);
266                 
267                 if(proxy.getSocket().isClosed()) return null;
268                 DBGPacket.sendPacket(os);
269
270                 waitResponse(1000);
271                 flushAllPackets();
272                 
273                 // Process serialized variables
274                 DBGVariableList= procVars(stack);
275
276                 return DBGVariableList;
277         }
278
279         public void log(String logString) throws IOException, DebugException  {
280                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
281                 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_LOG);
282                 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
283
284                 rawCounter++;
285                 DBGFrame1.addInt(rawCounter);                           // ilog
286                 DBGFrame1.addInt(1);                                            // type
287                 DBGFrame1.addInt(0);                                            // mod_no
288                 DBGFrame1.addInt(0);                                            // line_no
289                 DBGFrame1.addInt(0);                                            // imod_name
290                 DBGFrame1.addInt(0);                                            // ext_info             
291
292                 DBGFrame2.addInt(rawCounter);                           // FRAME_RAWDATA ID
293                 DBGFrame2.addInt(logString.length() + 1);       // length of rawdata (+ null char)
294                 DBGFrame2.addString(logString);                         // log string
295                 DBGFrame2.addChar('\0');                                        // null char
296
297                 // Add raw data first
298                 DBGPacket.addFrame(DBGFrame2);
299                 // Add command data
300                 DBGPacket.addFrame(DBGFrame1);
301                 
302                 if(proxy.getSocket().isClosed()) return;
303                 DBGPacket.sendPacket(os);
304
305                 waitResponse(1000);
306                 flushAllPackets();
307         }
308
309         public void evalBlock(String evalString) throws IOException, DebugException  {
310                 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
311                 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
312                 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
313
314                 rawCounter++;
315                 DBGFrame1.addInt(rawCounter);                           // istr = raw data ID
316                 DBGFrame1.addInt(-1);                                           // scope_id = -1 means current location, 0 never used, +1 first depth
317
318                 DBGFrame2.addInt(rawCounter);                           // FRAME_RAWDATA ID
319                 DBGFrame2.addInt(evalString.length() + 1);      // length of rawdata (+ null char)
320                 DBGFrame2.addString(evalString);                        // eval block
321                 DBGFrame2.addChar('\0');                                        // null char
322
323                 // Add raw data first
324                 DBGPacket.addFrame(DBGFrame2);
325                 // Add command data
326                 DBGPacket.addFrame(DBGFrame1);
327                 
328                 if(proxy.getSocket().isClosed()) return;
329                 DBGPacket.sendPacket(os);
330
331                 waitResponse(1000);
332                 flushAllPackets();
333         }
334
335         public void flushAllPackets() throws IOException {
336                 while(readResponse() != 0);
337         }
338
339         public String getModByNo(int modNo) {
340                 int i;
341                 PHPDBGMod dbg_mod;
342
343                 // look for mod
344                 for(i=0; i < DBGMods.size(); i++) {
345                         dbg_mod= (PHPDBGMod) DBGMods.get(i);
346                         if(dbg_mod.getNo() == modNo) {
347                                 return dbg_mod.getName(); 
348                         }
349                 }
350                 return "";
351         }
352
353         private int getModByName(String modName) {
354                 int i;
355                 PHPDBGMod dbg_mod;
356
357                 // look for mod
358                 for(i=0; i < DBGMods.size(); i++) {
359                         dbg_mod= (PHPDBGMod) DBGMods.get(i);
360                         if(dbg_mod.getName().equalsIgnoreCase(modName)) {
361                                 return dbg_mod.getNo(); 
362                         }
363                 }
364                 return -1;
365         }
366
367         private String getRawFrameData(char[] framesInfo, int frameNo) {
368                 int nextFrame= 0;
369                 int[] dbg_frame= new int[2];
370                 
371                 while(nextFrame < framesInfo.length) {
372                         dbg_frame[0] = PHPDBGBase.Char4ToInt(framesInfo, nextFrame);            // frame name
373                         dbg_frame[1] = PHPDBGBase.Char4ToInt(framesInfo, nextFrame + 4);        // frame size
374
375                         nextFrame += 8;
376                         if(dbg_frame[1] == 0) return "";
377
378                         switch(dbg_frame[0]) {
379                                 case PHPDBGBase.FRAME_RAWDATA:
380                                         if(frameNo == PHPDBGBase.Char4ToInt(framesInfo, nextFrame)) {
381                                                 int toRead= PHPDBGBase.Char4ToInt(framesInfo, nextFrame + 4);
382                                                 return String.copyValueOf(framesInfo, nextFrame + 8, toRead);
383                                         }
384                                         break;
385                         }
386                         // go to next frame
387                         nextFrame += dbg_frame[1];
388                 }
389                 return "";
390         }
391
392         public PHPVariable[] getInstVars(PHPVariable phpVar) throws DebugException {
393                 Vector vecVars= new Vector();
394                 PHPVariable localPHPVar;
395                 int i=0;
396                 
397                 // already unserialized
398                 for(i=0; i < DBGVars.size(); i++) {
399                         localPHPVar= (PHPVariable)DBGVars.get(i);
400                         if(localPHPVar.getParent() == phpVar) {
401                                 vecVars.add(localPHPVar);
402                         }
403                 }
404                 PHPVariable[] arrVars= new PHPVariable[vecVars.size()];
405                 arrVars= (PHPVariable[]) vecVars.toArray(arrVars);
406
407                 return arrVars;
408         }
409         
410         private PHPVariable[] procVars(PHPStackFrame stack) throws DebugException {
411                 Vector vecVars= new Vector();
412                 
413                 // unserialize
414                 finalPos= 0;
415                 refCounter= 0;
416                 doUnserialize(stack, vecVars, null);
417
418                 DBGVars= vecVars;
419                 
420                 return(getInstVars(null));
421         }
422
423         private String readValue(String serialVars) throws DebugException {
424                 int startPos=0, endPos=0, lenStr=0, i=0, elements=0;
425                 String ret= new String("");
426
427                 switch(serialVars.charAt(0)) {
428                         case 'a':       // associative array, a:elements:{[index][value]...}
429                                 typeRead= "hash";
430                                 startPos= 1;
431                                 endPos= serialVars.indexOf(':', startPos + 1);
432                                 if(endPos == -1) return "";
433                                 finalPos += endPos + 2;
434                                 ret= new String(serialVars.substring(startPos + 1, endPos));
435                                 
436                                 hasChildren= true;
437                                 break;
438                         case 'O':       // object, O:name_len:"name":elements:{[attribute][value]...}
439                                 typeRead= "object";
440                                 
441                                 startPos= 1;
442                                 endPos= serialVars.indexOf(':', startPos + 1);
443                                 if(endPos == -1) return "";
444                                 
445                                 // get object class
446                                 lenStr= Integer.parseInt(serialVars.substring(startPos + 1, endPos));
447                                 startPos= endPos + 2;
448                                 endPos= lenStr + startPos;
449                                 className= new String(serialVars.substring(startPos, endPos).toString());
450
451                                 // get num of elements
452                                 startPos= endPos + 1;
453                                 endPos= serialVars.indexOf(':', startPos + 1);
454                                 if(endPos == -1) return "";
455                                 finalPos += endPos + 2;
456                                 ret= new String(serialVars.substring(startPos + 1, endPos));
457
458                                 isObject= true;
459                                 hasChildren= true;                              
460                                 break;
461                         case 's':       // string, s:length:"data";
462                                 typeRead= "string";
463                                 startPos= 1;
464                                 endPos= serialVars.indexOf(':', startPos + 1);
465                                 if(endPos == -1) return "";
466
467                                 lenStr= Integer.parseInt(serialVars.substring(startPos + 1, endPos));
468                                 startPos= endPos + 2;
469                                 endPos= lenStr + startPos;
470                                 ret= new String(serialVars.substring(startPos, endPos).toString());
471                                 finalPos += endPos + 2; 
472                                 break;
473                         case 'i':       // integer, i:123;
474                                 typeRead= "integer";
475                                 startPos= 1;
476                                 endPos= serialVars.indexOf(';', startPos + 1);
477                                 if(endPos == -1) return "";
478
479                                 ret= new String(serialVars.substring(startPos + 1, endPos).toString());
480                                 finalPos += endPos + 1;
481                                 break;
482                         case 'd':       // double (float), d:1.23;
483                                 typeRead= "double";
484                                 startPos= 1;
485                                 endPos= serialVars.indexOf(';', startPos + 1);
486                                 if(endPos == -1) return "";
487         
488                                 ret= new String(serialVars.substring(startPos + 1, endPos).toString());
489                                 finalPos += endPos + 1;
490                                 break;
491                         case 'N':       // NULL, N;
492                                 typeRead= "null";
493                                 ret= "nil";
494                                 finalPos += 2;
495                                 break;
496                         case 'b':       // bool, b:0 or 1
497                                 typeRead= "boolean";
498                                 ret= (serialVars.charAt(2) == '1')?"true":"false";
499                                 finalPos += endPos + 4;
500                                 break;
501                         case 'z':       // resource, z:typename_len:"typename":valres;
502                                 typeRead= "resource";
503                                 
504                                 startPos= 1;
505                                 endPos= serialVars.indexOf(':', startPos + 1);
506                                 if(endPos == -1) return "";
507                 
508                                 // get resource type name
509                                 lenStr= Integer.parseInt(serialVars.substring(startPos + 1, endPos));
510                                 startPos= endPos + 2;
511                                 endPos= lenStr + startPos;
512                                 className= new String(serialVars.substring(startPos, endPos).toString());
513
514                                 // get resource value
515                                 startPos= endPos + 1;
516                                 endPos= serialVars.indexOf(';', startPos + 1);
517                                 if(endPos == -1) return "";
518                                 ret= new String(serialVars.substring(startPos + 1, endPos));
519                                 finalPos += endPos + 1;
520                                 break;
521                         case 'r':
522                         case 'R':
523                                 typeRead= "reference";
524                                 startPos= 1;
525                                 endPos= serialVars.indexOf(';', startPos + 1);
526                                 if(endPos == -1) return "0";
527
528                                 ret= new String(serialVars.substring(startPos + 1, endPos));
529                                 finalPos += endPos + 1;
530                                 isRef= true;
531                                 break;
532                         case ';':
533                                 typeRead= "unknown";
534                                 finalPos+= 1;
535                                 break;
536                         case '?':
537                                 finalPos+= 1;
538                         default:
539                                 finalPos+= 1;
540                                 typeRead= "unknown";
541                                 break;
542                 }
543                 return ret;
544         }
545
546         private void doUnserialize(PHPStackFrame stack, Vector vecVars, PHPVariable parent) throws DebugException {
547                 int i, elements= 0;
548                 PHPVariable newVar= null;
549                 String value= new String("");
550                 String name= new String("");
551                 String tmp= new String("");
552                 String[] tmpSplit;
553
554                 if(finalPos > serGlobals.length() || serGlobals.equals("") || serGlobals.substring(finalPos).equals("")) return;
555
556                 isRef= false;
557                 hasChildren= false;
558                 isObject= false;
559                 name= readValue(serGlobals.substring(finalPos));
560                 
561                 if(hasChildren) {
562                         // main array
563                         if(refCounter == 0) {
564                                 value= name;
565                                 name= "";
566                         }
567                 } else {
568                         hasChildren= false;
569                         isRef= false;
570                         value= readValue(serGlobals.substring(finalPos));
571                         // replaceAll doesn't work, why???
572                         tmpSplit= value.split("\\\\");
573                         value= "";
574                         for(i= 0; i < tmpSplit.length; i++) {
575                                 value= value + tmpSplit[i];
576                                 if(!tmpSplit[i].equals("")) {
577                                         if(i < (tmpSplit.length - 1)) {
578                                                 value= value + "\\";
579                                         }
580                                 }
581                         }
582                 }
583                 
584                 if(!name.equals("")) {
585                         if(isRef) {
586                                 PHPVariable varPHP;
587                                 for(i=0; i < vecVars.size(); i++) {
588                                         varPHP= (PHPVariable) vecVars.get(i);
589                                         if(varPHP.getObjectId().equals(value)) {
590                                                 newVar= new PHPVariable(stack, name, "local", true, (PHPValue)varPHP.getValue());
591                                                 break;                                          
592                                         }
593                                 }
594                                 if(newVar == null) {
595                                         newVar= new PHPVariable(stack, name, "local", false, null);
596                                 }
597                         } else {
598                                 refCounter++;
599                                 newVar= new PHPVariable(stack, name, "local", value, typeRead, hasChildren, Integer.toString(refCounter), className);
600                         }
601                         newVar.setParent(parent);
602                         vecVars.add(newVar);
603                 }
604                 if(hasChildren) {
605                         elements= Integer.parseInt(value);
606                         for(i=0; i < elements; i++)
607                                 doUnserialize(stack, vecVars, newVar);
608
609                         // skip "}"
610                         finalPos += 1;
611                 }
612         }
613
614         public int readResponse() throws IOException {
615                 int bytesToRead=0, nextFrame=0, i=0, cmdReceived=0, stackIndex=0;
616                 boolean errorStack= false;
617                 char[] dbg_header_struct_read= new char[16];
618                 int[] dbg_header_struct= new int[4];
619                 int[] dbg_bpl_tmp= new int[10];
620                 int[] dbg_frame= new int[2];
621                 int[] dbg_eval_tmp= new int[3];
622                 int[] dbg_src_tree_tmp= new int[4];
623                 int[] dbg_error_tmp= new int[2];
624                 Vector rawList= new Vector();
625                 Vector stackList= new Vector();
626                 PHPStackFrame[] newStackList;
627                 
628                 rawList.clear();
629                 stackList.clear();
630                 // Read from input
631                 while(readInput(dbg_header_struct_read, 16) != 0) {
632                         dbg_header_struct[0] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 0);
633                         dbg_header_struct[1] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 4);
634                         dbg_header_struct[2] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 8);
635                         dbg_header_struct[3] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 12);
636                         
637                         // Check DBG sync bytes
638                         if(dbg_header_struct[0] != 0x5953) return 0;
639                         
640                         cmdReceived= dbg_header_struct[1];
641                         setLastCmd(cmdReceived);
642                         bytesToRead= dbg_header_struct[3];
643
644                         //System.out.println("Response Received: " + cmdReceived);
645                         char[] entirePack= new char[bytesToRead];
646
647                         if(bytesToRead > 0) {
648                                 if(readInput(entirePack, bytesToRead) < bytesToRead) return 0;
649                         }
650                         
651                         // First process frames
652                         nextFrame= 0;
653                         while(nextFrame < bytesToRead) {
654                                 dbg_frame[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame);            // frame name
655                                 dbg_frame[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4);        // frame size
656                                 nextFrame += 8;
657                                 if(dbg_frame[1] == 0) return 0;
658                                 switch(dbg_frame[0]) {
659                                         case PHPDBGBase.FRAME_STACK:
660                                                 int[] dbg_stack_new= new int[4];
661                                                 dbg_stack_new[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);    // line no
662                                                 dbg_stack_new[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4);    // mod no
663                                                 dbg_stack_new[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8);    // scope id
664                                                 dbg_stack_new[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12);   // id of description string
665
666                                                 if(dbg_stack_new[1] != 0 && !errorStack) {
667                                                         stackIndex++;
668                                                         PHPStackFrame newStack= new PHPStackFrame(null, getModByNo(dbg_stack_new[1]), dbg_stack_new[0], stackIndex, getRawFrameData(entirePack, dbg_stack_new[3]), dbg_stack_new[1]);
669                                                         stackList.add(newStack);
670                                                 }
671                                                 errorStack= false;
672                                                 break;
673                                         case PHPDBGBase.FRAME_SOURCE:
674                                                 break;
675                                         case PHPDBGBase.FRAME_SRC_TREE:
676                                                 dbg_src_tree_tmp[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);         // parent_mod_no
677                                                 dbg_src_tree_tmp[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4);         // parent_line_no               /* NOT USED */
678                                                 dbg_src_tree_tmp[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8);         // mod_no
679                                                 dbg_src_tree_tmp[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12);        // imod_name
680
681                                                 if(getModByNo(dbg_src_tree_tmp[2]).equals("")) {
682                                                         String fileName= new String(getRawFrameData(entirePack, dbg_src_tree_tmp[3]));
683                                                         // Remove '\0' char
684                                                         if(fileName.length() > 0) fileName= fileName.substring(0, fileName.length() - 1);
685
686                                                         if(dbg_src_tree_tmp[2] != 0) {
687                                                                 PHPDBGMod modNew= new PHPDBGMod(dbg_src_tree_tmp[2], fileName);
688                                                                 DBGMods.add(modNew);
689                                                         }
690                                                 }
691                                                 break;
692                                         case PHPDBGBase.FRAME_RAWDATA:
693                                                 break;
694                                         case PHPDBGBase.FRAME_ERROR:
695                                                 errorStack= true;
696                                                 dbg_error_tmp[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);            // type                 /* type of error */
697                                                 dbg_error_tmp[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4);            // imessage             /* ID of error message */
698                                                 
699                                                 String error= "\n";
700                                                 switch(dbg_error_tmp[0]) {
701                                                         case PHPDBGBase.E_ERROR:
702                                                                 error+= "[Error]";
703                                                                 break;
704                                                         case PHPDBGBase.E_WARNING:
705                                                                 error+= "[Warning]";
706                                                                 break;
707                                                         case PHPDBGBase.E_PARSE:
708                                                                 error+= "[Parse Error]";
709                                                                 break;
710                                                         case PHPDBGBase.E_NOTICE:
711                                                                 error+= "[Notice]";
712                                                                 break;
713                                                         case PHPDBGBase.E_CORE_ERROR:
714                                                                 error+= "[Core Error]";
715                                                                 break;
716                                                         case PHPDBGBase.E_CORE_WARNING:
717                                                                 error+= "[Core Warning]";
718                                                                 break;
719                                                         case PHPDBGBase.E_COMPILE_ERROR:
720                                                                 error+= "[Compile Error]";
721                                                                 break;
722                                                         case PHPDBGBase.E_COMPILE_WARNING:
723                                                                 error+= "[Compile Warning]";
724                                                                 break;
725                                                         case PHPDBGBase.E_USER_ERROR:
726                                                                 error+= "[User Error]";
727                                                                 break;
728                                                         case PHPDBGBase.E_USER_WARNING:
729                                                                 error+= "[User Warning]";
730                                                                 break;
731                                                         case PHPDBGBase.E_USER_NOTICE:
732                                                                 error+= "[User Notice]";
733                                                                 break;
734                                                         default:
735                                                                 error+= "[Unexpected Error]";
736                                                                 break;
737                                                 }
738                                                 error+= ": ";
739                                                 error+= new String(getRawFrameData(entirePack, dbg_error_tmp[1]));
740                                                 // Remove '\0' char
741                                                 if(error.length() > 0) error= error.substring(0, error.length() - 1);
742                                                 error+= "\n";
743
744                                                 PHPDebugCorePlugin.log(new DebugException(new Status(IStatus.WARNING, PHPDebugCorePlugin.PLUGIN_ID, IStatus.OK, error, null)));
745                                                 // To print errors on the console, I must execute a code in the
746                                                 // php context, that write the stderr... I didn't found a better way
747                                                 // TODO: Find a better way????
748                                                 String codeExec= "";
749                                                 codeExec= "fwrite(fopen('php://stderr', 'w'),\\\"" + error + "\\\");";
750                                                 try {
751                                                         evalBlock("eval(\"" + codeExec + "\");");
752                                                 } catch (DebugException e) {
753                                                         PHPDebugCorePlugin.log(e);
754                                                 }
755                                                 if(!stopOnError) {
756                                                         if(lastCommand.equals(PHPDBGBase.DBGA_CONTINUE)) {
757                                                                 continueExecution();
758                                                         } else if(lastCommand.equals(PHPDBGBase.DBGA_STEPINTO)) {
759                                                                 stepInto();
760                                                         } else if(lastCommand.equals(PHPDBGBase.DBGA_STEPOUT)) {
761                                                                 stepOut();
762                                                         } else if(lastCommand.equals(PHPDBGBase.DBGA_STEPOVER)) {
763                                                                 stepOver();
764                                                         }
765                                                 }
766                                                 break;
767                                         case PHPDBGBase.FRAME_EVAL:
768                                                 String evalString= new String("");
769                                                 dbg_eval_tmp[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); // istr
770                                                 dbg_eval_tmp[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // iresult
771                                                 dbg_eval_tmp[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8); // ierror
772
773                                                 evalRet= getRawFrameData(entirePack, dbg_eval_tmp[1]);
774                                                 evalString= getRawFrameData(entirePack, dbg_eval_tmp[0]);
775                                                 serGlobals= evalRet;
776                                                 break;
777                                         case PHPDBGBase.FRAME_BPS:
778                                                 break;
779                                         case PHPDBGBase.FRAME_BPL:
780                                                 int[] dbg_bpl_new= new int[10];
781                                                 dbg_bpl_new[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
782                                                 dbg_bpl_new[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4);
783                                                 dbg_bpl_new[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8);
784                                                 dbg_bpl_new[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12);
785                                                 dbg_bpl_new[4] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 16);
786                                                 dbg_bpl_new[5] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 20);
787                                                 dbg_bpl_new[6] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 24);
788                                                 dbg_bpl_new[7] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 28);
789                                                 dbg_bpl_new[8] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 32);
790                                                 dbg_bpl_new[9] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 36);
791         
792                                                 // look if breakpoint already exists in vector
793                                                 for(i=0; i < DBGBPList.size(); i++) {
794                                                         dbg_bpl_tmp= (int[]) DBGBPList.get(i);
795                                                         if(dbg_bpl_tmp[8] == dbg_bpl_new[8]) {
796                                                                 DBGBPList.remove(i);
797                                                                 break;
798                                                         }
799                                                 }
800
801                                                 // add breakpoint to vector
802                                                 DBGBPList.add(dbg_bpl_new);
803                                                 copyToLastBP(dbg_bpl_new);
804                                                 
805                                                 // mod no returned?
806                                                 if(getModByNo(dbg_bpl_new[0]).equals("")) {
807                                                         String fileName= new String(getRawFrameData(entirePack, dbg_bpl_new[2]));
808                                                         // Remove '\0' char
809                                                         if(fileName.length() > 0) fileName= fileName.substring(0, fileName.length() - 1);
810                                                         if(dbg_bpl_new[0] != 0) {
811                                                                 PHPDBGMod modNew= new PHPDBGMod(dbg_bpl_new[0], fileName);
812                                                                 DBGMods.add(modNew);
813                                                         }
814                                                 }                                                       
815                                                 break;
816                                         case PHPDBGBase.FRAME_VER:
817                                                 break;
818                                         case PHPDBGBase.FRAME_SID:
819                                           sid = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
820                                                 break;
821                                         case PHPDBGBase.FRAME_SRCLINESINFO:
822                                                 break;
823                                         case PHPDBGBase.FRAME_SRCCTXINFO:
824                                                 break;
825                                         case PHPDBGBase.FRAME_LOG:
826                                                 break;
827                                         case PHPDBGBase.FRAME_PROF:
828                                                 break;
829                                         case PHPDBGBase.FRAME_PROF_C:
830                                                 break;
831                                         case PHPDBGBase.FRAME_SET_OPT:
832                                                 break;
833                                 }
834                                 // go to next frame
835                                 nextFrame += dbg_frame[1];
836                         }
837                         
838                         // Now process command
839                         switch(cmdReceived) {
840                                 case PHPDBGBase.DBGC_REPLY:
841                                         break;
842                                 case PHPDBGBase.DBGC_STARTUP:
843                                         break;
844                                 case PHPDBGBase.DBGC_END:
845                                         sessionEnded= true;
846                                         break;
847                                 case PHPDBGBase.DBGC_BREAKPOINT:
848                                         newStackList= new PHPStackFrame[stackList.size()];
849                                         newStackList= (PHPStackFrame[]) stackList.toArray(newStackList);
850                                         DBGStackList= newStackList;
851                                         BPUnderHit= getBPUnderHit();
852                                         break;
853                                 case PHPDBGBase.DBGC_STEPINTO_DONE:
854                                 case PHPDBGBase.DBGC_STEPOVER_DONE:
855                                 case PHPDBGBase.DBGC_STEPOUT_DONE:
856                                 case PHPDBGBase.DBGC_EMBEDDED_BREAK:
857                                 case PHPDBGBase.DBGC_PAUSE:
858                                         BPUnderHit= 1;
859                                         newStackList= new PHPStackFrame[stackList.size()];
860                                         newStackList= (PHPStackFrame[]) stackList.toArray(newStackList);
861                                         DBGStackList= newStackList;
862                                         break;
863                                 case PHPDBGBase.DBGC_ERROR:
864                                         stackList.clear();
865                                         newStackList= new PHPStackFrame[stackList.size()];
866                                         newStackList= (PHPStackFrame[]) stackList.toArray(newStackList);
867                                         DBGStackList= newStackList;
868                                         break;
869                                 case PHPDBGBase.DBGC_LOG:
870                                         break;
871                                 case PHPDBGBase.DBGC_SID:
872                                         break;
873                         }
874                 }
875                 return cmdReceived;
876         }
877
878         public PHPStackFrame[] getStackList() {
879                 return DBGStackList;
880         }
881
882         private int readInput(char[] buffer, int bytes) throws IOException {
883                 int bytesRead= 0;
884
885                 for(int i=0; i < bytes; i++) {
886                         if(in.ready()) {
887                                 buffer[i]= (char) (in.read() & 0x00FF);
888                                 bytesRead++;
889                         }
890                         else
891                                 break;                          
892                 }
893                 return bytesRead;
894         }
895         
896         public void setShouldStop() {
897                 this.shouldStop= true;
898         }
899
900         public boolean waitResponse(long milliseconds) throws IOException {
901                 long timeout= System.currentTimeMillis() + milliseconds;
902                 while(System.currentTimeMillis() < timeout) {
903                         if(in.ready() || shouldStop) {
904                                 break;
905                         }
906                 }
907                 return in.ready();
908         }
909 }