Пример #1
0
def _getty_append_invdiff(html_string, targets, go, prev_hash, curr_hash, iso):
    global ignore_all_ws
    ignore_all_ws = True
    anchor = "<br>{{{__getty_invariant_diff__}}}<br>"
    for target in sorted(targets, reverse=True):
        if config.install_diffinv_only:
            print '  -- processing inv diff for ' + target
            tfs = fsformat_with_sigs(target)
            osot_invf = go + "_getty_inv__" + tfs + "__" + prev_hash + "_.inv.out"
            nsnt_invf = go + "_getty_inv__" + tfs + "__" + curr_hash + "_.inv.out"
            invdiff_outft = go + "_getty_inv__" + tfs + "__" + ".inv.diff.html"
            diff_settings = [("ni", osot_invf, nsnt_invf, invdiff_outft)]
            if iso:
                osnt_invf = go + "_getty_inv__" + tfs + "__" + prev_hash + "_" + curr_hash + "_.inv.out"
                nsot_invf = go + "_getty_inv__" + tfs + "__" + curr_hash + "_" + prev_hash + "_.inv.out"
                diff_settings += [("si", osnt_invf, nsnt_invf,
                                   invdiff_outft[:-10] + ".si.diff.html"),
                                  ("ti4o", osot_invf, osnt_invf,
                                   invdiff_outft[:-10] + ".ti4o.diff.html"),
                                  ("ti4n", nsot_invf, nsnt_invf,
                                   invdiff_outft[:-10] + ".ti4n.diff.html")]
            for ds in diff_settings:
                replacement = anchor + "\n" + \
                    __generate_append_diff(target, ds[0], ds[1], ds[2], ds[3])
                html_string = html_string.replace(anchor, replacement)
    html_string = html_string.replace(anchor, "")
    if config.use_tmp_files:
        remove_many_files(go, "*" + PRSV_TMP)
    ignore_all_ws = False
    return html_string
Пример #2
0
def _getty_install_invtips(html_string, commit_msgs, github_link, prev_hash,
                           curr_hash, go, oldl2m, newl2m, iso):
    extra_tooltips_installation = "    set_commit_hashes(" + \
        "\"" + prev_hash + "\", " + "\"" + curr_hash + "\");\n"
    if config.install_extra_tips:
        newarray = ["\"" + curr_hash + "\""]
        if config.install_inv_tips:
            for pair in newl2m:
                newarray.append("\"" + __path_to_image(pair[0]) + "\"")
                newarray.append("\"" + str(pair[1]) + "\"")
                newarray.append("\"" + fsformat_with_sigs(newl2m[pair]) + "\"")
        newarray_str = "[" + ", ".join(t for t in newarray) + "]"

        oldarray = ["\"" + prev_hash + "\""]
        if config.install_inv_tips:
            for pair in oldl2m:
                oldarray.append("\"" + __path_to_image(pair[0]) + "\"")
                oldarray.append("\"" + str(pair[1]) + "\"")
                oldarray.append("\"" + fsformat_with_sigs(oldl2m[pair]) + "\"")
        oldarray_str = "[" + ", ".join(t for t in oldarray) + "]"

        extra_tooltips_installation = \
            "    installInvTips(" + \
            "\"" + curr_hash + "\", " + "\"" + prev_hash + "\", " + \
            newarray_str + ", " + oldarray_str + ");\n"

    iso_setup = ""
    if iso:
        iso_setup = "    isolation = true;\n"

    js_commit_msgs = json.dumps(commit_msgs)
    js_github_link = (json.dumps(github_link)
                      if github_link is not None else "''")

    install_line = \
        "<script>\n" + \
        "    install_msg_tips(" + js_commit_msgs + ", " + js_github_link + ");\n" + \
        "    install_legend_tips(\"" + legends + "\");\n" + \
        "    window.onbeforeunload = function() { return true; };\n" + \
        iso_setup + extra_tooltips_installation + \
        "    $(\"tr.diff-ignore\").hide();\n" + \
        "</script>\n</body>"
    html_string = html_string.replace("</body>", install_line)
    return html_string
