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