1 | // -*- c-basic-offset: 2 -*- |
2 | /* |
3 | * This file is part of the KDE libraries |
4 | * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) |
5 | * Copyright (C) 2001 Peter Kelly (pmk@post.com) |
6 | * |
7 | * This library is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2 of the License, or (at your option) any later version. |
11 | * |
12 | * This library is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with this library; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | * |
21 | */ |
22 | |
23 | #include "debugger.h" |
24 | #include "nodes.h" |
25 | #include <config-kjs.h> |
26 | #include "ustring.h" |
27 | |
28 | #include "internal.h" |
29 | |
30 | using namespace KJS; |
31 | |
32 | // ------------------------------ Debugger ------------------------------------- |
33 | |
34 | namespace KJS { |
35 | struct AttachedInterpreter |
36 | { |
37 | AttachedInterpreter(Interpreter *i, AttachedInterpreter *ai) : interp(i), next(ai) { ++Debugger::debuggersPresent; } |
38 | ~AttachedInterpreter() { --Debugger::debuggersPresent; } |
39 | Interpreter *interp; |
40 | AttachedInterpreter *next; |
41 | }; |
42 | |
43 | } |
44 | |
45 | int Debugger::debuggersPresent = 0; |
46 | |
47 | Debugger::Debugger() |
48 | { |
49 | lastLineRan = 0; |
50 | rep = new DebuggerImp(); |
51 | lastSourceParsed = -1; |
52 | } |
53 | |
54 | Debugger::~Debugger() |
55 | { |
56 | detach(0); |
57 | delete rep; |
58 | } |
59 | |
60 | void Debugger::attach(Interpreter* interp) |
61 | { |
62 | Debugger *other = interp->debugger(); |
63 | if (other == this) |
64 | return; |
65 | if (other) |
66 | other->detach(interp); |
67 | interp->setDebugger(this); |
68 | rep->interps = new AttachedInterpreter(interp, rep->interps); |
69 | } |
70 | |
71 | void Debugger::detach(Interpreter* interp) |
72 | { |
73 | // iterate the addresses where AttachedInterpreter pointers are stored |
74 | // so we can unlink items from the list |
75 | AttachedInterpreter **p = &rep->interps; |
76 | AttachedInterpreter *q; |
77 | while ((q = *p)) { |
78 | if (!interp || q->interp == interp) { |
79 | *p = q->next; |
80 | q->interp->setDebugger(0); |
81 | delete q; |
82 | } else |
83 | p = &q->next; |
84 | } |
85 | |
86 | if (interp) |
87 | latestExceptions.remove(interp); |
88 | else |
89 | latestExceptions.clear(); |
90 | } |
91 | |
92 | bool Debugger::hasHandledException(ExecState *exec, JSValue *exception) |
93 | { |
94 | if (latestExceptions.get(exec->dynamicInterpreter()).get() == exception) |
95 | return true; |
96 | |
97 | latestExceptions.set(exec->dynamicInterpreter(), exception); |
98 | return false; |
99 | } |
100 | |
101 | bool Debugger::sourceParsed(ExecState * /*exec*/, int /*sourceId*/, const UString &/*sourceURL*/, |
102 | const UString &/*source*/, int /*startingLineNumber*/, int /*errorLine*/, const UString & /*errorMsg*/) |
103 | { |
104 | return true; |
105 | } |
106 | |
107 | bool Debugger::exception(ExecState * /*exec*/, int /*sourceId*/, int /*lineno*/, |
108 | JSValue * /*exception*/) |
109 | { |
110 | return true; |
111 | } |
112 | |
113 | bool Debugger::atStatement(ExecState * /*exec*/, int /*sourceId*/, int /*firstLine*/, |
114 | int /*lastLine*/) |
115 | { |
116 | return true; |
117 | } |
118 | |
119 | void Debugger::reportAtStatement(ExecState *exec, int sourceId, int firstLine, int lastLine) |
120 | { |
121 | lastLineRan = firstLine; |
122 | atStatement(exec, sourceId, firstLine, lastLine); |
123 | } |
124 | |
125 | void Debugger::reportException(ExecState *exec, JSValue *exceptionVal) |
126 | { |
127 | if (!hasHandledException(exec, exceptionVal)) |
128 | exception(exec, exec->currentBody() ? exec->currentBody()->sourceId() : lastSourceParsed, lastLineRan, exceptionVal); |
129 | } |
130 | |
131 | bool Debugger::enterContext(ExecState * /*exec*/, int /*sourceId*/, int /*lineno*/, |
132 | JSObject * /*function*/, const List & /*args*/) |
133 | { |
134 | return true; |
135 | } |
136 | |
137 | bool Debugger::exitContext(ExecState * /*exec*/, int /*sourceId*/, int /*lineno*/, |
138 | JSObject * /*function*/) |
139 | { |
140 | return true; |
141 | } |
142 | |
143 | bool Debugger::shouldReindentSources() const |
144 | { |
145 | return false; |
146 | } |
147 | |
148 | bool Debugger::shouldReportCaught() const |
149 | { |
150 | return false; |
151 | } |
152 | |
153 | void Debugger::reportSourceParsed(ExecState *exec, FunctionBodyNode *body, |
154 | int sourceId, UString sourceURL, const UString &source, |
155 | int startingLineNumber, int errorLine, const UString &errorMsg) |
156 | { |
157 | lastSourceParsed = sourceId; |
158 | UString code = source; |
159 | if (shouldReindentSources() && body) |
160 | code = body->reindent(startingLineNumber); |
161 | sourceParsed(exec, sourceId, sourceURL, code, startingLineNumber, errorLine, errorMsg); |
162 | } |
163 | |