import inspect


def _find_source_lines(model_info, kernel_module):
    """
    Identify the location of the C source inside the model definition file.

    This code runs through the source of the kernel module looking for
    lines that start with 'Iq', 'Iqxy' or 'form_volume'.  Clearly there are
    all sorts of reasons why this might not work (e.g., code commented out
    in a triple-quoted line block, code built using string concatenation,
    or code defined in the branch of an 'if' block), but it should work
    properly in the 95% case, and getting the incorrect line number will
    be harmless.
    """
    # Check if we need line numbers at all
    if callable(model_info.Iq):
        return None

    if (model_info.Iq is None
            and model_info.Iqxy is None
            and model_info.Imagnetic is None
            and model_info.form_volume is None):
        return

    # find the defintion lines for the different code blocks
    try:
        source = inspect.getsource(kernel_module)
    except IOError:
        return
    for k, v in enumerate(source.split('\n')):
        if v.startswith('Imagnetic'):
            model_info._Imagnetic_line = k+1
        elif v.startswith('Iqxy'):
            model_info._Iqxy_line = k+1
        elif v.startswith('Iq'):
            model_info._Iq_line = k+1
        elif v.startswith('form_volume'):
            model_info._form_volume_line = k+1