#!/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
#----------------------------------------------------------------------

import lldb
import argparse
import commands
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.'
