ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/cmd/cmp.b/
implement Cmp;
include "sys.m";
sys: Sys;
include "draw.m";
draw: Draw;
include "arg.m";
BUF: con 65536;
stderr: ref Sys->FD;
Cmp: module
{
init: fn(nil: ref Draw->Context, argv: list of string);
};
init(nil: ref Draw->Context, args: list of string)
{
sys = load Sys Sys->PATH;
lflag := Lflag := sflag := 0;
buf1 := array[BUF] of byte;
buf2 := array[BUF] of byte;
stderr = sys->fildes(2);
arg := load Arg Arg->PATH;
if(arg == nil){
sys->fprint(stderr, "cmp: cannot load %s: %r\n", Arg->PATH);
raise "fail:load";
}
arg->init(args);
while((op := arg->opt()) != 0)
case op {
'l' => lflag = 1;
'L' => Lflag = 1;
's' => sflag = 1;
* => usage();
}
args = arg->argv();
arg = nil;
if(args == nil)
usage();
if(len args < 2)
usage();
name1 := hd args;
args = tl args;
if((f1 := sys->open(name1, Sys->OREAD)) == nil){
sys->fprint(stderr, "cmp: can't open %s: %r\n",name1);
raise "fail:open";
}
name2 := hd args;
args = tl args;
if((f2 := sys->open(name2, Sys->OREAD)) == nil){
sys->fprint(stderr, "cmp: can't open %s: %r\n",name2);
raise "fail:open";
}
if(args != nil){
o := big hd args;
if(sys->seek(f1, o, 0) < big 0){
sys->fprint(stderr, "cmp: seek by offset1 failed: %r\n");
raise "fail:seek 1";
}
args = tl args;
}
if(args != nil){
o := big hd args;
if(sys->seek(f2, o, 0) < big 0){
sys->fprint(stderr, "cmp: seek by offset2 failed: %r");
raise "fail:seek 2";
}
args = tl args;
}
if(args != nil)
usage();
nc := big 1;
l := big 1;
diff := 0;
b1, b2: array of byte;
for(;;){
if(len b1 == 0){
nr := sys->read(f1, buf1, BUF);
if(nr < 0){
if(!sflag)
sys->print("error on %s after %bd bytes\n", name1, nc-big 1);
raise "fail:read error";
}
b1 = buf1[0: nr];
}
if(len b2 == 0){
nr := sys->read(f2, buf2, BUF);
if(nr < 0){
if(!sflag)
sys->print("error on %s after %bd bytes\n", name2, nc-big 1);
raise "fail:read error";
}
b2 = buf2[0: nr];
}
n := len b2;
if(n > len b1)
n = len b1;
if(n == 0)
break;
for(i:=0; i<n; i++){
if(Lflag && b1[i]== byte '\n')
l++;
if(b1[i] != b2[i]){
if(!lflag){
if(!sflag){
sys->print("%s %s differ: char %bd", name1, name2, nc+big i);
if(Lflag)
sys->print(" line %bd\n", l);
else
sys->print("\n");
}
raise "fail:differ";
}
sys->print("%6bd 0x%.2x 0x%.2x\n", nc+big i, int b1[i], int b2[i]);
diff = 1;
}
}
nc += big n;
b1 = b1[n:];
b2 = b2[n:];
}
if(len b1 != len b2) {
nc--;
if(len b1 > len b2)
sys->print("EOF on %s after %bd bytes\n", name2, nc);
else
sys->print("EOF on %s after %bd bytes\n", name1, nc);
raise "fail:EOF";
}
if(diff)
raise "fail:differ";
exit;
}
usage()
{
sys->fprint(stderr, "Usage: cmp [-lsL] file1 file2 [offset1 [offset2] ]\n");
raise "fail:usage";
}