#!/usr/bin/python

# ---------------------------------------------------------------------
# Be sure to add the python path that points to the LLDB shared library.
#
# # To use this in the embedded python interpreter using "lldb" just
# import it with the full path using the "command script import"
# command
#   (lldb) command script import /path/to/cmdtemplate.py
# ---------------------------------------------------------------------

import inspect
import lldb
import optparse
import shlex
import sys


class FrameStatCommand:
    program = 'framestats'

    @classmethod
    def register_lldb_command(cls, debugger, module_name):
        parser = cls.create_options()
        cls.__doc__ = parser.format_help()
        # Add any commands contained in this module to LLDB
        command = 'command script add -c %s.%s %s' % (module_name,
                                                      cls.__name__,
                                                      cls.program)
        debugger.HandleCommand(command)
        print('The "{0}" command has been installed, type "help {0}" or "{0} '
              '--help" for detailed help.'.format(cls.program))

    @classmethod
    def create_options(cls):

        usage = "usage: %prog [options]"
        description = ('This command is meant to be an example of how to make '
                       'an LLDB command that does something useful, follows '
                       'best practices, and exploits the SB API. '
                       'Specifically, this command computes the aggregate '
                       'and average size of the variables in the current '
                       'frame and allows you to tweak exactly which variables '
                       'are to be accounted in the computation.')

        # Pass add_help_option = False, since this keeps the command in line
        #  with lldb commands, and we wire up "help command" to work by
        # providing the long & short help methods below.
        parser = optparse.OptionParser(
            description=description,
            prog=cls.program,
            usage=usage,
            add_help_option=False)

        parser.add_option(
            '-i',
            '--in-scope',
            action='store_true',
            dest='inscope',
            help='in_scope_only = True',
            default=True)

        parser.add_option(
            '-a',
            '--arguments',
            action='store_true',
            dest='arguments',
            help='arguments = True',
            default=True)

        parser.add_option(
            '-l',
            '--locals',
            action='store_true',
            dest='locals',
            help='locals = True',
            default=True)

        parser.add_option(
            '-s',
            '--statics',
            action='store_true',
            dest='statics',
            help='statics = True',
            default=True)

        return parser

    def get_short_help(self):
        return "Example command for use in debugging"

    def get_long_help(self):
        return self.help_string

    def __init__(self, debugger, unused):
        self.parser = self.create_options()
        self.help_string = self.parser.format_help()

    def __call__(self, debugger, command, exe_ctx, result):
        # Use the Shell Lexer to properly parse up command options just like a
        # shell would
        command_args = shlex.split(command)

        try:
            (options, args) = self.parser.parse_args(command_args)
        except:
            # if you don't handle exceptions, passing an incorrect argument to
            # the OptionParser will cause LLDB to exit (courtesy of OptParse
            # dealing with argument errors by throwing SystemExit)
            result.SetError("option parsing failed")
            return

        # Always get program state from the lldb.SBExecutionContext passed
        # in as exe_ctx
        frame = exe_ctx.GetFrame()
        if not frame.IsValid():
            result.SetError("invalid frame")
            return

        variables_list = frame.GetVariables(
            options.arguments,
            options.locals,
            options.statics,
            options.inscope)
        variables_count = variables_list.GetSize()
        if variables_count == 0:
            print >> result, "no variables here"
            return
        total_size = 0
        for i in range(0, variables_count):
            variable = variables_list.GetValueAtIndex(i)
            variable_type = variable.GetType()
            total_size = total_size + variable_type.GetByteSize()
            average_size = float(total_size) / variables_count
            print >>result, ("Your frame has %d variables. Their total size "
                             "is %d bytes. The average size is %f bytes") % (
                                    variables_count, total_size, average_size)
        # not returning anything is akin to returning success


def __lldb_init_module(debugger, dict):
    # Register all classes that have a register_lldb_command method
    for _name, cls in inspect.getmembers(sys.modules[__name__]):
        if inspect.isclass(cls) and callable(getattr(cls,
                                                     "register_lldb_command",
                                                     None)):
            cls.register_lldb_command(debugger, __name__)
