]>
Commit | Line | Data |
---|---|---|
39236c6e A |
1 | import getopt |
2 | import os | |
3 | import sys | |
4 | import re | |
5 | ||
6 | class ArgumentError(Exception): | |
cb323159 | 7 | """ Exception class for raising errors in command arguments. The lldb_command framework will catch this |
39236c6e A |
8 | class of exceptions and print suitable error message to user. |
9 | """ | |
10 | def __init__(self, msg): | |
11 | self.error_message = msg | |
12 | def __str__(self): | |
13 | return str(self.error_message) | |
14 | ||
15 | ||
16 | class RedirectStdStreams(object): | |
17 | def __init__(self, stdout=None, stderr=None): | |
18 | self._stdout = stdout or sys.stdout | |
19 | self._stderr = stderr or sys.stderr | |
20 | ||
21 | def __enter__(self): | |
22 | self.old_stdout, self.old_stderr = sys.stdout, sys.stderr | |
23 | self.old_stdout.flush(); self.old_stderr.flush() | |
24 | sys.stdout, sys.stderr = self._stdout, self._stderr | |
25 | ||
26 | def __exit__(self, exc_type, exc_value, traceback): | |
27 | self._stdout.flush(); self._stderr.flush() | |
28 | sys.stdout = self.old_stdout | |
29 | sys.stderr = self.old_stderr | |
30 | ||
cb323159 A |
31 | class IndentScope(object): |
32 | def __init__(self, O): | |
33 | self._O = O | |
34 | ||
35 | def __enter__(self): | |
36 | self._O._indent += ' ' | |
37 | ||
38 | def __exit__(self, exc_type, exc_value, traceback): | |
39 | self._O._indent = self._O._indent[:-4] | |
40 | ||
41 | class HeaderScope(object): | |
42 | def __init__(self, O, hdr, indent = False): | |
43 | self._O = O | |
44 | self._header = hdr | |
45 | self._indent = indent | |
46 | ||
47 | def __enter__(self): | |
48 | self._oldHeader = self._O._header | |
49 | self._oldLastHeader = self._O._lastHeader | |
50 | self._O._header = self._header | |
51 | self._O._lastHeader = None | |
52 | if self._indent: | |
53 | self._O._indent += ' ' | |
54 | ||
55 | def __exit__(self, exc_type, exc_value, traceback): | |
56 | self._O._header = self._oldHeader | |
57 | self._O._lastHeader = self._oldLastHeader | |
58 | if self._indent: | |
59 | self._O._indent = self._O._indent[:-4] | |
60 | ||
61 | class VT(object): | |
62 | Black = "\033[38;5;0m" | |
63 | DarkRed = "\033[38;5;1m" | |
64 | DarkGreen = "\033[38;5;2m" | |
65 | Brown = "\033[38;5;3m" | |
66 | DarkBlue = "\033[38;5;4m" | |
67 | DarkMagenta = "\033[38;5;5m" | |
68 | DarkCyan = "\033[38;5;6m" | |
69 | Grey = "\033[38;5;7m" | |
70 | ||
71 | DarkGrey = "\033[38;5;8m" | |
72 | Red = "\033[38;5;9m" | |
73 | Green = "\033[38;5;10m" | |
74 | Yellow = "\033[38;5;11m" | |
75 | Blue = "\033[38;5;12m" | |
76 | Magenta = "\033[38;5;13m" | |
77 | Cyan = "\033[38;5;14m" | |
78 | White = "\033[38;5;15m" | |
79 | ||
80 | Default = "\033[39m" | |
81 | ||
82 | Bold = "\033[1m" | |
83 | EndBold = "\033[22m" | |
84 | ||
85 | Oblique = "\033[3m" | |
86 | EndOblique = "\033[23m" | |
87 | ||
88 | Underline = "\033[4m" | |
89 | EndUnderline = "\033[24m" | |
90 | ||
91 | Reset = "\033[0m" | |
92 | ||
93 | class NOVT(object): | |
94 | def __getattribute__(self, *args): | |
95 | return "" | |
96 | ||
39236c6e A |
97 | class CommandOutput(object): |
98 | """ | |
cb323159 | 99 | An output handler for all commands. Use Output.print to direct all output of macro via the handler. |
39236c6e A |
100 | These arguments are passed after a "--". eg |
101 | (lldb) zprint -- -o /tmp/zprint.out.txt | |
cb323159 A |
102 | |
103 | Currently this provide capabilities | |
104 | -h show help | |
39236c6e | 105 | -o path/to/filename |
cb323159 | 106 | The output of this command execution will be saved to file. Parser information or errors will |
39236c6e A |
107 | not be sent to file though. eg /tmp/output.txt |
108 | -s filter_string | |
cb323159 A |
109 | the "filter_string" param is parsed to python regex expression and each line of output |
110 | will be printed/saved only if it matches the expression. | |
39236c6e | 111 | The command header will not be filtered in any case. |
cb323159 A |
112 | -p <plugin_name> |
113 | Send the output of the command to plugin. | |
114 | -v ... | |
115 | Up verbosity | |
116 | -c <always|never|auto> | |
117 | configure color | |
39236c6e | 118 | """ |
cb323159 | 119 | def __init__(self, cmd_name, CommandResult=None, fhandle=None): |
39236c6e A |
120 | """ Create a new instance to handle command output. |
121 | params: | |
cb323159 | 122 | CommandResult : SBCommandReturnObject result param from lldb's command invocation. |
39236c6e A |
123 | """ |
124 | self.fname=None | |
cb323159 | 125 | self.fhandle=fhandle |
39236c6e A |
126 | self.FILTER=False |
127 | self.pluginRequired = False | |
128 | self.pluginName = None | |
813fb2f6 | 129 | self.cmd_name = cmd_name |
39236c6e | 130 | self.resultObj = CommandResult |
39236c6e A |
131 | self.verbose_level = 0 |
132 | self.target_cmd_args = [] | |
133 | self.target_cmd_options = {} | |
cb323159 A |
134 | self.color = None |
135 | self.isatty = os.isatty(sys.__stdout__.fileno()) | |
136 | self._indent = '' | |
137 | self._buffer = '' | |
39236c6e | 138 | |
cb323159 A |
139 | self._header = None |
140 | self._lastHeader = None | |
141 | self._line = 0 | |
813fb2f6 | 142 | |
cb323159 | 143 | def _write(self, s): |
813fb2f6 | 144 | if self.fhandle != None: |
cb323159 | 145 | self.fhandle.write(self._indent + s + "\n") |
39236c6e | 146 | else: |
cb323159 A |
147 | self.resultObj.AppendMessage(self._indent + s) |
148 | self._line += 1 | |
149 | ||
150 | def _doColor(self): | |
151 | if self.color is True: | |
152 | return True; | |
153 | return self.color is None and self.isatty | |
154 | ||
155 | def _needsHeader(self): | |
156 | if self._header is None: | |
157 | return False | |
158 | if self._lastHeader is None: | |
159 | return True | |
160 | if not self.isatty: | |
161 | return False | |
162 | return self._line - self._lastHeader > 40 | |
163 | ||
164 | def indent(self): | |
165 | return IndentScope(self) | |
166 | ||
167 | def table(self, header, indent = False): | |
168 | return HeaderScope(self, header, indent) | |
169 | ||
170 | def format(self, s, *args, **kwargs): | |
171 | if self._doColor(): | |
172 | kwargs['VT'] = VT | |
173 | else: | |
174 | kwargs['VT'] = NOVT() | |
175 | ||
176 | return s.format(*args, **kwargs) | |
177 | ||
178 | def error(self, s, *args, **kwargs): | |
179 | print self.format("{cmd.cmd_name}: {VT.Red}"+s+"{VT.Default}", cmd=self, *args, **kwargs) | |
180 | ||
181 | def write(self, s): | |
182 | """ Handler for all commands output. By default just print to stdout """ | |
183 | ||
184 | s = self._buffer + s | |
185 | ||
186 | while s.find('\n') != -1: | |
187 | l, s = s.split("\n", 1) | |
188 | if self.FILTER: | |
189 | if not self.reg.search(l): | |
190 | continue | |
191 | if self._doColor(): | |
192 | l = self.reg.sub(VT.Underline + r"\g<0>" + VT.EndUnderline, l); | |
193 | ||
194 | if len(l) and self._needsHeader(): | |
195 | for hdr in self._header.split("\n"): | |
196 | self._write(self.format("{VT.Bold}{:s}{VT.EndBold}", hdr)) | |
197 | self._lastHeader = self._line | |
198 | ||
199 | self._write(l) | |
200 | ||
201 | self._buffer = s | |
39236c6e A |
202 | |
203 | def flush(self): | |
204 | if self.fhandle != None: | |
205 | self.fhandle.flush() | |
cb323159 | 206 | |
39236c6e A |
207 | def __del__(self): |
208 | """ closes any open files. report on any errors """ | |
cb323159 | 209 | if self.fhandle != None and self.fname != None: |
39236c6e | 210 | self.fhandle.close() |
cb323159 | 211 | |
813fb2f6 | 212 | def setOptions(self, cmdargs, cmdoptions =''): |
cb323159 A |
213 | """ parse the arguments passed to the command |
214 | param : | |
39236c6e | 215 | cmdargs => [] of <str> (typically args.split()) |
cb323159 | 216 | cmdoptions : str - string of command level options. |
39236c6e A |
217 | These should be CAPITAL LETTER options only. |
218 | """ | |
219 | opts=() | |
220 | args = cmdargs | |
221 | cmdoptions = cmdoptions.upper() | |
222 | try: | |
cb323159 | 223 | opts,args = getopt.gnu_getopt(args,'hvo:s:p:c:'+ cmdoptions,[]) |
39236c6e A |
224 | self.target_cmd_args = args |
225 | except getopt.GetoptError,err: | |
226 | raise ArgumentError(str(err)) | |
227 | #continue with processing | |
228 | for o,a in opts : | |
229 | if o == "-h": | |
230 | # This is misuse of exception but 'self' has no info on doc string. | |
231 | # The caller may handle exception and display appropriate info | |
232 | raise ArgumentError("HELP") | |
233 | if o == "-o" and len(a) > 0: | |
234 | self.fname=os.path.normpath(os.path.expanduser(a.strip())) | |
235 | self.fhandle=open(self.fname,"w") | |
236 | print "saving results in file ",str(a) | |
813fb2f6 | 237 | self.fhandle.write("(lldb)%s %s \n" % (self.cmd_name, " ".join(cmdargs))) |
cb323159 | 238 | self.isatty = os.isatty(self.fhandle.fileno()) |
39236c6e A |
239 | elif o == "-s" and len(a) > 0: |
240 | self.reg = re.compile(a.strip(),re.MULTILINE|re.DOTALL) | |
241 | self.FILTER=True | |
242 | print "showing results for regex:",a.strip() | |
243 | elif o == "-p" and len(a) > 0: | |
244 | self.pluginRequired = True | |
245 | self.pluginName = a.strip() | |
246 | #print "passing output to " + a.strip() | |
cb323159 | 247 | elif o == "-v": |
39236c6e | 248 | self.verbose_level += 1 |
cb323159 A |
249 | elif o == "-c": |
250 | if a in ["always", '1']: | |
251 | self.color = True | |
252 | elif a in ["never", '0']: | |
253 | self.color = False | |
254 | else: | |
255 | self.color = None | |
39236c6e A |
256 | else: |
257 | o = o.strip() | |
258 | self.target_cmd_options[o] = a | |
259 | ||
39236c6e | 260 |