Пример #3
0
def create_inv_out_file_per_method(out_file, methods_to_consider, this_hash,
                                   go):
    f = open(out_file, "r")

    if f.mode != 'r':
        print "WARN: file not opened in read mode"
        return False

    invariants = f.read()
    f.close()

    inv_array = invariants.split("\n================\n")

    for tgt in methods_to_consider:
        regex = daikon.dpformat_with_sigs(tgt)[1:]
        target_ff = daikon.fsformat_with_sigs(tgt)
        out_file = go + "_getty_inv__" + target_ff + "__" + this_hash + "_.inv.out"

        # TODO: this is to prevent invariants being added to the same file multiple times. This shouldn't happen in the first place.
        # I could figure out what is happening, but not exactly why and how to prevent it.
        # It's happening because, for the GStack test project:
        # For GStack, methods_to_consider will contain both isEmpty() and isEmpty()-56,56 so that's 2 times.
        # For GStackTest, methods_to_consider will also contain GStack:isEmpty() and GStack:isEmpty()-56,56, that's another 2 times.
        #    However, it will look for them in the GStackTests inv output file and of course cannot find anything there so it will print <NO INVARIANTS FOUND>
        # So in total we look 4 times for invariants for GStack:isEmtpy and 2 times we find none because we're looking in the wrong inv file.
        #    The first 2 times always find <NO INVARIANTS FOUND> and the last 2 times are duplicates
        # Solution for now: only keep the output of the last time as this was the original behavior before my changes.
        file_invs = []
        if py_os.path.isfile(out_file):
            f = open(out_file, "r")
            file_invs = f.read().split("\n================\n")
            f.close()
            if file_invs[0] == "<NO INVARIANTS INFERRED>\n":
                py_os.remove(out_file)
                file_invs = []

        file_created = len(file_invs) > 0
        for inv in inv_array:
            if inv in file_invs:
                continue

            if re.search(regex, inv):
                # print "=== writing: " + out_file
                f = open(out_file, "a+")
                file_created = True

                f.write("\n================\n")
                f.write(inv)
                f.close()

        if file_created is False:
            f = open(out_file, "a+")
            f.write("<NO INVARIANTS INFERRED>\n")
            f.close()

    return True
Пример #4
0
def inv_to_html(targets, go, commit_hash):
    for target in targets:
        tfs = fsformat_with_sigs(target)
        invs_file = go + "_getty_inv__" + tfs + "__" + commit_hash + "_.inv.out"
        try:
            with open(invs_file, 'r') as invf:
                invs = invf.read()
                newinvhtml = inv_html_header + invs + inv_html_footer
            with open(invs_file + ".html", "w") as wf:
                wf.write(newinvhtml)
        except IOError:
            with open(invs_file + ".html", 'w') as newf:
                newf.write("<NO INVARIANTS INFERRED>")
def is_different(target, go, prev_hash, post_hash):
    tfs = fsformat_with_sigs(target)
    prev_invs_file = go + "_getty_inv__" + tfs + "__" + prev_hash + "_.inv.out"
    post_invs_file = go + "_getty_inv__" + tfs + "__" + post_hash + "_.inv.out"
    if (not os.path.exists(prev_invs_file)) or (
            not os.path.exists(post_invs_file)):
        return True
    difftext = from_sys_call_enforce(" ".join(
        ["git diff", prev_invs_file, post_invs_file]))
    if difftext == "":
        return False
    else:
        return True
def __link_to_show_neighbors(t,
                             common_package,
                             all_codec_to_check=None,
                             all_invc_to_check=None):
    aid = "target-link-" + fsformat_with_sigs(t)
    cls = "target-linkstyle" + " class-" + aid
    if all_codec_to_check is not None:
        if t not in all_codec_to_check:
            cls += (" " + "dehighlight-code-change")
    if all_invc_to_check is not None:
        if t in all_invc_to_check:
            cls += (" " + "highlight-inv-change")
    _, displayname, _, _, _, fullname = simplify_target_name(
        t, common_package=common_package)
    js_cmd = "return activateNeighbors_ws(" + "\"" + fullname + "\"" + ");"
    return "<a href='#' id='" + aid + "' class='" + cls + "' onclick='" + js_cmd + "'>" + displayname + "</a>"
