Use custom AssemblyAnnotationWriter to improve vasm/llvm printing
[hiphop-php.git] / hphp / runtime / debugger / debugger_client.h
blob46870d6551b9c9ee0d95f2c2a9fc5b9b4f0e563d
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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 #ifndef incl_HPHP_EVAL_DEBUGGER_CLIENT_H_
18 #define incl_HPHP_EVAL_DEBUGGER_CLIENT_H_
20 #include <boost/smart_ptr/shared_array.hpp>
21 #include <map>
22 #include <memory>
23 #include <set>
24 #include <utility>
25 #include <vector>
27 #include "hphp/runtime/debugger/debugger.h"
28 #include "hphp/runtime/debugger/debugger_client_settings.h"
29 #include "hphp/runtime/base/debuggable.h"
30 #include "hphp/util/text-color.h"
31 #include "hphp/util/hdf.h"
32 #include "hphp/util/mutex.h"
34 namespace HPHP {
36 class StringBuffer;
38 namespace Eval {
40 ///////////////////////////////////////////////////////////////////////////////
42 struct DebuggerCommand;
43 struct CmdInterrupt;
45 using DebuggerCommandPtr = std::shared_ptr<DebuggerCommand>;
47 class DebuggerClient {
48 public:
49 static int LineWidth;
50 static int CodeBlockSize;
51 static int ScrollBlockSize;
52 static const char *LineNoFormat;
53 static const char *LineNoFormatWithStar;
54 static const char *LocalPrompt;
55 static const char *ConfigFileName;
56 static const char *LegacyConfigFileName;
57 static const char *HistoryFileName;
58 static std::string HomePrefix;
59 static std::string SourceRoot;
61 static bool UseColor;
62 static bool NoPrompt;
63 static const char *HelpColor;
64 static const char *InfoColor;
65 static const char *OutputColor;
66 static const char *ErrorColor;
67 static const char *ItemNameColor;
68 static const char *HighlightForeColor;
69 static const char *HighlightBgColor;
70 static const char *DefaultCodeColors[];
71 static const int MinPrintLevel = 1;
73 public:
74 static void LoadColors(const IniSetting::Map& ini, Hdf hdf);
75 static const char *LoadColor(const IniSetting::Map& ini, Hdf hdf,
76 const char *defaultName);
77 static const char *LoadBgColor(const IniSetting::Map& ini, Hdf hdf,
78 const char *defaultName);
79 static void LoadCodeColor(CodeColor index, const IniSetting::Map& ini,
80 Hdf hdf, const char *defaultName);
82 /**
83 * Starts/stops a debugger client.
85 static SmartPtr<Socket> Start(const DebuggerClientOptions &options);
86 static void Stop();
88 /**
89 * Pre-defined auto-complete lists. Append-only, as they will be used in
90 * binary communication protocol.
92 enum AutoComplete {
93 AutoCompleteFileNames,
94 AutoCompleteVariables,
95 AutoCompleteConstants,
96 AutoCompleteClasses,
97 AutoCompleteFunctions,
98 AutoCompleteClassMethods,
99 AutoCompleteClassProperties,
100 AutoCompleteClassConstants,
101 AutoCompleteKeyword,
102 AutoCompleteCode,
104 AutoCompleteCount
106 static const char **GetCommands();
108 typedef std::vector<std::string> LiveList;
109 typedef boost::shared_array<LiveList> LiveListsPtr;
110 static LiveListsPtr CreateNewLiveLists() {
111 return LiveListsPtr(new LiveList[DebuggerClient::AutoCompleteCount]);
113 std::vector<std::string> getAllCompletions(std::string const &text);
116 * Helpers
118 static void AdjustScreenMetrics();
119 static bool Match(const char *input, const char *cmd);
120 static bool IsValidNumber(const std::string &arg);
121 static String FormatVariable(const Variant& v, int maxlen = 80,
122 char format = 'd');
123 static String FormatInfoVec(const IDebuggable::InfoVec &info,
124 int *nameLen = nullptr);
125 static String FormatTitle(const char *title);
127 public:
128 explicit DebuggerClient();
129 ~DebuggerClient();
132 * Main processing functions.
134 void console();
135 // Carries out the current command and returns true if the command completed.
136 bool process();
137 void quit();
138 void onSignal(int sig);
139 int pollSignal();
142 * Output functions
144 void print (const char *fmt, ...) ATTRIBUTE_PRINTF(2,3);
145 void help (const char *fmt, ...) ATTRIBUTE_PRINTF(2,3);
146 void info (const char *fmt, ...) ATTRIBUTE_PRINTF(2,3);
147 void output (const char *fmt, ...) ATTRIBUTE_PRINTF(2,3);
148 void error (const char *fmt, ...) ATTRIBUTE_PRINTF(2,3);
150 void print (const std::string &s);
151 void help (const std::string &s);
152 void info (const std::string &s);
153 void output (const std::string &s);
154 void error (const std::string &s);
156 void print (const String& s);
157 void help (const String& s);
158 void info (const String& s);
159 void output (const String& s);
160 void error (const String& s);
162 bool code(const String& source, int lineFocus = 0, int line1 = 0,
163 int line2 = 0,
164 int charFocus0 = 0, int lineFocus1 = 0, int charFocus1 = 0);
165 void shortCode(BreakPointInfoPtr bp);
166 char ask(const char *fmt, ...) ATTRIBUTE_PRINTF(2,3);
168 std::string wrap(const std::string &s);
169 void helpTitle(const char *title);
170 void helpCmds(const char *cmd, const char *desc, ...);
171 void helpCmds(const std::vector<const char *> &cmds);
172 void helpBody(const std::string &s);
173 void helpSection(const std::string &s);
175 void tutorial(const char *text);
176 void setTutorial(int mode);
178 // Returns the source code string that the debugger is currently
179 // evaluating.
180 const std::string &getCode() const { return m_code;}
181 void swapHelp();
184 * Test if argument matches specified. "index" is 1-based.
186 const std::string &getCommand() const { return m_command;}
187 bool arg(int index, const char *s);
188 int argCount() { return m_args.size();}
189 std::string argValue(int index);
190 // The entire line after that argument, un-escaped.
191 std::string lineRest(int index);
192 std::vector<std::string> *args() { return &m_args;}
195 * Send the commmand to server's DebuggerProxy and expect same type of command
196 * back. The WithNestedExecution version supports commands that cause the
197 * server to run PHP on send when we want to be able to debug that PHP before
198 * completing the command.
200 template<typename T> std::shared_ptr<T> xend(DebuggerCommand *cmd) {
201 return std::static_pointer_cast<T>(xend(cmd, Nested));
203 template<typename T> std::shared_ptr<T>
204 xendWithNestedExecution(DebuggerCommand *cmd) {
205 return std::static_pointer_cast<T>(xend(cmd, NestedWithExecution));
208 void sendToServer(DebuggerCommand *cmd);
211 * Machine functions. True if we're switching to a machine that's not
212 * interrupting, therefore, we need to throw DebuggerConsoleExitException
213 * to pump more interrupts. False if we're switching to a machine that
214 * was already interrupting, OR, there was a failure to switch. We then
215 * need to call initializeMachine() immediately without waiting.
217 bool connect(const std::string &host, int port);
218 bool connectRPC(const std::string &host, int port);
219 bool reconnect();
220 bool disconnect();
221 bool initializeMachine();
222 bool isLocal();
225 * Sandbox functions.
227 void updateSandboxes(std::vector<DSandboxInfoPtr> &sandboxes) {
228 m_sandboxes = sandboxes;
230 DSandboxInfoPtr getSandbox(int index) const;
231 void setSandbox(DSandboxInfoPtr sandbox);
232 std::string getSandboxId();
235 * Thread functions.
237 void updateThreads(std::vector<DThreadInfoPtr> threads);
238 DThreadInfoPtr getThread(int index) const;
239 int64_t getCurrentThreadId() const { return m_threadId;}
242 * Current source location and breakpoints.
244 BreakPointInfoPtr getCurrentLocation() const { return m_breakpoint;}
245 std::vector<BreakPointInfoPtr> *getBreakPoints() { return &m_breakpoints;}
246 void setMatchedBreakPoints(std::vector<BreakPointInfoPtr> breakpoints);
247 void setCurrentLocation(int64_t threadId, BreakPointInfoPtr breakpoint);
248 std::vector<BreakPointInfoPtr> *getMatchedBreakPoints() { return &m_matched;}
250 // Retrieves a source location that is the current focus of the
251 // debugger. The current focus is initially determined by the
252 // breakpoint where the debugger is currently stopped and can
253 // thereafter be modified by list commands and by switching the
254 // the stack frame.
255 void getListLocation(std::string &file, int &line, int &lineFocus0,
256 int &charFocus0, int &lineFocus1, int &charFocus1);
258 void setListLocation(const std::string &file, int line, bool center);
259 void setSourceRoot(const std::string &sourceRoot);
262 * Watch expressions.
264 typedef std::pair<const char *, std::string> Watch;
265 typedef std::shared_ptr<Watch> WatchPtr;
266 typedef std::vector<WatchPtr> WatchPtrVec;
267 WatchPtrVec &getWatches() { return m_watches;}
268 void addWatch(const char *fmt, const std::string &php);
271 * Stacktraces.
273 Array getStackTrace() { return m_stacktrace; }
274 void setStackTrace(const Array& stacktrace, bool isAsync);
275 bool isStackTraceAsync() { return m_stacktraceAsync; }
276 void moveToFrame(int index, bool display = true);
277 void printFrame(int index, const Array& frame);
278 void setFrame(int frame) { m_frame = frame; }
279 int getFrame() const { return m_frame; }
282 * Auto-completion.
284 bool setCompletion(const char *text, int start, int end);
285 char *getCompletion(const char *text, int state);
286 void addCompletion(AutoComplete type);
287 void addCompletion(const char **list);
288 void addCompletion(const char *name);
289 void addCompletion(const std::vector<std::string> &items);
290 void setLiveLists(LiveListsPtr liveLists) { m_acLiveLists = liveLists; }
292 void init(const DebuggerClientOptions &options);
293 void clearCachedLocal() {
294 m_stacktrace.reset();
298 * Macro functions
300 void startMacro(std::string name);
301 void endMacro();
302 bool playMacro(std::string name);
303 const std::vector<std::shared_ptr<Macro>> &getMacros() const {
304 return m_macros;
306 bool deleteMacro(int index);
308 DECLARE_DBG_CLIENT_SETTING_ACCESSORS
310 std::string getLogFile () const { return m_logFile; }
311 void setLogFile (std::string inLogFile) { m_logFile = inLogFile; }
312 FILE* getLogFileHandler () const { return m_logFileHandler; }
313 void setLogFileHandler (FILE* inLogFileHandler) {
314 m_logFileHandler = inLogFileHandler;
316 std::string getCurrentUser() const { return m_options.user; }
318 // Usage logging
319 void usageLogCommand(const std::string &cmd, const std::string &data);
320 void usageLogEvent(const std::string &eventName,
321 const std::string &data = "");
323 std::string getZendExecutable() const { return m_zendExe; }
325 // Internal testing helpers. Only used by internal tests!!!
326 bool internalTestingIsClientStopped() const { return m_stopped; }
328 bool unknownCmdReceived() const { return m_unknownCmd; }
329 private:
330 enum InputState {
331 TakingCommand,
332 TakingCode,
333 TakingInterrupt
336 std::string m_configFileName;
337 int m_tutorial;
338 std::set<std::string> m_tutorialVisited;
339 bool m_scriptMode; // Is this client being scripted by a test?
340 bool m_neverSaveConfig; // So that tests can avoid clobbering the config file
341 bool m_neverSaveConfigOverride;
343 DECLARE_DBG_CLIENT_SETTING
345 std::string m_logFile;
346 FILE* m_logFileHandler;
348 DebuggerClientOptions m_options;
349 AsyncFunc<DebuggerClient> m_mainThread;
350 bool m_stopped;
352 InputState m_inputState;
353 int m_sigNum; // Set when ctrl-c is pressed, used by signal polling
354 int m_sigCount; // Number of times ctrl-c pressed since last interrupt
356 // auto-completion states
357 int m_acLen;
358 int m_acIndex;
359 int m_acPos;
360 std::vector<const char **> m_acLists;
361 std::vector<const char *> m_acStrings;
362 std::vector<std::string> m_acItems;
363 bool m_acLiveListsDirty;
364 LiveListsPtr m_acLiveLists;
365 bool m_acProtoTypePrompted;
367 std::string m_line;
368 // The current command to process.
369 std::string m_command;
370 std::string m_commandCanonical;
371 std::string m_prevCmd;
372 std::vector<std::string> m_args;
373 // m_args[i]'s last character is m_line[m_argIdx[i]]
374 std::vector<int> m_argIdx;
375 std::string m_code;
377 std::vector<std::shared_ptr<Macro>> m_macros;
378 std::shared_ptr<Macro> m_macroRecording;
379 std::shared_ptr<Macro> m_macroPlaying;
381 std::vector<std::shared_ptr<DMachineInfo>>
382 m_machines; // All connected machines. 0th is local.
383 std::shared_ptr<DMachineInfo> m_machine; // Current machine
384 std::string m_rpcHost; // Current RPC host
386 std::vector<DSandboxInfoPtr> m_sandboxes;
387 std::vector<DThreadInfoPtr> m_threads;
388 int64_t m_threadId;
389 std::map<int64_t, int> m_threadIdMap; // maps threadId to index
391 std::vector<BreakPointInfoPtr> m_breakpoints;
392 BreakPointInfoPtr m_breakpoint;
393 std::vector<BreakPointInfoPtr> m_matched;
395 // list command's current location, which may be different from m_breakpoint
397 // The file currently being listed. Set implicitly by breakpoints and
398 // explicitly by list commands issued to the client by a user.
399 std::string m_listFile;
401 // The first line to list
402 int m_listLine;
403 int m_listLineFocus;
405 WatchPtrVec m_watches;
407 Array m_stacktrace;
408 bool m_stacktraceAsync;
409 int m_frame;
411 std::string m_sourceRoot;
413 void start(const DebuggerClientOptions &options);
414 void run();
416 // helpers
417 std::string getPrompt();
418 void addToken(std::string &token, int idx);
419 void parseCommand(const char *line);
420 void shiftCommand();
421 bool parse(const char *line);
422 bool match(const char *cmd);
423 int checkEvalEnd();
424 void processTakeCode();
425 bool processEval();
426 DebuggerCommand *createCommand();
428 void updateLiveLists();
429 void promptFunctionPrototype();
430 char *getCompletion(const std::vector<std::string> &items,
431 const char *text);
432 char *getCompletion(const std::vector<const char *> &items,
433 const char *text);
435 // config and macros
436 void defineColors(const Hdf &config);
437 void loadConfig();
438 void saveConfig();
439 void record(const char *line);
441 // connections
442 void closeAllConnections();
443 void switchMachine(std::shared_ptr<DMachineInfo> machine);
444 SmartPtr<Socket> connectLocal();
445 bool connectRemote(const std::string &host, int port);
446 bool tryConnect(const std::string &host, int port, bool clearmachines);
448 enum EventLoopKind {
449 TopLevel, // The top-level event loop, called from run().
450 Nested, // A nested loop where we expect a cmd back with no PHP executed.
451 NestedWithExecution // A nested loop where more PHP may execute.
454 DebuggerCommandPtr xend(DebuggerCommand *cmd, EventLoopKind loopKind);
455 DebuggerCommandPtr eventLoop(EventLoopKind loopKind, int expectedCmd,
456 const char *caller);
458 // Zend executable for CmdZend, overridable via config.
459 std::string m_zendExe = "php";
461 bool m_unknownCmd;
464 ///////////////////////////////////////////////////////////////////////////////
467 #endif // incl_HPHP_EVAL_DEBUGGER_CLIENT_H_