make #includes consistent
[hiphop-php.git] / hphp / runtime / eval / debugger / cmd / cmd_interrupt.cpp
blob04b5b5148df0546c92aa5d622e6c858b086ad3b7
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/eval/debugger/cmd/cmd_interrupt.h"
18 #include "hphp/runtime/eval/debugger/cmd/cmd_break.h"
19 #include "hphp/runtime/eval/debugger/cmd/cmd_print.h"
21 namespace HPHP { namespace Eval {
22 ///////////////////////////////////////////////////////////////////////////////
24 TRACE_SET_MOD(debugger);
26 void CmdInterrupt::sendImpl(DebuggerThriftBuffer &thrift) {
27 DebuggerCommand::sendImpl(thrift);
28 thrift.write(m_interrupt);
29 thrift.write(m_program);
30 thrift.write(m_errorMsg);
31 thrift.write(m_threadId);
32 // Used to be m_pendingJump, but that's been removed. Write false until
33 // we rev the protocol.
34 thrift.write(false);
35 if (m_site) {
36 thrift.write(true);
37 thrift.write(m_site->getFile());
38 thrift.write(m_site->getLine0());
39 thrift.write(m_site->getChar0());
40 thrift.write(m_site->getLine1());
41 thrift.write(m_site->getChar1());
42 thrift.write(m_site->getNamespace());
43 thrift.write(m_site->getClass());
44 thrift.write(m_site->getFunction());
45 Variant e = m_site->getException();
46 if (e.isNull()) {
47 thrift.write("");
48 } else if (e.isObject()) {
49 thrift.write(e.toObject()->o_getClassName());
50 } else {
51 String ex(BreakPointInfo::ErrorClassName);
52 thrift.write(ex);
54 thrift.write(e.toString());
55 } else {
56 thrift.write(false);
58 BreakPointInfo::SendImpl(m_matched, thrift);
61 void CmdInterrupt::recvImpl(DebuggerThriftBuffer &thrift) {
62 DebuggerCommand::recvImpl(thrift);
63 thrift.read(m_interrupt);
64 thrift.read(m_program);
65 thrift.read(m_errorMsg);
66 thrift.read(m_threadId);
67 // Used to be m_pendingJump, but that's been removed. Read a dummy bool until
68 // we rev the protocol.
69 bool dummy;
70 thrift.read(dummy);
71 m_bpi = BreakPointInfoPtr(new BreakPointInfo());
72 bool site; thrift.read(site);
73 if (site) {
74 thrift.read(m_bpi->m_file);
75 thrift.read(m_bpi->m_line1);
76 thrift.read(m_bpi->m_char1);
77 thrift.read(m_bpi->m_line2);
78 thrift.read(m_bpi->m_char2);
79 DFunctionInfoPtr func(new DFunctionInfo());
80 thrift.read(func->m_namespace);
81 thrift.read(func->m_class);
82 thrift.read(func->m_function);
83 m_bpi->m_funcs.push_back(func);
84 thrift.read(m_bpi->m_exceptionClass);
85 thrift.read(m_bpi->m_exceptionObject);
87 BreakPointInfo::RecvImpl(m_matched, thrift);
90 std::string CmdInterrupt::desc() const {
91 switch (m_interrupt) {
92 case SessionStarted:
93 if (!m_program.empty()) {
94 return m_program + " loaded.";
96 return "Program loaded.";
97 case SessionEnded:
98 if (!m_program.empty()) {
99 return m_program + " exited normally.";
101 return "Program exited normally.";
102 case RequestStarted:
103 if (!m_program.empty()) {
104 return m_program + " started.";
106 return "Web request started.";
107 case RequestEnded:
108 if (!m_program.empty()) {
109 return m_program + " ended.";
111 return "Web request ended.";
112 case PSPEnded:
113 if (!m_program.empty()) {
114 return "Post-Send Processing for " + m_program + " was ended.";
116 return "Post-Send Processing was ended.";
117 case HardBreakPoint:
118 case BreakPointReached:
119 case ExceptionThrown: {
120 assert(m_site);
121 if (m_site) {
122 return m_site->desc();
124 return "Breakpoint reached.";
128 assert(false);
129 return "";
132 bool CmdInterrupt::onClient(DebuggerClient *client) {
133 client->setCurrentLocation(m_threadId, m_bpi);
134 if (!client->getDebuggerSmallStep()) {
135 // Adjust line and char if it's not small stepping
136 if (m_bpi->m_line1 == m_bpi->m_line2) {
137 m_bpi->m_char1 = 1;
138 m_bpi->m_char2 = 100;
141 client->setMatchedBreakPoints(m_matched);
143 switch (m_interrupt) {
144 case SessionStarted:
145 if (!m_program.empty()) {
146 client->info("Program %s loaded. Type '[r]un' or '[c]ontinue' to go.",
147 m_program.c_str());
148 m_bpi->m_file = m_program;
150 break;
151 case SessionEnded:
152 if (!m_program.empty()) {
153 client->info("Program %s exited normally.", m_program.c_str());
155 break;
156 case RequestStarted:
157 if (!m_program.empty()) {
158 client->info("Web request %s started.", m_program.c_str());
160 break;
161 case RequestEnded:
162 if (!m_program.empty()) {
163 client->info("Web request %s ended.", m_program.c_str());
165 break;
166 case PSPEnded:
167 if (!m_program.empty()) {
168 client->info("Post-Send Processing for %s was ended.",
169 m_program.c_str());
171 break;
172 case HardBreakPoint:
173 case BreakPointReached:
174 case ExceptionThrown: {
175 bool found = false;
176 bool toggled = false;
177 BreakPointInfoPtrVec *bps = client->getBreakPoints();
178 for (unsigned int i = 0; i < m_matched.size(); i++) {
179 BreakPointInfoPtr bpm = m_matched[i];
180 BreakPointInfoPtr bp;
181 int index = 0;
182 for (; index < (int)bps->size(); index++) {
183 if (bpm->same((*bps)[index])) {
184 bp = (*bps)[index];
185 break;
188 if (bp) {
189 found = true;
190 if (bp->m_state == BreakPointInfo::Once) {
191 bp->m_state = BreakPointInfo::Disabled;
192 toggled = true;
194 if (m_interrupt == BreakPointReached ||
195 m_interrupt == HardBreakPoint) {
196 client->info("Breakpoint %d reached %s", bp->index(),
197 m_bpi->site().c_str());
198 client->shortCode(m_bpi);
199 } else {
200 if (m_bpi->m_exceptionClass == BreakPointInfo::ErrorClassName) {
201 client->info("Breakpoint %d reached: An error occurred %s",
202 bp->index(), m_bpi->site().c_str());
203 client->shortCode(m_bpi);
204 client->error("Error Message: %s",
205 m_bpi->m_exceptionObject.c_str());
206 } else {
207 client->info("Breakpoint %d reached: Throwing %s %s",
208 bp->index(),
209 m_bpi->m_exceptionClass.c_str(),
210 m_bpi->site().c_str());
211 client->shortCode(m_bpi);
212 client->output(m_bpi->m_exceptionObject);
215 if (!bpm->m_output.empty()) {
216 client->print(bpm->m_output);
220 if (toggled) {
221 CmdBreak::SendClientBreakpointListToServer(client);
223 if (!found) {
224 if (m_interrupt == HardBreakPoint) {
225 // for HardBreakPoint, default the frame to the caller
226 client->setFrame(1);
228 client->info("Break %s", m_bpi->site().c_str());
229 client->shortCode(m_bpi);
231 break;
235 if (!m_errorMsg.empty()) {
236 client->error(m_errorMsg);
239 // watches
240 switch (m_interrupt) {
241 case SessionStarted:
242 case RequestStarted:
243 break;
244 default: {
245 DebuggerClient::WatchPtrVec &watches = client->getWatches();
246 for (int i = 0; i < (int)watches.size(); i++) {
247 if (i > 0) client->output("");
248 client->info("Watch %d: %s =", i + 1, watches[i]->second.c_str());
249 Variant v = CmdPrint().processWatch(client, watches[i]->first,
250 watches[i]->second);
251 client->output(CmdPrint::FormatResult(watches[i]->first, v));
256 return true;
259 static const StaticString s_format("format");
260 static const StaticString s_php("php");
261 static const StaticString s_value("value");
263 void CmdInterrupt::setClientOutput(DebuggerClient *client) {
264 client->setOutputType(DebuggerClient::OTCodeLoc);
265 client->setOTFileLine(m_bpi->m_file, m_bpi->m_line1);
266 Array values;
267 DebuggerClient::WatchPtrVec &watches = client->getWatches();
268 for (int i = 0; i < (int)watches.size(); i++) {
269 ArrayInit watch(3);
270 watch.set(s_format, watches[i]->first);
271 watch.set(s_php, watches[i]->second);
272 Variant v = CmdPrint().processWatch(client, watches[i]->first,
273 watches[i]->second);
274 watch.set(s_value, CmdPrint::FormatResult(watches[i]->first, v));
275 values.append(watch.create());
277 client->setOTValues(values);
280 bool CmdInterrupt::onServer(DebuggerProxy *proxy) {
281 return proxy->sendToClient(this);
284 bool CmdInterrupt::shouldBreak(const BreakPointInfoPtrVec &bps) {
286 switch (m_interrupt) {
287 case SessionStarted:
288 case SessionEnded:
289 case HardBreakPoint:
290 return true; // always break
291 case RequestStarted:
292 case RequestEnded:
293 case PSPEnded:
294 case BreakPointReached:
295 case ExceptionThrown:
296 m_matched.clear();
297 if (m_site) {
298 for (unsigned int i = 0; i < bps.size(); i++) {
299 if (bps[i]->m_state != BreakPointInfo::Disabled &&
300 bps[i]->match(getInterruptType(), *getSite())) {
301 BreakPointInfoPtr bp(new BreakPointInfo());
302 *bp = *bps[i]; // make a copy
303 m_matched.push_back(bp);
307 return !m_matched.empty();
309 assert(false);
310 return false;
313 std::string CmdInterrupt::getFileLine() const {
314 string ret;
315 if (m_site) {
316 if (m_site->getFile()) {
317 ret = m_site->getFile();
319 ret += ":" + lexical_cast<string>(m_site->getLine0());
321 return ret;
324 ///////////////////////////////////////////////////////////////////////////////