001: /*
002: * @(#)VisualDebuggerModel.java 1.3 05/03/18
003: *
004: * Copyright (c) 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution of
007: * this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.tools;
010:
011: import java.io.PrintWriter;
012: import java.util.Enumeration;
013: import java.util.Hashtable;
014: import java.util.Vector;
015: import pnuts.lang.Context;
016: import pnuts.lang.Pnuts;
017: import pnuts.lang.PnutsException;
018: import pnuts.lang.Runtime;
019: import pnuts.lang.SimpleNode;
020: import pnuts.lang.PnutsParserTreeConstants;
021:
022: public class VisualDebuggerModel extends Runtime implements Debugger {
023: DebugContext dc;
024: boolean quit;
025: private Object currentSource;
026: private int currentLine;
027: private int n_nexts;
028: private int n_steps;
029: private int command;
030: private Hashtable files; // source -> lines (break points)
031: private boolean initialized = false;
032: private int initialEvalDepth;
033: private int initialCallDepth;
034: private int e_depth;
035: private int c_depth;
036: private PrintWriter errorStream;
037: private Object traceTag;
038: private Context parent;
039: private VisualDebuggerView view;
040:
041: static final int OPEN = 1;
042: static final int STEP = 2;
043: static final int STEP_UP = 3;
044: static final int NEXT = 4;
045: static final int CONT = 5;
046: static final int CLOSE = 6;
047: static final int CLEAR_BP = 7;
048: static final int INSPECT = 8;
049:
050: public VisualDebuggerModel() {
051: this .files = new Hashtable();
052: }
053:
054: void setView(VisualDebuggerView view) {
055: this .view = view;
056: }
057:
058: void init(DebugContext dc) {
059: quit = false;
060: this .dc = dc;
061: dc.setDebugger(this );
062: initialEvalDepth = Pnuts.evalDepth(dc);
063: e_depth = 0;
064: c_depth = 0;
065: n_steps = 1;
066: n_nexts = 1;
067: }
068:
069: public synchronized void do_step(int n) {
070: command = STEP;
071: n_steps = n;
072: notifyAll();
073: }
074:
075: public synchronized void do_stepup() {
076: command = STEP_UP;
077: c_depth = dc.getCallDepth();
078: e_depth = dc.getEvalDepth();
079: notifyAll();
080: }
081:
082: public synchronized void do_next(int n) {
083: command = NEXT;
084: n_nexts = n;
085: notifyAll();
086: }
087:
088: public synchronized void do_cont() {
089: command = CONT;
090: n_steps = 0;
091: n_nexts = 0;
092: notifyAll();
093: }
094:
095: public synchronized void do_close() {
096: command = CONT;
097: quit = true;
098: notifyAll();
099: }
100:
101: public Object getCurrentSource() {
102: return currentSource;
103: }
104:
105: public void setBreakPoint(Object source, int lineno) {
106: if (source == null) {
107: return;
108: }
109: Vector lines = (Vector) files.get(source);
110: if (lines == null) {
111: lines = new Vector();
112: files.put(source, lines);
113: }
114: Integer i = new Integer(lineno + 1);
115: if (!lines.contains(i)) {
116: lines.addElement(i);
117: }
118: }
119:
120: public void removeBreakPoint(Object source, int lineno) {
121: if (source == null) {
122: return;
123: }
124: Vector lines = (Vector) files.get(source);
125: if (lines == null) {
126: return;
127: }
128: lines.removeElement(new Integer(lineno + 1));
129: }
130:
131: public Vector getBreakPoints(Object source) {
132: if (source == null) {
133: return null;
134: }
135: return (Vector) files.get(source);
136: }
137:
138: public void clearBreakPoints() {
139: files.clear();
140: }
141:
142: public void signal(CommandEvent event) {
143: this .dc = (DebugContext) event.getSource();
144:
145: int eventType = event.getType();
146:
147: if (eventType == CommandEvent.EXITED) {
148: if (dc.getEvalDepth() <= initialEvalDepth
149: && dc.getCallDepth() <= initialCallDepth) {
150: if (!quit) {
151: showScript(dc.getScriptSource(), -1, null, dc);
152: }
153: initialized = false;
154:
155: }
156: return;
157: }
158:
159: if (eventType == CommandEvent.LINE_UPDATED) {
160:
161: SimpleNode node = (SimpleNode) event.getArg();
162: int beginLine = dc.getBeginLine();
163: int endLine = dc.getEndLine();
164: Object source = dc.getScriptSource();
165:
166: if (!initialized) {
167: init(dc);
168: initialized = true;
169: c_depth = dc.getCallDepth();
170: e_depth = dc.getEvalDepth();
171: initialCallDepth = dc.getCallDepth();
172:
173: showScript(source, beginLine, node, dc);
174: waitForCommands();
175: currentLine = beginLine;
176: return;
177: }
178:
179: if (hasToStop(source, node, beginLine, endLine)) {
180: c_depth = dc.getCallDepth();
181: e_depth = dc.getEvalDepth();
182: showScript(source, beginLine, node, dc);
183: waitForCommands();
184: currentLine = beginLine;
185: }
186: } else if (eventType == CommandEvent.EXCEPTION) {
187: Throwable t = (Throwable) event.getArg();
188: if (t instanceof PnutsException) {
189: PnutsException pe = (PnutsException) t;
190: Object source = pe.getScriptSource();
191: int beginLine = pe.getLine();
192: showScript(source, beginLine, null, dc);
193: }
194: initialized = false;
195: }
196: }
197:
198: boolean checkBreakPoint(Vector lines, SimpleNode node, int begin,
199: int end) {
200: if (node != null
201: && node.id == PnutsParserTreeConstants.JJTBLOCK) {
202: return false;
203: }
204: for (Enumeration e = lines.elements(); e.hasMoreElements();) {
205: int bp = ((Integer) e.nextElement()).intValue();
206: if (bp >= begin && bp <= end) {
207: return true;
208: }
209: }
210: return false;
211: }
212:
213: boolean hasToStop(Object source, SimpleNode node, int beginLine,
214: int endLine) {
215: if (source instanceof Runtime) {
216: return false;
217: }
218: if (source == null && node != null && command != CONT) {
219: return true;
220: }
221: if (command == OPEN) {
222: currentLine = beginLine;
223: command = 0;
224: return true;
225: } else if (command == STEP) {
226: if (--n_steps < 1) {
227: return true;
228: }
229: } else if (command == NEXT) {
230: int d1 = dc.getEvalDepth();
231: int d2 = dc.getCallDepth();
232: if (e_depth >= d1
233: && c_depth >= d2
234: && (currentSource != source || currentLine != beginLine)) {
235: if (--n_nexts < 1) {
236: return true;
237: }
238: }
239: } else if (command == STEP_UP) {
240: int d1 = dc.getEvalDepth();
241: int d2 = dc.getCallDepth();
242: if (e_depth > d1 || e_depth >= d1 && c_depth > d2) {
243: return true;
244: }
245: }
246:
247: Vector lines = getBreakPoints(source);
248:
249: if (lines != null
250: && checkBreakPoint(lines, node, beginLine, endLine)) {
251: currentLine = beginLine;
252: return true;
253: }
254:
255: return false;
256: }
257:
258: synchronized void waitForCommands() {
259: command = 0;
260: try {
261: while (command == 0) {
262: wait();
263: }
264: } catch (InterruptedException e) {
265: }
266: if (quit) {
267: escape(null);
268: }
269: }
270:
271: protected void showScript(Object source, int line, SimpleNode node,
272: Context context) {
273: if (!quit && view != null) {
274: view.update(source, line, node, context);
275: }
276: currentSource = source;
277: }
278: }
|