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