Пример #7
0
def _install_anchors_for(original, targets, l4ms):
    l2as = {}
    for target in targets:
        if target in l4ms:
            l2as[l4ms[target]] = "<a name='" + fsformat_with_sigs(
                target) + "'></a>"
    if len(l2as) > 0:
        installed = []
        for line_number, line_content in enumerate(original.split("\n"),
                                                   start=1):
            if line_number in l2as:
                installed.append(l2as[line_number] + line_content)
            else:
                installed.append(line_content)
        return '\n'.join(installed)
    else:
        return original
Пример #8
0
def __generate_append_diff(target, diff_type, prev_invf, post_invf,
                           diff_htmlf):
    global cached_header
    global caching_stage
    if diff_type not in ["ni", "ti4o", "ti4n", "si"]:
        raise ValueError(
            "diff_type must be one of 'ni', 'ti4o', 'ti4n', and 'si'")
    if config.use_tmp_files:
        prev_invs_file_tagged = __prediff_process(prev_invf, PRSV_LEFT,
                                                  PRSV_TMP)
        curr_invs_file_tagged = __prediff_process(post_invf, PRSV_RIGHT,
                                                  PRSV_TMP)
        dstring = from_sys_call_enforce(" ".join([
            "git diff", "--unified=" + str(config.inv_diff_context_lines),
            prev_invs_file_tagged, curr_invs_file_tagged
        ]))
    else:
        prev_invs_tagged = __prediff_process_in_memory(prev_invf, PRSV_LEFT)
        curr_invs_tagged = __prediff_process_in_memory(post_invf, PRSV_RIGHT)
        dstring = "diff --git a/invariants b/invariants\n"
        for ln in difflib.unified_diff(prev_invs_tagged,
                                       curr_invs_tagged,
                                       n=config.inv_diff_context_lines):
            dstring += ln

    cached_header = None
    caching_stage = False
    if len(dstring.split("\n")) <= config.max_diff_lines:
        dstring = __denoise(dstring)
        dtable = parse_from_memory(dstring, True, None, with_ln=False)
    else:
        print '   --- too big diff to be shown'
        dtable = '<div>The differential is too big to be shown</div>'

    inv_title = \
        "<div class='inv-cmp-title'><span class='menu-words'>Compare Invariants for</span> " + \
        "{ <span class='program-words'><b>" + __escape(target) + "</b></span> }</div>"
    invdiffhtml = \
        "<div id='vsinvs-" + diff_type + "-" + fsformat_with_sigs(target) + "'>" + \
        inv_title + "\n" + \
        ("NO DIFFERENCE" if is_empty(dtable) else dtable) + \
        "\n</div>\n"
    with open(diff_htmlf, 'w') as idout:
        idout.write(invdiffhtml)
    return invdiffhtml
def __possible_diff_with_preprocessed_diff_html(target, go):
    tfs = fsformat_with_sigs(target)
    ni_hdiff = go + "_getty_inv__" + tfs + "__.inv.diff.html"
    si_hdiff = go + "_getty_inv__" + tfs + "__.inv.si.diff.html"
    ti4o_hdiff = go + "_getty_inv__" + tfs + "__.inv.ti4o.diff.html"
    ti4n_hdiff = go + "_getty_inv__" + tfs + "__.inv.ti4n.diff.html"
    for hd in [ni_hdiff, si_hdiff, ti4o_hdiff, ti4n_hdiff]:
        if os.path.exists(hd):
            with open(hd, 'r') as hdf:
                diff_html = hdf.read()
            if not (diff_html.find("<table") < 0
                    and diff_html.find("NO DIFFERENCE") >= 0):
                return True
        else:
            print '\n***'
            print '  could not find the preprocessed file: ' + hd
            print '    --> assuming there were no diffs'
            print '***\n'
    return False
Пример #10
0
def _install_ln_anchors_for(original,
                            targets,
                            class_name_check=None,
                            for_old=False):
    #     anchored = []
    #     for index, line in enumerate(original.split("\n"), start=1):
    #         anchored.append("<a name='l" + str(index) + "'></a>" + line)
    #     return '\n'.join(anchored)
    l2as = {}
    for target in targets:
        colon_pos = target.find(":")
        dolar_pos = target.find("$")
        if class_name_check is not None:
            if (dolar_pos == -1 and target[:colon_pos] == class_name_check) or \
                (dolar_pos < colon_pos and target[:dolar_pos] == class_name_check):
                last_dash = target.rfind("-")
                ln_info_str = target[last_dash + 1:].strip()
                [oldln,
                 newln] = [int(lnstr) for lnstr in ln_info_str.split(",")]
                if for_old:
                    ln = oldln
                else:
                    ln = newln
                l2as[ln - config.max_method_decl_span] = \
                    "<a name='" + fsformat_with_sigs(target) + "'></a>"
    if len(l2as) > 0:
        installed = []
        for line_number, line_content in enumerate(original.split("\n"),
                                                   start=1):
            if line_number in l2as:
                installed.append(l2as[line_number] + line_content)
            else:
                installed.append(line_content)
        return '\n'.join(installed)
    else:
        return original
