kolibrios/programs/cmm/vfc/vfc.c
Kirill Lipatov (Leency) 6b3f26b172 cmm: upload vfc (Visual Text Comparer / Diff tool)
git-svn-id: svn://kolibrios.org@6732 a494cfbc-eb01-0410-851d-a64ba20cac60
2016-11-20 21:48:03 +00:00

210 lines
5.4 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//visual text comparer
//by den po - jdp@bk.ru
#define MEMSIZE 4096 * 60
#include "../lib/io.h"
#include "../lib/strings.h"
#include "../lib/obj/console.h"
IO io1, io2;
#define MAX_PATH 260
#include "32user32.h"
#include "objects.h"
#include "vfc_gui.h"
#define mincmpstrings 2
#define maxcmpstrings 10
#define maxcmpoffset 100
char window_title[] = "Visual Text Comparer (Diff tool)";
char* srcfilename;
char* dstfilename;
dword srcfile;
dword dstfile;
dword srcfilesize;
dword dstfilesize;
TCollection srcfilelines; //file lines
TCollection dstfilelines;
TCollection srcfilenums; //lines numbers
TCollection dstfilenums;
struct TSimpleCollection:TSortedCollection
{
TSimpleCollection();
int Compare( int Key1, Key2 );
};
int TSimpleCollection::Compare( int Key1, Key2 ){
return Key1-Key2;
}
TSimpleCollection::TSimpleCollection():TSortedCollection(1000,1000);
{
comparemethod=#Compare;
}
TSimpleCollection diffs; //list of differing strings
dword srcfilelinks; //pointer to the previos line with the same first symbol
dword dstfilelinks; //
getstrings(dword srcfile,srcfilesize,srcfilelines){
ECX=srcfilesize;
ESI=srcfile;
WHILE(ECX){
$push ECX,ESI
EAX=srcfilelines;
EAX.TCollection.Insert(ESI);
$pop ESI,ECX
WHILE(ECX){
$cld $lodsb ECX--;
if(AL==0x0D)||(AL==0x0A)DSBYTE[ESI-1]=0;
if(AL==0x0D)&&(DSBYTE[ESI]==0x0A){$lodsb;ECX--;}
if(AL==0x0D)||(AL==0x0A)BREAK;
}
}
}
#include "if.h"
bool getparam()
{
int i, param_len = strlen(#param);
if (param[0]=='"') {
for (i=1; i<param_len; i++) if (param[i]=='"') param[i]=NULL;
srcfilename = #param + 1;
dstfilename = #param + strlen(#param) + 3;
return true;
}
notify("'Wrong params specified. Use next format:\nAPPPATH \"PARAM1\" \"PARAM2\"' -E");
return false;
}
main(){
if (param[0]) getparam();
if (!srcfilename) || (!dstfilename) gui(); else console();
}
console() {
int i;
int p;
int bs,bd,bsc,bdc,bsp,bdp;
int cache[256];
char s1;
int s2;
srcfile = io1.read(srcfilename);
dstfile = io2.read(dstfilename);
srcfilesize = io1.FILES_SIZE;
dstfilesize = io2.FILES_SIZE;
if (!srcfile) die("'First file not found' -E");
if (!dstfile) die("'Second file not found' -E");
srcfilelines.TCollection(srcfilesize/40,8192);
dstfilelines.TCollection(dstfilesize/40,8192);
//fill line pointers
getstrings(srcfile,srcfilesize,#srcfilelines);
getstrings(dstfile,dstfilesize,#dstfilelines);
srcfilenums.TCollection(srcfilelines.Count,1000);
dstfilenums.TCollection(dstfilelines.Count,1000);
srcfilelinks=malloc(srcfilelines.Count*4);
dstfilelinks=malloc(dstfilelines.Count*4);
//fill links on the next strings with the same first symbols
FillMemory(#cache,sizeof(cache),-1); i=srcfilelines.Count;
WHILE(i){
i--;
EBX=srcfilelines.At(i); EBX=DSBYTE[EBX];
DSDWORD[i<<2+srcfilelinks]=cache[EBX*4];
cache[EBX*4]=i;
}
FillMemory(#cache,sizeof(cache),-1); i=dstfilelines.Count;
WHILE(i){
i--;
EBX=dstfilelines.At(i); EBX=DSBYTE[EBX];
DSDWORD[i<<2+dstfilelinks]=cache[EBX*4];
cache[EBX*4]=i;
}
diffs.TSimpleCollection();
while( bsp < srcfilelines.Count ) || ( bdp < dstfilelines.Count )
{
////////////////////////////////////////////////////////
bsc=0;
p=dstfilelines.At(bdp);//current dst position
s1=DSBYTE[p];
bs=bsp+1;//found src line, bsc - number of matched
while( bs != -1 )//no next line starting with the same symbols
&&(bs-bsp<=maxcmpoffset)//check for 100 lines depth
&&(bs<srcfilelines.Count)
{
s2=srcfilelines.At(bs);
if(!strcmp(p,s2))
{//line found
bsc=1;
WHILE(bsc<maxcmpstrings)//counting number of matching lines
&&(bdp+bsc<dstfilelines.Count)
&&(bs+bsc<srcfilelines.Count)
&&(!strcmp(dstfilelines.At(bdp+bsc),srcfilelines.At(bs+bsc)))bsc++;
BREAK;
}
if(DSBYTE[s2]==s1)bs=DSDWORD[bs<<2+srcfilelinks];else bs++;
}
bdc=0;
p=srcfilelines.At(bsp);//current src position
s1=DSBYTE[p];
bd=bdp+1;//found dst line, bsc - number of matched
while( bd != -1 )//no next line starting with the same symbols
&&(bd-bdp<=maxcmpoffset)//check for 100 lines depth
&&(bd<dstfilelines.Count)
{
s2=dstfilelines.At(bd);
if(!strcmp(p,s2))
{
bdc=1;
WHILE(bdc<maxcmpstrings)//counting number of matching lines
&&(bsp+bdc<srcfilelines.Count)
&&(bd+bdc<dstfilelines.Count)
&&(!strcmp(srcfilelines.At(bsp+bdc),dstfilelines.At(bd+bdc)))bdc++;
BREAK;
}
if(DSBYTE[s2]==s1)bd=DSDWORD[bd<<2+dstfilelinks];else bd++;
}
if(bsc<bdc)
if(bd-bdp<bdc)
||(bdc>=mincmpstrings)
{
WHILE(bdp<bd){
diffs.Insert(srcfilenums.Count);
srcfilenums.Insert(-1); dstfilenums.Insert(bdp); bdp++;
}
continue;
}
if(strcmp(srcfilelines.At(bsp),dstfilelines.At(bdp)))diffs.Insert(srcfilenums.Count);
//lines are equal
srcfilenums.Insert(bsp); bsp++;
dstfilenums.Insert(bdp); bdp++;
CONTINUE;
}
free(srcfilelinks);
free(dstfilelinks);
if(!diffs.Count)
notify("'Nothing to compare' -E");
else ifinit();
diffs.DeleteAll(); delete diffs;
dstfilenums.DeleteAll(); delete dstfilenums;
srcfilenums.DeleteAll(); delete srcfilenums;
dstfilelines.DeleteAll(); delete dstfilelines;
srcfilelines.DeleteAll(); delete srcfilelines;
free(dstfile);
free(srcfile);
}