static int call_diff (const char *out) { call_diff_add_arg (NULL); if (out == RUN_TTY) return diff_run( call_diff_argc, call_diff_argv, NULL, &call_diff_stdout_callbacks ); else return diff_run( call_diff_argc, call_diff_argv, out, &call_diff_file_callbacks ); }
int generate_diff(deng_t ** d, slist_t * l1, slist_t * l2, char * file, bool display, options_t * opt) { int ret; clist_t * cl1, * cl2; int un1, un2, idf, mf; deng_t * eng; eng = diff_engine_initialize(l1, l2, opt); if (eng == NULL) return -1; cl1 = clist_init(l1); cl2 = clist_init(l2); if (file) ret = diff_run(eng, cl1, cl2, DIFF_EQUAL_NAME, DIFF_NEQUAL_STR, false); else { ret = diff_run(eng, cl1, cl2, DIFF_EQUAL_SIG_HASH_CRC, DIFF_EQUAL_SIG_HASH, false); ret = diff_run(eng, cl1, cl2, DIFF_NEQUAL_PRED, DIFF_NEQUAL_STR, false); } //printf("%s\n",file); if (display) { eng->mlist = siglist_init(eng->matched, file); eng->ulist = siglist_init(eng->unmatched, file); eng->ilist = siglist_init(eng->identical, file); un1 = un2 = idf = mf = 0; for (size_t i=0; i<l1->num; i++) { if (sig_is_class(l1->sigs[i])) { sig_free(l1->sigs[i]); continue; } if (sig_get_matched_type(l1->sigs[i]) == DIFF_UNMATCHED) { sig_set_nfile(l1->sigs[i], 1); siglist_add(eng->ulist, l1->sigs[i]); un1++; } else { // was || should be && ? if (l1->sigs[i]->hash2 == l1->sigs[i]->msig->hash2 && sig_equal(l1->sigs[i], l1->sigs[i]->msig, DIFF_EQUAL_SIG_HASH)) { siglist_add(eng->ilist, l1->sigs[i]); idf++; } else { siglist_add(eng->mlist, l1->sigs[i]); mf++; } } } for (size_t i=0; i<l2->num; i++) { if (sig_is_class(l2->sigs[i])) { sig_free(l2->sigs[i]); continue; } if (sig_get_matched_type(l2->sigs[i]) == DIFF_UNMATCHED) { sig_set_nfile(l2->sigs[i], 2); siglist_add(eng->ulist, l2->sigs[i]); un2++; } } msg("Identical functions: %d\n", idf); msg("Matched functions: %d\n", mf); msg("Unmatched functions 1: %d\n", un1); msg("Unmatched functions 2: %d\n", un2); display_results(eng); } if (d) *d = eng; return 0; }
int diff_run(deng_t * eng, clist_t * cl1, clist_t * cl2, int min_type, int max_type, bool pclass) { dpsig_t * dsig, * dsig2; int changed = 0; int type = min_type; int mtype = max_type; bool b; if (pclass && max_type > DIFF_EQUAL_SIG_HASH) mtype = DIFF_EQUAL_SIG_HASH; do { clist_reset(cl1); clist_reset(cl2); changed = 0; while ( (dsig = clist_get_best_sig(cl1, type)) != NULL) { clist_reset(cl2); dsig2 = clist_get_eq_sig(cl2, dsig, type); if (dsig2) { sig_set_matched_sig(dsig->sig, dsig2->sig, type); eng->unmatched -= 2; /* struct signature { (...) unsigned long sig; unsigned long hash; unsigned long hash2; unsigned long crc_hash; unsigned long str_hash; unsigned long lines; (...) }; */ /* Debug: if(dsig->sig->hash2 != dsig2->sig->hash2) { printf("SIG: %lu : %lu\n",dsig->sig->sig,dsig2->sig->sig); printf("HASH: %lu : %lu\n",dsig->sig->hash,dsig2->sig->hash); printf("HASH2: %lu : %lu\n",dsig->sig->hash2,dsig2->sig->hash2); printf("CRC: %lu : %lu\n",dsig->sig->crc_hash,dsig2->sig->crc_hash); }*/ // was OR, should be AND ? if (sig_equal(dsig->sig, dsig2->sig, DIFF_EQUAL_SIG_HASH) && (dsig->sig->hash2 == dsig2->sig->hash2)) { eng->identical++; } else { eng->matched++; } changed = 1; clist_update_and_remove(cl1, dsig); clist_update_and_remove(cl2, dsig2); b = sig_is_class(dsig->sig); // string matching is not 100% reliable so we only match on crc/hash if (mtype == DIFF_NEQUAL_STR) b = true; diff_run(eng, sig_get_crefs(dsig->sig, SIG_PRED), sig_get_crefs(dsig2->sig, SIG_PRED), min_type, max_type, b); diff_run(eng, sig_get_crefs(dsig->sig, SIG_SUCC), sig_get_crefs(dsig2->sig, SIG_SUCC), min_type, max_type, b); } } if (changed == 0) type++; } while(type <= mtype); return 0; }