#!/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/clandiag.py
#----------------------------------------------------------------------

from __future__ import absolute_import, division, print_function
import lldb
import argparse
import shlex
import os
import re
import subprocess

class MyParser(argparse.ArgumentParser):
    def format_help(self):
        return '''     Commands for managing clang diagnostic breakpoints

Syntax: clangdiag enable [<warning>|<diag-name>]
        clangdiag disable
        clangdiag diagtool [<path>|reset]

The following subcommands are supported:

      enable   -- Enable clang diagnostic breakpoints.
      disable  -- Disable all clang diagnostic breakpoints.
      diagtool -- Return, set, or reset diagtool path.

This command sets breakpoints in clang, and clang based tools, that
emit diagnostics.  When a diagnostic is emitted, and clangdiag is
enabled, it will use the appropriate diagtool application to determine
the name of the DiagID, and set breakpoints in all locations that
'diag::name' appears in the source.  Since the new breakpoints are set
after they are encountered, users will need to launch the executable a
second time in order to hit the new breakpoints.

For in-tree builds, the diagtool application, used to map DiagID's to
names, is found automatically in the same directory as the target
executable.  However, out-or-tree builds must use the 'diagtool'
subcommand to set the appropriate path for diagtool in the clang debug
bin directory.  Since this mapping is created at build-time, it's
important for users to use the same version that was generated when
clang was compiled, or else the id's won't match.

Notes:
- Substrings can be passed for both <warning> and <diag-name>.
- If <warning> is passed, only enable the DiagID(s) for that warning.
- If <diag-name> is passed, only enable that DiagID.
- Rerunning enable clears existing breakpoints.
- diagtool is used in breakpoint callbacks, so it can be changed
  without the need to rerun enable.
- Adding this to your ~.lldbinit file makes clangdiag available at startup:
  "command script import /path/to/clangdiag.py"

'''

def create_diag_options():
    parser = MyParser(prog='clangdiag')
    subparsers = parser.add_subparsers(
        title='subcommands',
        dest='subcommands',
        metavar='')
    disable_parser = subparsers.add_parser('disable')
    enable_parser = subparsers.add_parser('enable')
    enable_parser.add_argument('id', nargs='?')
    diagtool_parser = subparsers.add_parser('diagtool')
    diagtool_parser.add_argument('path', nargs='?')
    return parser

def getDiagtool(target, diagtool = None):
    id = target.GetProcess().GetProcessID()
    if 'diagtool' not in getDiagtool.__dict__:
        getDiagtool.diagtool = {}
    if diagtool:
        if diagtool == 'reset':
            getDiagtool.diagtool[id] = None
        elif os.path.exists(diagtool):
            getDiagtool.diagtool[id] = diagtool
        else:
            print('clangdiag: %s not found.' % diagtool)
    if not id in getDiagtool.diagtool or not getDiagtool.diagtool[id]:
        getDiagtool.diagtool[id] = None
        exe = target.GetExecutable()
        if not exe.Exists():
            print('clangdiag: Target (%s) not set.' % exe.GetFilename())
        else:
            diagtool = os.path.join(exe.GetDirectory(), 'diagtool')
            if os.path.exists(diagtool):
                getDiagtool.diagtool[id] = diagtool
            else:
                print('clangdiag: diagtool not found along side %s' % exe)

    return getDiagtool.diagtool[id]

def setDiagBreakpoint(frame, bp_loc, dict):
    id = frame.FindVariable("DiagID").GetValue()
    if id is None:
        print('clangdiag: id is None')
        return False

    # Don't need to test this time, since we did that in enable.
    target = frame.GetThread().GetProcess().GetTarget()
    diagtool = getDiagtool(target)
    name = subprocess.check_output([diagtool, "find-diagnostic-id", id]).rstrip();
    # Make sure we only consider errors, warnings, and extensions.
    # FIXME: Make this configurable?
    prefixes = ['err_', 'warn_', 'exp_']
    if len([prefix for prefix in prefixes+[''] if name.startswith(prefix)][0]):
        bp = target.BreakpointCreateBySourceRegex(name, lldb.SBFileSpec())
        bp.AddName("clang::Diagnostic")

    return False

def enable(exe_ctx, args):
    # Always disable existing breakpoints
    disable(exe_ctx)

    target = exe_ctx.GetTarget()
    numOfBreakpoints = target.GetNumBreakpoints()

    if args.id:
        # Make sure we only consider errors, warnings, and extensions.
        # FIXME: Make this configurable?
        prefixes = ['err_', 'warn_', 'exp_']
        if len([prefix for prefix in prefixes+[''] if args.id.startswith(prefix)][0]):
            bp = target.BreakpointCreateBySourceRegex(args.id, lldb.SBFileSpec())
            bp.AddName("clang::Diagnostic")
        else:
            diagtool = getDiagtool(target)
            list = subprocess.check_output([diagtool, "list-warnings"]).rstrip();
            for line in list.splitlines(True):
                m = re.search(r' *(.*) .*\[\-W' + re.escape(args.id) + r'.*].*', line)
                # Make sure we only consider warnings.
                if m and m.group(1).startswith('warn_'):
                    bp = target.BreakpointCreateBySourceRegex(m.group(1), lldb.SBFileSpec())
                    bp.AddName("clang::Diagnostic")
    else:
        print('Adding callbacks.')
        bp = target.BreakpointCreateByName('DiagnosticsEngine::Report')
        bp.SetScriptCallbackFunction('clangdiag.setDiagBreakpoint')
        bp.AddName("clang::Diagnostic")

    count = target.GetNumBreakpoints() - numOfBreakpoints
    print('%i breakpoint%s added.' % (count, "s"[count==1:]))

    return

def disable(exe_ctx):
    target = exe_ctx.GetTarget()
    # Remove all diag breakpoints.
    bkpts = lldb.SBBreakpointList(target)
    target.FindBreakpointsByName("clang::Diagnostic", bkpts)
    for i in range(bkpts.GetSize()):
        target.BreakpointDelete(bkpts.GetBreakpointAtIndex(i).GetID())

    return

def the_diag_command(debugger, command, exe_ctx, result, dict):
    # Use the Shell Lexer to properly parse up command options just like a
    # shell would
    command_args = shlex.split(command)
    parser = create_diag_options()
    try:
        args = parser.parse_args(command_args)
    except:
        return

    if args.subcommands == 'enable':
        enable(exe_ctx, args)
    elif args.subcommands == 'disable':
        disable(exe_ctx)
    else:
        diagtool = getDiagtool(exe_ctx.GetTarget(), args.path)
        print('diagtool = %s' % diagtool)

    return

def __lldb_init_module(debugger, dict):
    # This initializer is being run from LLDB in the embedded command interpreter
    # Make the options so we can generate the help text for the new LLDB
    # command line command prior to registering it with LLDB below
    parser = create_diag_options()
    the_diag_command.__doc__ = parser.format_help()
    # Add any commands contained in this module to LLDB
    debugger.HandleCommand(
        'command script add -f clangdiag.the_diag_command clangdiag')
    print('The "clangdiag" command has been installed, type "help clangdiag" or "clangdiag --help" for detailed help.')