def is_possibly_different(target,
                          go,
                          prev_hash,
                          post_hash,
                          preprocessed=False):
    if preprocessed:
        return __possible_diff_with_preprocessed_diff_html(target, go)
    else:
        tfs = fsformat_with_sigs(target)
        osot_invf = go + "_getty_inv__" + tfs + "__" + prev_hash + "_.inv.out"
        nsnt_invf = go + "_getty_inv__" + tfs + "__" + post_hash + "_.inv.out"
        osnt_invf = go + "_getty_inv__" + tfs + "__" + prev_hash + "_" + post_hash + "_.inv.out"
        nsot_invf = go + "_getty_inv__" + tfs + "__" + post_hash + "_" + prev_hash + "_.inv.out"
        all_pairs = [(osot_invf, nsnt_invf), (osnt_invf, nsnt_invf),
                     (osot_invf, osnt_invf), (nsot_invf, nsnt_invf)]
        for fpair in all_pairs:
            if (not os.path.exists(fpair[0])) or (not os.path.exists(
                    fpair[1])):
                return True
            difftext = from_sys_call_enforce(" ".join(
                ["git diff", fpair[0], fpair[1]]))
            if difftext != "":
                return True
        return False
Пример #12
0
def seq_get_invs(target_set_index_pair, java_cmd, junit_torun, go, this_hash,
                 consider_expansion, test_selection):
    index = target_set_index_pair[1]
    target_set = target_set_index_pair[0]
    # if test selection remove class from target set
    if test_selection:
        ttarget_set = set(target_set)
        for s in ttarget_set:
            if not s.__contains__(":"):
                target_set.remove(s)
    #     select_pattern = daikon.select_full(target_set)
    select_pattern = daikon.dfformat_full_ordered(target_set, test_selection)
    print "\n=== select pattern ===\n" + select_pattern + "\n"

    inv_gz = go + "_getty_inv_" + this_hash + "_." + index
    if config.compress_inv:
        inv_gz += ".inv.gz"
    else:
        inv_gz += ".inv"

    daikon_control_opt_list = []
    if SHOW_MORE_DEBUG_INFO:
        daikon_control_opt_list.append("--show_progress --no_text_output")
    elif SHOW_DEBUG_INFO:
        daikon_control_opt_list.append("--no_show_progress --no_text_output")
    else:
        daikon_control_opt_list.append("--no_text_output")
    if config.disable_known_invs:
        daikon_control_opt_list.append("--disable-all-invariants")
    if config.omit_redundant_invs:
        daikon_control_opt_list.append("--omit_from_output 0r")
    if config.daikon_format_only:
        daikon_control_opt_list.append("--format Daikon")
    daikon_control_opt_list.append(config.blocked_daikon_invs_exp)
    daikon_display_args = " ".join(daikon_control_opt_list)
    # run Chicory + Daikon (online) for invariants without trace I/O
    run_chicory_daikon = \
        " ".join([java_cmd, "daikon.Chicory --daikon-online --exception-handling",
                  "--daikon-args=\"" + daikon_display_args,
                  "-o", inv_gz + "\"",
                  "--ppt-select-pattern=\"" + select_pattern + "\"",
                  junit_torun])
    if SHOW_DEBUG_INFO:
        print "\n=== Daikon:Chicory+Daikon(online) command to run: \n" + run_chicory_daikon
    os.sys_call(run_chicory_daikon,
                ignore_bad_exit=True,
                cwd=ProjectUtils.get_version_path(this_hash))

    expansion = set()
    if consider_expansion and config.class_level_expansion:
        try:
            all_methods_expansion(expansion, go, this_hash, index, java_cmd,
                                  inv_gz)
        except:
            pass

    if SHOW_DEBUG_INFO:
        current_count = 0
        total_count = len(target_set)

    all_to_consider = set(target_set)
    if config.class_level_expansion:
        all_to_consider = (all_to_consider | expansion)

    classes_to_consider = set()
    for tgt in all_to_consider:
        class_ref = tgt.split(':')[0]
        classes_to_consider.add(class_ref)

    print "==== classes to consider: ", classes_to_consider, " hash: " + this_hash
    for tgt in classes_to_consider:
        print "============ target is: " + tgt + ", pattern is: " + daikon.dpformat_with_sigs(
            tgt) + " ==============="
        target_ff = daikon.fsformat_with_sigs(tgt)
        out_file = go + "_getty_inv__" + target_ff + "__" + this_hash + "_.inv.out"

        # TODO: For some reason adding this optimization leads to different results
        # if py_os.path.isfile(out_file):
        #     f = open(out_file, "r")
        #     f_invs = f.read()
        #     f.close()
        #     if  f_invs == "<NO INVARIANTS INFERRED>\n":
        #         print "no invariants found, running daikon.PrintInvariants again for class", tgt
        #     else:
        #         # don't run daikon.PrintInvariants twice for the same class
        #         print "not running daikon.PrintInvariants again for class", tgt, f_invs
        #         continue

        run_printinv = \
            " ".join([java_cmd, "daikon.PrintInvariants",
                      "--format", config.output_inv_format,
                      "--ppt-select-pattern=\'" + daikon.dpformat_with_sigs(tgt)[:-1] + "[.:]" + "\'",
                      "--output", out_file, inv_gz])
        if SHOW_DEBUG_INFO:
            current_count += 1
            if config.show_regex_debug:
                print "\n\tthe regex for: " + tgt + "\n\t\t" + daikon.dpformat_with_sigs(
                    tgt) + "\n"
            os.print_progress(current_count,
                              total_count,
                              prefix='Progress(' + index + '):',
                              suffix='(' + str(current_count) + '/' +
                              str(total_count) + ': ' + tgt + ')' + ' ' * 20,
                              bar_length=50)
        elif SHOW_MORE_DEBUG_INFO:
            print "\n=== Daikon:PrintInvs command to run: \n" + run_printinv
        os.sys_call(run_printinv,
                    ignore_bad_exit=True,
                    cwd=ProjectUtils.get_version_path(this_hash))
        sort_txt_inv(out_file)

        result = create_inv_out_file_per_method(out_file, all_to_consider,
                                                this_hash, go)
        if result is False:
            print "create_inv_out_file_per_method returned False"

    os.remove_file(inv_gz)
