def identifier_search(search, tree_name, needle, complete, fold_case):
    needle = re.sub(r'\\(.)', r'\1', needle)

    pieces = re.split(r'\.|::', needle)
    # If the last segment of the search needle is too short, return no results
    # because we're worried that would return too many results.
    if not complete and len(pieces[-1]) < 3:
        return {}

    # Fixup closure for use by add_qualified_results to reduce the range of the
    # match's bounds to the prefix that was included in the search needle from
    # the full bounds of the search result.  (So if the search was "foo::bar"
    # and we matched "foo::bartab" and "foo::barhat", the idea I guess is that
    # only the "bar" portion would be highlighted assuming the bounds
    # previously were referencing "bartab" and "barhat".)
    def line_modifier(line):
        if 'bounds' in line:
            (start, end) = line['bounds']
            end = start + len(pieces[-1])
            line['bounds'] = [start, end]

    ids = identifiers.lookup(tree_name, needle, complete, fold_case)
    for (i, (qualified, sym)) in enumerate(ids):
        if i > 500:
            break

        q = demangle(sym)
        if q == sym:
            q = qualified

        results = crossrefs.lookup(tree_name, sym)
        search.add_qualified_results(q, results, line_modifier)