xref: /xnu-10063.141.1/tools/lldbmacros/core/standard.py (revision d8b80295118ef25ac3a784134bcf95cd8e88109f)
1*d8b80295SApple OSS Distributionsimport getopt
2*d8b80295SApple OSS Distributionsimport os
3*d8b80295SApple OSS Distributionsimport string
4*d8b80295SApple OSS Distributionsimport sys
5*d8b80295SApple OSS Distributionsimport re
6*d8b80295SApple OSS Distributions
7*d8b80295SApple OSS Distributionsfrom lldb import SBValue
8*d8b80295SApple OSS Distributionsfrom core import value as cvalue
9*d8b80295SApple OSS Distributionsfrom .configuration import config
10*d8b80295SApple OSS Distributions
11*d8b80295SApple OSS Distributionsclass ArgumentError(Exception):
12*d8b80295SApple OSS Distributions    """ Exception class for raising errors in command arguments. The lldb_command framework will catch this
13*d8b80295SApple OSS Distributions        class of exceptions and print suitable error message to user.
14*d8b80295SApple OSS Distributions    """
15*d8b80295SApple OSS Distributions    def __init__(self, msg):
16*d8b80295SApple OSS Distributions        self.error_message = msg
17*d8b80295SApple OSS Distributions    def __str__(self):
18*d8b80295SApple OSS Distributions        return str(self.error_message)
19*d8b80295SApple OSS Distributions
20*d8b80295SApple OSS Distributions
21*d8b80295SApple OSS Distributionsclass RedirectStdStreams(object):
22*d8b80295SApple OSS Distributions    def __init__(self, stdout=None, stderr=None):
23*d8b80295SApple OSS Distributions        self._stdout = stdout or sys.stdout
24*d8b80295SApple OSS Distributions        self._stderr = stderr or sys.stderr
25*d8b80295SApple OSS Distributions
26*d8b80295SApple OSS Distributions    def __enter__(self):
27*d8b80295SApple OSS Distributions        self.old_stdout, self.old_stderr = sys.stdout, sys.stderr
28*d8b80295SApple OSS Distributions        self.old_stdout.flush(); self.old_stderr.flush()
29*d8b80295SApple OSS Distributions        sys.stdout, sys.stderr = self._stdout, self._stderr
30*d8b80295SApple OSS Distributions
31*d8b80295SApple OSS Distributions    def __exit__(self, exc_type, exc_value, traceback):
32*d8b80295SApple OSS Distributions        self._stdout.flush(); self._stderr.flush()
33*d8b80295SApple OSS Distributions        sys.stdout = self.old_stdout
34*d8b80295SApple OSS Distributions        sys.stderr = self.old_stderr
35*d8b80295SApple OSS Distributions
36*d8b80295SApple OSS Distributionsclass IndentScope(object):
37*d8b80295SApple OSS Distributions    def __init__(self, O):
38*d8b80295SApple OSS Distributions        self._O = O
39*d8b80295SApple OSS Distributions
40*d8b80295SApple OSS Distributions    def __enter__(self):
41*d8b80295SApple OSS Distributions        self._O._indent += '    '
42*d8b80295SApple OSS Distributions
43*d8b80295SApple OSS Distributions    def __exit__(self, exc_type, exc_value, traceback):
44*d8b80295SApple OSS Distributions        self._O._indent = self._O._indent[:-4]
45*d8b80295SApple OSS Distributions
46*d8b80295SApple OSS Distributionsclass HeaderScope(object):
47*d8b80295SApple OSS Distributions    def __init__(self, O, hdr, indent = False):
48*d8b80295SApple OSS Distributions        self._O = O
49*d8b80295SApple OSS Distributions        self._header = hdr
50*d8b80295SApple OSS Distributions        self._indent = indent
51*d8b80295SApple OSS Distributions
52*d8b80295SApple OSS Distributions    def __enter__(self):
53*d8b80295SApple OSS Distributions        self._oldHeader = self._O._header
54*d8b80295SApple OSS Distributions        self._oldLastHeader = self._O._lastHeader
55*d8b80295SApple OSS Distributions        self._O._header = self._header
56*d8b80295SApple OSS Distributions        self._O._lastHeader = None
57*d8b80295SApple OSS Distributions        if self._indent:
58*d8b80295SApple OSS Distributions            self._O._indent += '    '
59*d8b80295SApple OSS Distributions
60*d8b80295SApple OSS Distributions    def __exit__(self, exc_type, exc_value, traceback):
61*d8b80295SApple OSS Distributions        self._O._header = self._oldHeader
62*d8b80295SApple OSS Distributions        self._O._lastHeader = self._oldLastHeader
63*d8b80295SApple OSS Distributions        if self._indent:
64*d8b80295SApple OSS Distributions            self._O._indent = self._O._indent[:-4]
65*d8b80295SApple OSS Distributions
66*d8b80295SApple OSS Distributionsclass VT(object):
67*d8b80295SApple OSS Distributions    Black        = "\033[38;5;0m"
68*d8b80295SApple OSS Distributions    DarkRed      = "\033[38;5;1m"
69*d8b80295SApple OSS Distributions    DarkGreen    = "\033[38;5;2m"
70*d8b80295SApple OSS Distributions    Brown        = "\033[38;5;3m"
71*d8b80295SApple OSS Distributions    DarkBlue     = "\033[38;5;4m"
72*d8b80295SApple OSS Distributions    DarkMagenta  = "\033[38;5;5m"
73*d8b80295SApple OSS Distributions    DarkCyan     = "\033[38;5;6m"
74*d8b80295SApple OSS Distributions    Grey         = "\033[38;5;7m"
75*d8b80295SApple OSS Distributions
76*d8b80295SApple OSS Distributions    DarkGrey     = "\033[38;5;8m"
77*d8b80295SApple OSS Distributions    Red          = "\033[38;5;9m"
78*d8b80295SApple OSS Distributions    Green        = "\033[38;5;10m"
79*d8b80295SApple OSS Distributions    Yellow       = "\033[38;5;11m"
80*d8b80295SApple OSS Distributions    Blue         = "\033[38;5;12m"
81*d8b80295SApple OSS Distributions    Magenta      = "\033[38;5;13m"
82*d8b80295SApple OSS Distributions    Cyan         = "\033[38;5;14m"
83*d8b80295SApple OSS Distributions    White        = "\033[38;5;15m"
84*d8b80295SApple OSS Distributions
85*d8b80295SApple OSS Distributions    Default      = "\033[39m"
86*d8b80295SApple OSS Distributions
87*d8b80295SApple OSS Distributions    Bold         = "\033[1m"
88*d8b80295SApple OSS Distributions    EndBold      = "\033[22m"
89*d8b80295SApple OSS Distributions
90*d8b80295SApple OSS Distributions    Oblique      = "\033[3m"
91*d8b80295SApple OSS Distributions    EndOblique   = "\033[23m"
92*d8b80295SApple OSS Distributions
93*d8b80295SApple OSS Distributions    Underline    = "\033[4m"
94*d8b80295SApple OSS Distributions    EndUnderline = "\033[24m"
95*d8b80295SApple OSS Distributions
96*d8b80295SApple OSS Distributions    Reset        = "\033[0m"
97*d8b80295SApple OSS Distributions
98*d8b80295SApple OSS Distributionsclass NOVT(object):
99*d8b80295SApple OSS Distributions    def __getattribute__(self, *args):
100*d8b80295SApple OSS Distributions        return ""
101*d8b80295SApple OSS Distributions
102*d8b80295SApple OSS Distributionsclass SBValueFormatter(string.Formatter):
103*d8b80295SApple OSS Distributions    """
104*d8b80295SApple OSS Distributions    Formatter that treats SBValues specially
105*d8b80295SApple OSS Distributions
106*d8b80295SApple OSS Distributions    It adds the following magical syntax for fields:
107*d8b80295SApple OSS Distributions
108*d8b80295SApple OSS Distributions    - {$value->path.to[10].field} will follow a given expression path,
109*d8b80295SApple OSS Distributions      and compute the resulting SBValue. This works with cvalues too.
110*d8b80295SApple OSS Distributions
111*d8b80295SApple OSS Distributions    - {&value->path.to[10].field} will return the load address
112*d8b80295SApple OSS Distributions      of the specified value path. This works with cvalue too.
113*d8b80295SApple OSS Distributions
114*d8b80295SApple OSS Distributions
115*d8b80295SApple OSS Distributions    The format spec can now take a multi-char conversion,
116*d8b80295SApple OSS Distributions    {field|<multi-char-conversion>!conv:spec},
117*d8b80295SApple OSS Distributions    where <multi-char-conversion> is one of:
118*d8b80295SApple OSS Distributions
119*d8b80295SApple OSS Distributions    - `c_str` which will attempt to read the value as a C string using
120*d8b80295SApple OSS Distributions      xGetValueAsCString()
121*d8b80295SApple OSS Distributions
122*d8b80295SApple OSS Distributions    - `human_size` will convert sizes into a human readable representation.
123*d8b80295SApple OSS Distributions
124*d8b80295SApple OSS Distributions    - a conversion registered with the SBValueFormatter.converter
125*d8b80295SApple OSS Distributions      decorator,
126*d8b80295SApple OSS Distributions
127*d8b80295SApple OSS Distributions    - a `key.method` specification where the key is one of the positional
128*d8b80295SApple OSS Distributions      or named arguments to the format.
129*d8b80295SApple OSS Distributions
130*d8b80295SApple OSS Distributions
131*d8b80295SApple OSS Distributions    When the value of a given field is an SBValue (because &/$ was used,
132*d8b80295SApple OSS Distributions    or the field was already an SBValue -- but not a cvalue), in the absence
133*d8b80295SApple OSS Distributions    of a explicit conversion, the SBValue will be converted to a scalar
134*d8b80295SApple OSS Distributions    using xGetValueAsScalar()
135*d8b80295SApple OSS Distributions    """
136*d8b80295SApple OSS Distributions
137*d8b80295SApple OSS Distributions    _KEY_RE = re.compile(r"[.-\[]")
138*d8b80295SApple OSS Distributions
139*d8b80295SApple OSS Distributions    _CONVERTERS = {}
140*d8b80295SApple OSS Distributions
141*d8b80295SApple OSS Distributions    @classmethod
142*d8b80295SApple OSS Distributions    def converter(cls, name, raw=False):
143*d8b80295SApple OSS Distributions        def register(fn):
144*d8b80295SApple OSS Distributions            cls._CONVERTERS[name] = (fn, raw)
145*d8b80295SApple OSS Distributions
146*d8b80295SApple OSS Distributions        return register
147*d8b80295SApple OSS Distributions
148*d8b80295SApple OSS Distributions    def format(self, format_string, *args, **kwargs):
149*d8b80295SApple OSS Distributions        return self.vformat(self, format_string, args, kwargs)
150*d8b80295SApple OSS Distributions
151*d8b80295SApple OSS Distributions    def _raise_switch_manual_to_automatic(self):
152*d8b80295SApple OSS Distributions        raise ValueError('cannot switch from manual field '
153*d8b80295SApple OSS Distributions                         'specification to automatic field '
154*d8b80295SApple OSS Distributions                         'numbering')
155*d8b80295SApple OSS Distributions
156*d8b80295SApple OSS Distributions    def vformat(self, format_string, args, kwargs):
157*d8b80295SApple OSS Distributions        result    = []
158*d8b80295SApple OSS Distributions        auto_idx  = 0
159*d8b80295SApple OSS Distributions
160*d8b80295SApple OSS Distributions        #
161*d8b80295SApple OSS Distributions        # Python 2.7 doesn't support empty field names in Formatter,
162*d8b80295SApple OSS Distributions        # so we need to implement vformat. Because we avoid certain
163*d8b80295SApple OSS Distributions        # features such as "unused fields accounting" we actually
164*d8b80295SApple OSS Distributions        # are faster than the core library Formatter this way which
165*d8b80295SApple OSS Distributions        # adds up quickly for our macros, so it's worth keeping
166*d8b80295SApple OSS Distributions        # this implementation even on Python 3.
167*d8b80295SApple OSS Distributions        #
168*d8b80295SApple OSS Distributions        for text, field_name, format_spec, conv in \
169*d8b80295SApple OSS Distributions                self.parse(format_string):
170*d8b80295SApple OSS Distributions
171*d8b80295SApple OSS Distributions            if text:
172*d8b80295SApple OSS Distributions                result.append(text)
173*d8b80295SApple OSS Distributions
174*d8b80295SApple OSS Distributions            if field_name is None:
175*d8b80295SApple OSS Distributions                continue
176*d8b80295SApple OSS Distributions
177*d8b80295SApple OSS Distributions            field_name, _, transform = field_name.partition('|')
178*d8b80295SApple OSS Distributions
179*d8b80295SApple OSS Distributions            if field_name == '':
180*d8b80295SApple OSS Distributions                #
181*d8b80295SApple OSS Distributions                # Handle auto-numbering like python 3
182*d8b80295SApple OSS Distributions                #
183*d8b80295SApple OSS Distributions                if auto_idx is None:
184*d8b80295SApple OSS Distributions                    self._raise_switch_manual_to_automatic()
185*d8b80295SApple OSS Distributions                field_name = str(auto_idx)
186*d8b80295SApple OSS Distributions                auto_idx  += 1
187*d8b80295SApple OSS Distributions
188*d8b80295SApple OSS Distributions            elif field_name.isdigit():
189*d8b80295SApple OSS Distributions                #
190*d8b80295SApple OSS Distributions                # numeric key
191*d8b80295SApple OSS Distributions                #
192*d8b80295SApple OSS Distributions                if auto_idx:
193*d8b80295SApple OSS Distributions                    self._raise_switch_manual_to_automatic()
194*d8b80295SApple OSS Distributions                auto_idx = None
195*d8b80295SApple OSS Distributions
196*d8b80295SApple OSS Distributions            try:
197*d8b80295SApple OSS Distributions                if field_name[0] in '&$':
198*d8b80295SApple OSS Distributions                    #
199*d8b80295SApple OSS Distributions                    # Our magic sigils
200*d8b80295SApple OSS Distributions                    #
201*d8b80295SApple OSS Distributions                    obj, auto_idx = self.get_value_field(
202*d8b80295SApple OSS Distributions                        field_name, args, kwargs, auto_idx)
203*d8b80295SApple OSS Distributions
204*d8b80295SApple OSS Distributions                else:
205*d8b80295SApple OSS Distributions                    #
206*d8b80295SApple OSS Distributions                    # Fallback typical case
207*d8b80295SApple OSS Distributions                    #
208*d8b80295SApple OSS Distributions                    obj, _ = self.get_field(field_name, args, kwargs)
209*d8b80295SApple OSS Distributions            except:
210*d8b80295SApple OSS Distributions                if config['debug']: raise
211*d8b80295SApple OSS Distributions                result.extend((
212*d8b80295SApple OSS Distributions                    VT.Red,
213*d8b80295SApple OSS Distributions                    "<FAIL {}>".format(field_name),
214*d8b80295SApple OSS Distributions                    VT.Reset
215*d8b80295SApple OSS Distributions                ))
216*d8b80295SApple OSS Distributions                continue
217*d8b80295SApple OSS Distributions
218*d8b80295SApple OSS Distributions            # do any conv on the resulting object
219*d8b80295SApple OSS Distributions            try:
220*d8b80295SApple OSS Distributions                obj = self.convert_field(obj, conv, transform, args, kwargs)
221*d8b80295SApple OSS Distributions            except:
222*d8b80295SApple OSS Distributions                if config['debug']: raise
223*d8b80295SApple OSS Distributions                result.extend((
224*d8b80295SApple OSS Distributions                    VT.Red,
225*d8b80295SApple OSS Distributions                    "<CONV {}>".format(field_name),
226*d8b80295SApple OSS Distributions                    VT.Reset
227*d8b80295SApple OSS Distributions                ))
228*d8b80295SApple OSS Distributions                continue
229*d8b80295SApple OSS Distributions
230*d8b80295SApple OSS Distributions            result.append(self.format_field(obj, format_spec))
231*d8b80295SApple OSS Distributions
232*d8b80295SApple OSS Distributions        return ''.join(result)
233*d8b80295SApple OSS Distributions
234*d8b80295SApple OSS Distributions    def get_value_field(self, name, args, kwargs, auto_idx):
235*d8b80295SApple OSS Distributions        match = self._KEY_RE.search(name)
236*d8b80295SApple OSS Distributions        index = match.start() if match else len(name)
237*d8b80295SApple OSS Distributions        key   = name[1:index]
238*d8b80295SApple OSS Distributions        path  = name[index:]
239*d8b80295SApple OSS Distributions
240*d8b80295SApple OSS Distributions        if key == '':
241*d8b80295SApple OSS Distributions            raise ValueError("Key part of '{}' can't be empty".format(name))
242*d8b80295SApple OSS Distributions
243*d8b80295SApple OSS Distributions        if key.isdigit():
244*d8b80295SApple OSS Distributions            key = int(key)
245*d8b80295SApple OSS Distributions            if auto_idx:
246*d8b80295SApple OSS Distributions                self._raise_switch_manual_to_automatic()
247*d8b80295SApple OSS Distributions            auto_idx = None
248*d8b80295SApple OSS Distributions
249*d8b80295SApple OSS Distributions        obj = self.get_value(key, args, kwargs)
250*d8b80295SApple OSS Distributions        if isinstance(obj, cvalue):
251*d8b80295SApple OSS Distributions            obj = obj.GetSBValue()
252*d8b80295SApple OSS Distributions
253*d8b80295SApple OSS Distributions        if name[0] == '&':
254*d8b80295SApple OSS Distributions            if len(path):
255*d8b80295SApple OSS Distributions                return obj.xGetLoadAddressByPath(path), auto_idx
256*d8b80295SApple OSS Distributions            return obj.GetLoadAddress(), auto_idx
257*d8b80295SApple OSS Distributions
258*d8b80295SApple OSS Distributions        if len(path):
259*d8b80295SApple OSS Distributions            obj = obj.GetValueForExpressionPath(path)
260*d8b80295SApple OSS Distributions        return obj, auto_idx
261*d8b80295SApple OSS Distributions
262*d8b80295SApple OSS Distributions    def convert_field(self, obj, conv, transform='', args=None, kwargs=None):
263*d8b80295SApple OSS Distributions        is_sbval = isinstance(obj, SBValue)
264*d8b80295SApple OSS Distributions
265*d8b80295SApple OSS Distributions        if transform != '':
266*d8b80295SApple OSS Distributions            fn, raw = self._CONVERTERS.get(transform, (None, False))
267*d8b80295SApple OSS Distributions            if not raw and is_sbval:
268*d8b80295SApple OSS Distributions                obj = obj.xGetValueAsScalar()
269*d8b80295SApple OSS Distributions
270*d8b80295SApple OSS Distributions            if fn:
271*d8b80295SApple OSS Distributions                obj = fn(obj)
272*d8b80295SApple OSS Distributions            else:
273*d8b80295SApple OSS Distributions                objname, _, method = transform.partition('.')
274*d8b80295SApple OSS Distributions                field, _ = self.get_field(objname, args, kwargs)
275*d8b80295SApple OSS Distributions                obj = getattr(field, method)(obj)
276*d8b80295SApple OSS Distributions
277*d8b80295SApple OSS Distributions            is_sbval = False
278*d8b80295SApple OSS Distributions
279*d8b80295SApple OSS Distributions        if conv is None:
280*d8b80295SApple OSS Distributions            return obj.xGetValueAsScalar() if is_sbval else obj
281*d8b80295SApple OSS Distributions
282*d8b80295SApple OSS Distributions        return super(SBValueFormatter, self).convert_field(obj, conv)
283*d8b80295SApple OSS Distributions
284*d8b80295SApple OSS Distributions@SBValueFormatter.converter("c_str", raw=True)
285*d8b80295SApple OSS Distributionsdef __sbval_to_cstr(v):
286*d8b80295SApple OSS Distributions    return v.xGetValueAsCString() if isinstance(v, SBValue) else str(v)
287*d8b80295SApple OSS Distributions
288*d8b80295SApple OSS Distributions@SBValueFormatter.converter("human_size")
289*d8b80295SApple OSS Distributionsdef __human_size(v):
290*d8b80295SApple OSS Distributions    n = v.xGetValueAsCString() if isinstance(v, SBValue) else int(v)
291*d8b80295SApple OSS Distributions    order = ((n//10) | 1).bit_length() // 10
292*d8b80295SApple OSS Distributions    return "{:.1f}{}".format(n / (1024 ** order), "BKMGTPE"[order])
293*d8b80295SApple OSS Distributions
294*d8b80295SApple OSS Distributions
295*d8b80295SApple OSS Distributions_xnu_core_default_formatter = SBValueFormatter()
296*d8b80295SApple OSS Distributions
297*d8b80295SApple OSS Distributionsdef xnu_format(fmt, *args, **kwargs):
298*d8b80295SApple OSS Distributions    """ Conveniency function to call SBValueFormatter().format """
299*d8b80295SApple OSS Distributions    return _xnu_core_default_formatter.vformat(fmt, args, kwargs)
300*d8b80295SApple OSS Distributions
301*d8b80295SApple OSS Distributionsdef xnu_vformat(fmt, args, kwargs):
302*d8b80295SApple OSS Distributions    """ Conveniency function to call SBValueFormatter().vformat """
303*d8b80295SApple OSS Distributions    return _xnu_core_default_formatter.vformat(fmt, args, kwargs)
304*d8b80295SApple OSS Distributions
305*d8b80295SApple OSS Distributions
306*d8b80295SApple OSS Distributionsclass CommandOutput(object):
307*d8b80295SApple OSS Distributions    """
308*d8b80295SApple OSS Distributions    An output handler for all commands. Use Output.print to direct all output of macro via the handler.
309*d8b80295SApple OSS Distributions    These arguments are passed after a "--". eg
310*d8b80295SApple OSS Distributions    (lldb) zprint -- -o /tmp/zprint.out.txt
311*d8b80295SApple OSS Distributions
312*d8b80295SApple OSS Distributions    Currently this provide capabilities
313*d8b80295SApple OSS Distributions    -h show help
314*d8b80295SApple OSS Distributions    -o path/to/filename
315*d8b80295SApple OSS Distributions       The output of this command execution will be saved to file. Parser information or errors will
316*d8b80295SApple OSS Distributions       not be sent to file though. eg /tmp/output.txt
317*d8b80295SApple OSS Distributions    -s filter_string
318*d8b80295SApple OSS Distributions       the "filter_string" param is parsed to python regex expression and each line of output
319*d8b80295SApple OSS Distributions       will be printed/saved only if it matches the expression.
320*d8b80295SApple OSS Distributions       The command header will not be filtered in any case.
321*d8b80295SApple OSS Distributions    -p <plugin_name>
322*d8b80295SApple OSS Distributions       Send the output of the command to plugin.
323*d8b80295SApple OSS Distributions    -v ...
324*d8b80295SApple OSS Distributions       Up verbosity
325*d8b80295SApple OSS Distributions    -c <always|never|auto>
326*d8b80295SApple OSS Distributions       configure color
327*d8b80295SApple OSS Distributions    """
328*d8b80295SApple OSS Distributions    def __init__(self, cmd_name, CommandResult=None, fhandle=None):
329*d8b80295SApple OSS Distributions        """ Create a new instance to handle command output.
330*d8b80295SApple OSS Distributions        params:
331*d8b80295SApple OSS Distributions                CommandResult : SBCommandReturnObject result param from lldb's command invocation.
332*d8b80295SApple OSS Distributions        """
333*d8b80295SApple OSS Distributions        self.fname=None
334*d8b80295SApple OSS Distributions        self.fhandle=fhandle
335*d8b80295SApple OSS Distributions        self.FILTER=False
336*d8b80295SApple OSS Distributions        self.pluginRequired = False
337*d8b80295SApple OSS Distributions        self.pluginName = None
338*d8b80295SApple OSS Distributions        self.cmd_name = cmd_name
339*d8b80295SApple OSS Distributions        self.resultObj = CommandResult
340*d8b80295SApple OSS Distributions        self.verbose_level = 0
341*d8b80295SApple OSS Distributions        self.target_cmd_args = []
342*d8b80295SApple OSS Distributions        self.target_cmd_options = {}
343*d8b80295SApple OSS Distributions        self._indent = ''
344*d8b80295SApple OSS Distributions        self._buffer = ''
345*d8b80295SApple OSS Distributions
346*d8b80295SApple OSS Distributions        self._header = None
347*d8b80295SApple OSS Distributions        self._lastHeader = None
348*d8b80295SApple OSS Distributions        self._line = 0
349*d8b80295SApple OSS Distributions
350*d8b80295SApple OSS Distributions        self.color = None
351*d8b80295SApple OSS Distributions        self.isatty = os.isatty(sys.__stdout__.fileno())
352*d8b80295SApple OSS Distributions        self.VT = VT if self._doColor() else NOVT()
353*d8b80295SApple OSS Distributions
354*d8b80295SApple OSS Distributions
355*d8b80295SApple OSS Distributions    def _doColor(self):
356*d8b80295SApple OSS Distributions        if self.color is True:
357*d8b80295SApple OSS Distributions            return True;
358*d8b80295SApple OSS Distributions        return self.color is None and self.isatty
359*d8b80295SApple OSS Distributions
360*d8b80295SApple OSS Distributions    def _needsHeader(self):
361*d8b80295SApple OSS Distributions        if self._header is None:
362*d8b80295SApple OSS Distributions            return False
363*d8b80295SApple OSS Distributions        if self._lastHeader is None:
364*d8b80295SApple OSS Distributions            return True
365*d8b80295SApple OSS Distributions        if not self.isatty:
366*d8b80295SApple OSS Distributions            return False
367*d8b80295SApple OSS Distributions        return self._line - self._lastHeader > 40
368*d8b80295SApple OSS Distributions
369*d8b80295SApple OSS Distributions    def indent(self):
370*d8b80295SApple OSS Distributions        return IndentScope(self)
371*d8b80295SApple OSS Distributions
372*d8b80295SApple OSS Distributions    def table(self, header, indent = False):
373*d8b80295SApple OSS Distributions        return HeaderScope(self, header, indent)
374*d8b80295SApple OSS Distributions
375*d8b80295SApple OSS Distributions    def format(self, s, *args, **kwargs):
376*d8b80295SApple OSS Distributions        kwargs['VT'] = self.VT
377*d8b80295SApple OSS Distributions        return xnu_vformat(s, args, kwargs)
378*d8b80295SApple OSS Distributions
379*d8b80295SApple OSS Distributions    def error(self, s, *args, **kwargs):
380*d8b80295SApple OSS Distributions        print(self.format("{cmd.cmd_name}: {VT.Red}"+s+"{VT.Default}", cmd=self, *args, **kwargs))
381*d8b80295SApple OSS Distributions
382*d8b80295SApple OSS Distributions    def write(self, s):
383*d8b80295SApple OSS Distributions        """ Handler for all commands output. By default just print to stdout """
384*d8b80295SApple OSS Distributions
385*d8b80295SApple OSS Distributions        o = self.fhandle or self.resultObj
386*d8b80295SApple OSS Distributions
387*d8b80295SApple OSS Distributions        for l in (self._buffer + s).splitlines(True):
388*d8b80295SApple OSS Distributions            if l[-1] != '\n':
389*d8b80295SApple OSS Distributions                self._buffer = l
390*d8b80295SApple OSS Distributions                return
391*d8b80295SApple OSS Distributions
392*d8b80295SApple OSS Distributions            if self.FILTER:
393*d8b80295SApple OSS Distributions                if not self.reg.search(l):
394*d8b80295SApple OSS Distributions                    continue
395*d8b80295SApple OSS Distributions                l = self.reg.sub(self.VT.Underline + r"\g<0>" + self.VT.EndUnderline, l);
396*d8b80295SApple OSS Distributions
397*d8b80295SApple OSS Distributions            if len(l) == 1:
398*d8b80295SApple OSS Distributions                o.write(l)
399*d8b80295SApple OSS Distributions                self._line += 1
400*d8b80295SApple OSS Distributions                continue
401*d8b80295SApple OSS Distributions
402*d8b80295SApple OSS Distributions            if len(l) > 1 and self._needsHeader():
403*d8b80295SApple OSS Distributions                for h in self._header.splitlines():
404*d8b80295SApple OSS Distributions                    o.write(self.format("{}{VT.Bold}{:s}{VT.EndBold}\n", self._indent, h))
405*d8b80295SApple OSS Distributions                self._lastHeader = self._line
406*d8b80295SApple OSS Distributions
407*d8b80295SApple OSS Distributions            o.write(self._indent + l)
408*d8b80295SApple OSS Distributions            self._line += 1
409*d8b80295SApple OSS Distributions
410*d8b80295SApple OSS Distributions        self._buffer = ''
411*d8b80295SApple OSS Distributions
412*d8b80295SApple OSS Distributions    def flush(self):
413*d8b80295SApple OSS Distributions        if self.fhandle != None:
414*d8b80295SApple OSS Distributions            self.fhandle.flush()
415*d8b80295SApple OSS Distributions
416*d8b80295SApple OSS Distributions    def __del__(self):
417*d8b80295SApple OSS Distributions        """ closes any open files. report on any errors """
418*d8b80295SApple OSS Distributions        if self.fhandle != None and self.fname != None:
419*d8b80295SApple OSS Distributions            self.fhandle.close()
420*d8b80295SApple OSS Distributions
421*d8b80295SApple OSS Distributions    def setOptions(self, cmdargs, cmdoptions =''):
422*d8b80295SApple OSS Distributions        """ parse the arguments passed to the command
423*d8b80295SApple OSS Distributions            param :
424*d8b80295SApple OSS Distributions                cmdargs => [] of <str> (typically args.split())
425*d8b80295SApple OSS Distributions                cmdoptions : str - string of command level options.
426*d8b80295SApple OSS Distributions                             These should be CAPITAL LETTER options only.
427*d8b80295SApple OSS Distributions        """
428*d8b80295SApple OSS Distributions        opts=()
429*d8b80295SApple OSS Distributions        args = cmdargs
430*d8b80295SApple OSS Distributions        cmdoptions = cmdoptions.upper()
431*d8b80295SApple OSS Distributions        try:
432*d8b80295SApple OSS Distributions            opts,args = getopt.gnu_getopt(args,'hvo:s:p:c:'+ cmdoptions,[])
433*d8b80295SApple OSS Distributions            self.target_cmd_args = args
434*d8b80295SApple OSS Distributions        except getopt.GetoptError as err:
435*d8b80295SApple OSS Distributions            raise ArgumentError(str(err))
436*d8b80295SApple OSS Distributions        #continue with processing
437*d8b80295SApple OSS Distributions        for o,a in opts :
438*d8b80295SApple OSS Distributions            if o == "-h":
439*d8b80295SApple OSS Distributions                # This is misuse of exception but 'self' has no info on doc string.
440*d8b80295SApple OSS Distributions                # The caller may handle exception and display appropriate info
441*d8b80295SApple OSS Distributions                raise ArgumentError("HELP")
442*d8b80295SApple OSS Distributions            if o == "-o" and len(a) > 0:
443*d8b80295SApple OSS Distributions                self.fname=os.path.normpath(os.path.expanduser(a.strip()))
444*d8b80295SApple OSS Distributions                self.fhandle=open(self.fname,"w")
445*d8b80295SApple OSS Distributions                print("saving results in file ",str(a))
446*d8b80295SApple OSS Distributions                self.fhandle.write("(lldb)%s %s \n" % (self.cmd_name, " ".join(cmdargs)))
447*d8b80295SApple OSS Distributions                self.isatty = os.isatty(self.fhandle.fileno())
448*d8b80295SApple OSS Distributions            elif o == "-s" and len(a) > 0:
449*d8b80295SApple OSS Distributions                self.reg = re.compile(a.strip(),re.MULTILINE|re.DOTALL)
450*d8b80295SApple OSS Distributions                self.FILTER=True
451*d8b80295SApple OSS Distributions                print("showing results for regex:",a.strip())
452*d8b80295SApple OSS Distributions            elif o == "-p" and len(a) > 0:
453*d8b80295SApple OSS Distributions                self.pluginRequired = True
454*d8b80295SApple OSS Distributions                self.pluginName = a.strip()
455*d8b80295SApple OSS Distributions                #print "passing output to " + a.strip()
456*d8b80295SApple OSS Distributions            elif o == "-v":
457*d8b80295SApple OSS Distributions                self.verbose_level += 1
458*d8b80295SApple OSS Distributions            elif o == "-c":
459*d8b80295SApple OSS Distributions                if a in ["always", '1']:
460*d8b80295SApple OSS Distributions                    self.color = True
461*d8b80295SApple OSS Distributions                elif a in ["never", '0']:
462*d8b80295SApple OSS Distributions                    self.color = False
463*d8b80295SApple OSS Distributions                else:
464*d8b80295SApple OSS Distributions                    self.color = None
465*d8b80295SApple OSS Distributions                self.VT = VT if self._doColor() else NOVT()
466*d8b80295SApple OSS Distributions            else:
467*d8b80295SApple OSS Distributions                o = o.strip()
468*d8b80295SApple OSS Distributions                self.target_cmd_options[o] = a
469*d8b80295SApple OSS Distributions
470*d8b80295SApple OSS Distributions
471