def seq_get_invs(target_set_index_pair, java_cmd, junit_torun, go, this_hash, consider_expansion):
    
    index = target_set_index_pair[1]
    target_set = target_set_index_pair[0]
    print "\n\t****\n" + "  forked: " + index + "\n\t****\n"
    
#     select_pattern = daikon.select_full(target_set)
    select_pattern = daikon.dfformat_full_ordered(target_set)
    print "\n=== select pattern ===\n" + select_pattern + "\n"
    
    inv_gz = go + "_getty_inv_" + this_hash + "_." + index
    if config.compress_inv:
        inv_gz += ".inv.gz"
    else:
        inv_gz += ".inv"
    
    daikon_control_opt_list = []
    if SHOW_MORE_DEBUG_INFO:
        daikon_control_opt_list.append("--show_progress --no_text_output")
    elif SHOW_DEBUG_INFO:
        daikon_control_opt_list.append("--no_show_progress --no_text_output")
    else:
        daikon_control_opt_list.append("--no_text_output")
    if config.disable_known_invs:
        daikon_control_opt_list.append("--disable-all-invariants")
    if config.omit_redundant_invs:
        daikon_control_opt_list.append("--omit_from_output 0r")
    if config.daikon_format_only:
        daikon_control_opt_list.append("--format Daikon")
    daikon_control_opt_list.append(config.blocked_daikon_invs_exp)
    daikon_display_args = " ".join(daikon_control_opt_list)
    # run Chicory + Daikon (online) for invariants without trace I/O
    run_chicory_daikon = \
        " ".join([java_cmd, "daikon.Chicory --daikon-online --exception-handling",
                  "--daikon-args=\""+daikon_display_args,
                  "-o", inv_gz+"\"",
                  "--ppt-select-pattern=\""+select_pattern+"\"",
                  junit_torun])
    if SHOW_DEBUG_INFO:
        print "\n=== Daikon:Chicory+Daikon(online) command to run: \n" + run_chicory_daikon
    os.sys_call(run_chicory_daikon, ignore_bad_exit=True)
    
    expansion = set()
    if consider_expansion and config.class_level_expansion:
        try:
            all_methods_expansion(expansion, target_set, go, this_hash, index, java_cmd, inv_gz)
        except:
            pass
    
    if SHOW_DEBUG_INFO:
        current_count = 0
        total_count = len(target_set)
    
    all_to_consider = set(target_set)
    if config.class_level_expansion:
        all_to_consider = (all_to_consider | expansion)
    
    for tgt in all_to_consider:
        target_ff = daikon.fsformat_with_sigs(tgt)
        out_file = go+"_getty_inv__"+target_ff+"__"+this_hash+"_.inv.out"
        run_printinv = \
            " ".join([java_cmd, "daikon.PrintInvariants",
                      "--format", config.output_inv_format,
                      "--ppt-select-pattern=\'"+daikon.dpformat_with_sigs(tgt)+"\'",
                      "--output", out_file, inv_gz])
        if SHOW_DEBUG_INFO:
            current_count += 1
            if config.show_regex_debug:
                print "\n\tthe regex for: " + tgt + "\n\t\t" + daikon.dpformat_with_sigs(tgt) + "\n"
            os.print_progress(current_count, total_count, 
                              prefix='Progress('+index+'):', 
                              suffix='('+str(current_count)+'/'+str(total_count)+': '+tgt+')'+' '*20, 
                              bar_length=50)
        elif SHOW_MORE_DEBUG_INFO:
            print "\n=== Daikon:PrintInvs command to run: \n" + run_printinv
        os.sys_call(run_printinv, ignore_bad_exit=True)
        sort_txt_inv(out_file)
    os.remove_file(inv_gz)
