]> git.saurik.com Git - apple/xnu.git/blame - tools/lldbmacros/core/standard.py
xnu-7195.101.1.tar.gz
[apple/xnu.git] / tools / lldbmacros / core / standard.py
CommitLineData
39236c6e
A
1import getopt
2import os
3import sys
4import re
5
6class 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
16class 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
31class 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
41class 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
61class 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
93class NOVT(object):
94 def __getattribute__(self, *args):
95 return ""
96
39236c6e
A
97class 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