1 /**********************************************************************
2 Copyright (c) 2000, 2002 IBM Corp. and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Common Public License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/legal/cpl-v10.html
9 Vicente Fernando - www.alfersoft.com.ar - Initial implementation
10 **********************************************************************/
11 package net.sourceforge.phpdt.internal.debug.core;
13 import java.io.IOException;
14 import java.io.BufferedReader;
15 import java.io.OutputStream;
16 import java.util.Vector;
17 import java.lang.System;
18 import org.eclipse.debug.core.DebugException;
19 import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
20 import net.sourceforge.phpdt.internal.debug.core.model.PHPVariable;
21 import net.sourceforge.phpdt.internal.debug.core.model.PHPValue;
22 import net.sourceforge.phpdt.internal.debug.core.PHPDBGMod;
24 public class PHPDBGInterface {
27 public boolean sessionEnded= false;
28 public int sessType= -1;
29 public int BPUnderHit= 0;
30 public String sessID= new String();
33 private int[] LastBPRead= new int[10];
34 private Vector DBGBPList= new Vector();
35 private PHPStackFrame[] DBGStackList;
36 private PHPVariable[] DBGVariableList;
37 private Vector DBGMods= new Vector();
38 private Vector DBGVars= new Vector();
39 private BufferedReader in;
40 private OutputStream os;
41 private boolean shouldStop= false, isRef= false, hasChildren= false, isObject= false;
42 private String evalRet= new String("");
43 private String serGlobals= new String("");
44 private String typeRead= new String("");
45 private String className= new String("");
46 private int finalPos=0, refCounter=0, rawCounter=0;
48 public PHPDBGInterface(BufferedReader in, OutputStream os) {
54 public int addBreakpoint(String mod_name, int line) throws IOException {
55 return setBreakpoint(mod_name, "", line, PHPDBGBase.BPS_ENABLED + PHPDBGBase.BPS_UNRESOLVED, 0, 0, 0, 0, 0);
58 public void removeBreakpoint(String mod_name, int line, int bpNo) throws IOException {
59 setBreakpoint(mod_name, "", line, PHPDBGBase.BPS_DISABLED, 0, 0, 0, bpNo, 0);
62 public void requestDBGVersion() throws IOException {
63 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
64 PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_VER);
66 DBGPacket.addFrame(DBGFrame);
68 DBGPacket.sendPacket(os);
71 // Returns DBG Breakpoint ID
72 private int setBreakpoint(String mod_name, String condition, int line, int state, int istemp, int hitcount, int skiphits, int bpno, int isunderhit) throws IOException {
75 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
76 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_BPS);
77 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
79 modNo= getModByName(mod_name);
82 DBGFrame1.addInt(modNo); // mod number
84 DBGFrame1.addInt(0); // mod number (0 use file name)
87 DBGFrame1.addInt(line); // line number
90 DBGFrame1.addInt(0); // use mod number
93 DBGFrame1.addInt(rawCounter); // ID of FRAME_RAWDATA to send file name
96 DBGFrame1.addInt(state); // state BPS_*
97 DBGFrame1.addInt(istemp); // istemp
98 DBGFrame1.addInt(hitcount); // hit count
99 DBGFrame1.addInt(skiphits); // skip hits
100 DBGFrame1.addInt(0); // ID of condition
101 DBGFrame1.addInt(bpno); // breakpoint number
102 DBGFrame1.addInt(isunderhit); // is under hit
105 DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID
106 DBGFrame2.addInt(mod_name.length() + 1); // length of rawdata (+ null char)
107 DBGFrame2.addString(mod_name); // file name
108 DBGFrame2.addChar('\0'); // null char
109 // First add file name data
110 DBGPacket.addFrame(DBGFrame2);
113 // Second add command data
114 DBGPacket.addFrame(DBGFrame1);
116 DBGPacket.sendPacket(os);
120 // Wait response (1 second) and read response
124 return LastBPRead[8];
127 private void clearLastBP() {
130 for(i=0; i < LastBPRead.length; i++)
134 private void copyToLastBP(int[] BPBody) {
137 for(i=0; i < LastBPRead.length; i++)
138 LastBPRead[i]= BPBody[i];
141 public void continueExecution() throws IOException {
143 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_CONTINUE);
144 DBGPacket.sendPacket(os);
147 private int getBPUnderHit() {
149 int[] dbg_bpl_body= new int[10];
151 // look for bp under hit
152 for(i=0; i < DBGBPList.size(); i++) {
153 dbg_bpl_body= (int[]) DBGBPList.get(i);
154 if(dbg_bpl_body[9] == 1) {
155 BPUnder= dbg_bpl_body[8];
161 public void stepInto() throws IOException {
163 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPINTO);
164 DBGPacket.sendPacket(os);
167 public void stepOver() throws IOException {
169 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOVER);
170 DBGPacket.sendPacket(os);
173 public void stepOut() throws IOException {
175 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOUT);
176 DBGPacket.sendPacket(os);
179 public void stopExecution() throws IOException {
181 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STOP);
182 DBGPacket.sendPacket(os);
185 public PHPVariable[] getVariables(PHPStackFrame stack) throws IOException, DebugException {
186 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
187 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
188 //PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
190 DBGFrame1.addInt(0); // istr = raw data ID
191 DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth
194 String evalBlock= new String("$GLOBALS");
195 DBGFrame2.addInt(1); // FRAME_RAWDATA ID
196 DBGFrame2.addInt(evalBlock.length() + 1); // length of rawdata (+ null char)
197 DBGFrame2.addString(evalBlock); // eval block
198 DBGFrame2.addChar('\0'); // null char
202 DBGPacket.addFrame(DBGFrame1);
204 DBGPacket.sendPacket(os);
209 // Process serialized variables
210 DBGVariableList= procVars(stack);
212 return DBGVariableList;
215 public void evalBlock(String evalString) throws IOException, DebugException {
216 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
217 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
218 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
221 DBGFrame1.addInt(rawCounter); // istr = raw data ID
222 DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth
224 DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID
225 DBGFrame2.addInt(evalString.length() + 1); // length of rawdata (+ null char)
226 DBGFrame2.addString(evalString); // eval block
227 DBGFrame2.addChar('\0'); // null char
229 // Add raw data first
230 DBGPacket.addFrame(DBGFrame2);
232 DBGPacket.addFrame(DBGFrame1);
234 DBGPacket.sendPacket(os);
240 public void flushAllPackets() throws IOException {
241 while(readResponse() != 0);
244 private String getModByNo(int modNo) {
249 for(i=0; i < DBGMods.size(); i++) {
250 dbg_mod= (PHPDBGMod) DBGMods.get(i);
251 if(dbg_mod.getNo() == modNo) {
252 return dbg_mod.getName();
258 private int getModByName(String modName) {
263 for(i=0; i < DBGMods.size(); i++) {
264 dbg_mod= (PHPDBGMod) DBGMods.get(i);
265 if(dbg_mod.getName().equalsIgnoreCase(modName)) {
266 return dbg_mod.getNo();
272 private String getRawFrameData(char[] framesInfo, int frameNo) {
274 int[] dbg_frame= new int[2];
276 while(nextFrame < framesInfo.length) {
277 dbg_frame[0] = PHPDBGBase.Char4ToInt(framesInfo, nextFrame); // frame name
278 dbg_frame[1] = PHPDBGBase.Char4ToInt(framesInfo, nextFrame + 4); // frame size
281 if(dbg_frame[1] == 0) return "";
283 switch(dbg_frame[0]) {
284 case PHPDBGBase.FRAME_RAWDATA:
285 if(frameNo == PHPDBGBase.Char4ToInt(framesInfo, nextFrame)) {
286 int toRead= PHPDBGBase.Char4ToInt(framesInfo, nextFrame + 4);
287 return String.copyValueOf(framesInfo, nextFrame + 8, toRead);
292 nextFrame += dbg_frame[1];
297 public PHPVariable[] getInstVars(PHPVariable phpVar) throws DebugException {
298 Vector vecVars= new Vector();
299 PHPVariable localPHPVar;
302 // already unserialized
303 for(i=0; i < DBGVars.size(); i++) {
304 localPHPVar= (PHPVariable)DBGVars.get(i);
305 if(localPHPVar.getParent() == phpVar) {
306 vecVars.add(localPHPVar);
309 PHPVariable[] arrVars= new PHPVariable[vecVars.size()];
310 arrVars= (PHPVariable[]) vecVars.toArray(arrVars);
315 private PHPVariable[] procVars(PHPStackFrame stack) throws DebugException {
316 Vector vecVars= new Vector();
321 doUnserialize(stack, vecVars, null);
325 return(getInstVars(null));
328 private String readValue(String serialVars) throws DebugException {
329 int startPos=0, endPos=0, lenStr=0, i=0, elements=0;
330 String ret= new String("");
332 switch(serialVars.charAt(0)) {
333 case 'a': // associative array, a:elements:{[index][value]...}
336 endPos= serialVars.indexOf(':', startPos + 1);
337 if(endPos == -1) return "";
338 finalPos += endPos + 2;
339 ret= new String(serialVars.substring(startPos + 1, endPos));
343 case 'O': // object, O:name_len:"name":elements:{[attribute][value]...}
347 endPos= serialVars.indexOf(':', startPos + 1);
348 if(endPos == -1) return "";
351 lenStr= Integer.parseInt(serialVars.substring(startPos + 1, endPos));
352 startPos= endPos + 2;
353 endPos= lenStr + startPos;
354 className= new String(serialVars.substring(startPos, endPos).toString());
356 // get num of elements
357 startPos= endPos + 1;
358 endPos= serialVars.indexOf(':', startPos + 1);
359 if(endPos == -1) return "";
360 finalPos += endPos + 2;
361 ret= new String(serialVars.substring(startPos + 1, endPos));
366 case 's': // string, s:length:"data";
369 endPos= serialVars.indexOf(':', startPos + 1);
370 if(endPos == -1) return "";
372 lenStr= Integer.parseInt(serialVars.substring(startPos + 1, endPos));
373 startPos= endPos + 2;
374 endPos= lenStr + startPos;
375 ret= new String(serialVars.substring(startPos, endPos).toString());
376 finalPos += endPos + 2;
378 case 'i': // integer, i:123;
381 endPos= serialVars.indexOf(';', startPos + 1);
382 if(endPos == -1) return "";
384 ret= new String(serialVars.substring(startPos + 1, endPos).toString());
385 finalPos += endPos + 1;
387 case 'd': // double (float), d:1.23;
390 endPos= serialVars.indexOf(';', startPos + 1);
391 if(endPos == -1) return "";
393 ret= new String(serialVars.substring(startPos + 1, endPos).toString());
394 finalPos += endPos + 1;
396 case 'N': // NULL, N;
401 case 'b': // bool, b:0 or 1
403 ret= (serialVars.charAt(2) == '1')?"true":"false";
404 finalPos += endPos + 4;
406 case 'z': // resource, z:typename_len:"typename":valres;
407 typeRead= "resource";
410 endPos= serialVars.indexOf(':', startPos + 1);
411 if(endPos == -1) return "";
413 // get resource type name
414 lenStr= Integer.parseInt(serialVars.substring(startPos + 1, endPos));
415 startPos= endPos + 2;
416 endPos= lenStr + startPos;
417 className= new String(serialVars.substring(startPos, endPos).toString());
419 // get resource value
420 startPos= endPos + 1;
421 endPos= serialVars.indexOf(';', startPos + 1);
422 if(endPos == -1) return "";
423 ret= new String(serialVars.substring(startPos + 1, endPos));
424 finalPos += endPos + 1;
428 typeRead= "reference";
430 endPos= serialVars.indexOf(';', startPos + 1);
431 if(endPos == -1) return "0";
433 ret= new String(serialVars.substring(startPos + 1, endPos));
434 finalPos += endPos + 1;
451 private void doUnserialize(PHPStackFrame stack, Vector vecVars, PHPVariable parent) throws DebugException {
453 PHPVariable newVar= null;
454 String value= new String("");
455 String name= new String("");
456 String tmp= new String("");
458 if(finalPos > serGlobals.length() || serGlobals.equals("") || serGlobals.substring(finalPos).equals("")) return;
463 name= readValue(serGlobals.substring(finalPos));
467 if(refCounter == 0) {
474 value= readValue(serGlobals.substring(finalPos));
477 if(!name.equals("")) {
480 for(i=0; i < vecVars.size(); i++) {
481 varPHP= (PHPVariable) vecVars.get(i);
482 if(varPHP.getObjectId().equals(value)) {
483 newVar= new PHPVariable(stack, name, "local", true, (PHPValue)varPHP.getValue());
488 newVar= new PHPVariable(stack, name, "local", false, null);
492 newVar= new PHPVariable(stack, name, "local", value, typeRead, hasChildren, Integer.toString(refCounter), className);
494 newVar.setParent(parent);
498 elements= Integer.parseInt(value);
499 for(i=0; i < elements; i++)
500 doUnserialize(stack, vecVars, newVar);
507 public int readResponse() throws IOException {
508 int bytesToRead=0, nextFrame=0, i=0, cmdReceived=0, stackIndex=0;
509 char[] dbg_header_struct_read= new char[16];
510 int[] dbg_header_struct= new int[4];
511 int[] dbg_bpl_tmp= new int[10];
512 int[] dbg_frame= new int[2];
513 int[] dbg_eval_tmp= new int[3];
514 Vector rawList= new Vector();
515 Vector stackList= new Vector();
516 PHPStackFrame[] newStackList;
521 while(readInput(dbg_header_struct_read, 16) != 0) {
522 dbg_header_struct[0] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 0);
523 dbg_header_struct[1] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 4);
524 dbg_header_struct[2] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 8);
525 dbg_header_struct[3] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 12);
527 // Check DBG sync bytes
528 if(dbg_header_struct[0] != 0x5953) return 0;
530 cmdReceived= dbg_header_struct[1];
531 bytesToRead= dbg_header_struct[3];
533 System.out.println("Response Received: " + cmdReceived);
535 char[] entirePack= new char[bytesToRead];
537 if(bytesToRead > 0) {
538 if(readInput(entirePack, bytesToRead) < bytesToRead) return 0;
541 // First process frames
543 while(nextFrame < bytesToRead) {
544 dbg_frame[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame); // frame name
545 dbg_frame[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // frame size
547 if(dbg_frame[1] == 0) return 0;
548 switch(dbg_frame[0]) {
549 case PHPDBGBase.FRAME_STACK:
550 int[] dbg_stack_new= new int[4];
551 dbg_stack_new[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); // line no
552 dbg_stack_new[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // mod no
553 dbg_stack_new[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8); // scope id
554 dbg_stack_new[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12); // id of description string
557 if(!getModByNo(dbg_stack_new[1]).equals("")) {
558 PHPStackFrame newStack= new PHPStackFrame(null, getModByNo(dbg_stack_new[1]), dbg_stack_new[0], stackIndex, getRawFrameData(entirePack, dbg_stack_new[3]));
559 stackList.add(newStack);
562 case PHPDBGBase.FRAME_SOURCE:
564 case PHPDBGBase.FRAME_SRC_TREE:
566 case PHPDBGBase.FRAME_RAWDATA:
568 case PHPDBGBase.FRAME_ERROR:
570 case PHPDBGBase.FRAME_EVAL:
571 String evalString= new String("");
572 dbg_eval_tmp[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); // istr
573 dbg_eval_tmp[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // iresult
574 dbg_eval_tmp[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8); // ierror
576 evalRet= getRawFrameData(entirePack, dbg_eval_tmp[1]);
577 evalString= getRawFrameData(entirePack, dbg_eval_tmp[0]);
580 case PHPDBGBase.FRAME_BPS:
582 case PHPDBGBase.FRAME_BPL:
583 int[] dbg_bpl_new= new int[10];
584 dbg_bpl_new[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
585 dbg_bpl_new[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4);
586 dbg_bpl_new[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8);
587 dbg_bpl_new[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12);
588 dbg_bpl_new[4] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 16);
589 dbg_bpl_new[5] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 20);
590 dbg_bpl_new[6] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 24);
591 dbg_bpl_new[7] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 28);
592 dbg_bpl_new[8] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 32);
593 dbg_bpl_new[9] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 36);
595 // look if breakpoint already exists in vector
596 for(i=0; i < DBGBPList.size(); i++) {
597 dbg_bpl_tmp= (int[]) DBGBPList.get(i);
598 if(dbg_bpl_tmp[8] == dbg_bpl_new[8]) {
604 // add breakpoint to vector
605 DBGBPList.add(dbg_bpl_new);
606 copyToLastBP(dbg_bpl_new);
609 if(getModByNo(dbg_bpl_new[0]).equals("")) {
610 String fileName= new String(getRawFrameData(entirePack, dbg_bpl_new[2]));
612 if(fileName.length() > 0) fileName= fileName.substring(0, fileName.length() - 1);
613 PHPDBGMod modNew= new PHPDBGMod(dbg_bpl_new[0], fileName);
617 case PHPDBGBase.FRAME_VER:
619 case PHPDBGBase.FRAME_SID:
621 case PHPDBGBase.FRAME_SRCLINESINFO:
623 case PHPDBGBase.FRAME_SRCCTXINFO:
625 case PHPDBGBase.FRAME_LOG:
627 case PHPDBGBase.FRAME_PROF:
629 case PHPDBGBase.FRAME_PROF_C:
631 case PHPDBGBase.FRAME_SET_OPT:
635 nextFrame += dbg_frame[1];
638 // Now process command
639 switch(cmdReceived) {
640 case PHPDBGBase.DBGC_REPLY:
642 case PHPDBGBase.DBGC_STARTUP:
644 case PHPDBGBase.DBGC_END:
647 case PHPDBGBase.DBGC_BREAKPOINT:
648 newStackList= new PHPStackFrame[stackList.size()];
649 newStackList= (PHPStackFrame[]) stackList.toArray(newStackList);
650 DBGStackList= newStackList;
651 BPUnderHit= getBPUnderHit();
653 case PHPDBGBase.DBGC_STEPINTO_DONE:
654 case PHPDBGBase.DBGC_STEPOVER_DONE:
655 case PHPDBGBase.DBGC_STEPOUT_DONE:
656 case PHPDBGBase.DBGC_EMBEDDED_BREAK:
658 newStackList= new PHPStackFrame[stackList.size()];
659 newStackList= (PHPStackFrame[]) stackList.toArray(newStackList);
660 DBGStackList= newStackList;
662 case PHPDBGBase.DBGC_ERROR:
663 newStackList= new PHPStackFrame[stackList.size()];
664 newStackList= (PHPStackFrame[]) stackList.toArray(newStackList);
665 DBGStackList= newStackList;
667 case PHPDBGBase.DBGC_LOG:
669 case PHPDBGBase.DBGC_SID:
671 case PHPDBGBase.DBGC_PAUSE:
679 public PHPStackFrame[] getStackList() {
683 private int readInput(char[] buffer, int bytes) throws IOException {
686 for(int i=0; i < bytes; i++) {
688 buffer[i]= (char) (in.read() & 0x00FF);
697 public void setShouldStop() {
698 this.shouldStop= true;
701 public void waitResponse(long milliseconds) throws IOException {
702 long timeout= System.currentTimeMillis() + milliseconds;
703 while(System.currentTimeMillis() < timeout) {
704 if(in.ready() || shouldStop) {