Пример #14
0
def add_line(s1, s2, output_file, with_ln=True):
    global line1
    global line2

    global oldl2m
    global newl2m

    global cached_header
    global caching_stage
    global ignore_all_ws

    orig1 = s1
    orig2 = s2

    line1_active_flag = False
    line2_active_flag = False

    if s1 is None and s2 is None:
        type_name = "unmodified"
    if (s1 is None or (len(s1) <= 1 and s1.strip() == "")) and \
            (s2 is None or (len(s2) <= 1 and s2.strip() == "")):
        if ignore_all_ws:
            type_name = "-ignore"
        else:
            type_name = "unmodified"
    elif (s1 is None or s1.strip() == "") and s2 is not None:
        type_name = "added"
        line2_active_flag = True
    elif (s2 is None or s2.strip() == "") and s1 is not None:
        type_name = "deleted"
        line1_active_flag = True
    elif s1 == s2 and not (s1.startswith(TOO_LONG_MSG)
                           and s2.startswith(TOO_LONG_MSG)):
        type_name = "unmodified"
    else:
        type_name = "changed"
        line2_active_flag = True
        if algorithm == 1:
            s1, s2 = diff_changed_words_ts(orig1, orig2)
        elif algorithm == 2:
            s1, s2 = diff_changed_ts(orig1, orig2)
        else:  # default
            s1, s2 = linediff(orig1, orig2)

    extra_anchor_names = set()

    if (not line1_active_flag) and (not line2_active_flag):
        extra_anchor_names.clear()
    else:
        if line2_active_flag:
            possible_nk = (postfile, int(line2))
            if possible_nk in newl2m:
                extra_anchor_names.add(TARGET_ANCHOR_PREFIX +
                                       fsformat_with_sigs(newl2m[possible_nk]))
        if line1_active_flag:
            possible_ok = (prefile, int(line1))
            if possible_ok in oldl2m:
                extra_anchor_names.add(TARGET_ANCHOR_PREFIX +
                                       fsformat_with_sigs(oldl2m[possible_ok]))

    if (orig1 is not None and orig1.startswith(PRSV_LEFT)) or \
            (orig2 is not None and orig2.startswith(PRSV_RIGHT)):
        cached_header = ('<tr class="invheader diff%s">' %
                         type_name).encode(encoding)
        caching_stage = True
    else:
        if ((orig1 is None or str(orig1).strip() == "") and
            (orig2 is not None and str(orig2).strip().startswith("================"))) or \
             ((orig2 is None or str(orig2).strip() == "") and
              (orig1 is not None and str(orig1).strip().startswith("================"))) or \
             ((orig1 is not None and str(orig1).strip().startswith("================")) and
              (orig2 is not None and str(orig2).strip().startswith("================"))) or \
             (orig1 is None and orig2 is not None and str(orig2).strip() == "") or \
             (orig2 is None and orig1 is not None and str(orig1).strip() == "") or \
             (orig1 is not None and orig2 is not None and type_name == "unmodified" and not with_ln) or \
             (ignore_all_ws and str(orig1).strip() == "" and str(orig2).strip() == ""):
            if caching_stage:
                cached_header += (('<tr class="diff-ignore diff%s">' %
                                   type_name).encode(encoding))
            else:
                output_file.write(('<tr class="diff-ignore diff%s">' %
                                   type_name).encode(encoding))
        else:
            if cached_header is not None:
                output_file.write(cached_header)
                cached_header = None
            if caching_stage:
                caching_stage = False
            output_file.write(
                ('<tr class="diff%s">' % type_name).encode(encoding))

    if caching_stage:
        om1 = re.match(orig_header_regex, str(orig1))
        if om1:
            m1 = re.match(header_regex, str(s1))
            s1 = str(s1)[len(m1.group(1)):].strip() if m1 else str(s1).strip()
        om2 = re.match(orig_header_regex, str(orig2))
        if om2:
            m2 = re.match(header_regex, str(s2))
            s2 = str(s2)[len(m2.group(1)):].strip() if m2 else str(s2).strip()

        if s1 != None and s1 != "":
            cached_header += (('<td class="diffline">%s </td>' %
                               _ln(line1, with_ln)).encode(encoding))
            cached_header += ('<td class="diffpresent">'.encode(encoding))
            cached_header += (convert(s1, linesize=linesize,
                                      ponct=1).encode(encoding))
            cached_header += ('</td>')
        else:
            s1 = ""
            cached_header += ('<td colspan="2"></td>')

        if s2 != None and s2 != "":
            if with_ln:
                cached_header += (('<td class="diffline">%s </td>' %
                                   _ln(line2, with_ln)).encode(encoding))
            else:
                cached_header += (('<td class="diffline with_liner">%s </td>' %
                                   _ln(line2, with_ln)).encode(encoding))
            cached_header += ('<td class="diffpresent">')
            cached_header += (convert(s2, linesize=linesize,
                                      ponct=1).encode(encoding))
            cached_header += ('</td>')
        else:
            s2 = ""
            if with_ln:
                cached_header += ('<td colspan="2"></td>')
            else:
                cached_header += ('<td class="with_liner" colspan="2"></td>')
        cached_header += ('</tr>\n')
    else:
        extra_anchors = ""
        for ean in extra_anchor_names:
            extra_anchors += ("<a name='" + ean + "'></a>")
        if s1 != None and s1 != "":
            output_file.write(
                ('<td class="diffline">' + extra_anchors +
                 '%s </td>' % _ln(line1, with_ln)).encode(encoding))
            output_file.write('<td class="diffpresent">'.encode(encoding))
            output_file.write(
                convert(s1, linesize=linesize, ponct=1).encode(encoding))
            output_file.write('</td>')
        else:
            s1 = ""
            output_file.write('<td colspan="2">' + extra_anchors + '</td>')

        if s2 != None and s2 != "":
            if with_ln:
                output_file.write(('<td class="diffline">%s </td>' %
                                   _ln(line2, with_ln)).encode(encoding))
            else:
                output_file.write(('<td class="diffline with_liner">%s </td>' %
                                   _ln(line2, with_ln)).encode(encoding))
            output_file.write('<td class="diffpresent">')
            output_file.write(
                convert(s2, linesize=linesize, ponct=1).encode(encoding))
            output_file.write('</td>')
        else:
            s2 = ""
            if with_ln:
                output_file.write('<td colspan="2"></td>')
            else:
                output_file.write('<td class="with_liner" colspan="2"></td>')
        output_file.write('</tr>\n')

    if s1 != "":
        line1 += 1
    if s2 != "":
        line2 += 1