1implement Cmp; 2 3include "sys.m"; 4 sys: Sys; 5 6include "draw.m"; 7 draw: Draw; 8 9include "arg.m"; 10 11BUF: con 65536; 12stderr: ref Sys->FD; 13 14Cmp: module 15{ 16 init: fn(nil: ref Draw->Context, argv: list of string); 17}; 18 19init(nil: ref Draw->Context, args: list of string) 20{ 21 sys = load Sys Sys->PATH; 22 23 lflag := Lflag := sflag := 0; 24 buf1 := array[BUF] of byte; 25 buf2 := array[BUF] of byte; 26 27 stderr = sys->fildes(2); 28 29 arg := load Arg Arg->PATH; 30 if(arg == nil){ 31 sys->fprint(stderr, "cmp: cannot load %s: %r\n", Arg->PATH); 32 raise "fail:load"; 33 } 34 arg->init(args); 35 while((op := arg->opt()) != 0) 36 case op { 37 'l' => lflag = 1; 38 'L' => Lflag = 1; 39 's' => sflag = 1; 40 * => usage(); 41 } 42 args = arg->argv(); 43 arg = nil; 44 if(args == nil) 45 usage(); 46 47 if(len args < 2) 48 usage(); 49 name1 := hd args; 50 args = tl args; 51 52 if((f1 := sys->open(name1, Sys->OREAD)) == nil){ 53 sys->fprint(stderr, "cmp: can't open %s: %r\n",name1); 54 raise "fail:open"; 55 } 56 name2 := hd args; 57 args = tl args; 58 59 if((f2 := sys->open(name2, Sys->OREAD)) == nil){ 60 sys->fprint(stderr, "cmp: can't open %s: %r\n",name2); 61 raise "fail:open"; 62 } 63 64 if(args != nil){ 65 o := big hd args; 66 if(sys->seek(f1, o, 0) < big 0){ 67 sys->fprint(stderr, "cmp: seek by offset1 failed: %r\n"); 68 raise "fail:seek 1"; 69 } 70 args = tl args; 71 } 72 73 if(args != nil){ 74 o := big hd args; 75 if(sys->seek(f2, o, 0) < big 0){ 76 sys->fprint(stderr, "cmp: seek by offset2 failed: %r"); 77 raise "fail:seek 2"; 78 } 79 args = tl args; 80 } 81 if(args != nil) 82 usage(); 83 nc := big 1; 84 l := big 1; 85 diff := 0; 86 b1, b2: array of byte; 87 for(;;){ 88 if(len b1 == 0){ 89 nr := sys->read(f1, buf1, BUF); 90 if(nr < 0){ 91 if(!sflag) 92 sys->print("error on %s after %bd bytes\n", name1, nc-big 1); 93 raise "fail:read error"; 94 } 95 b1 = buf1[0: nr]; 96 } 97 if(len b2 == 0){ 98 nr := sys->read(f2, buf2, BUF); 99 if(nr < 0){ 100 if(!sflag) 101 sys->print("error on %s after %bd bytes\n", name2, nc-big 1); 102 raise "fail:read error"; 103 } 104 b2 = buf2[0: nr]; 105 } 106 n := len b2; 107 if(n > len b1) 108 n = len b1; 109 if(n == 0) 110 break; 111 for(i:=0; i<n; i++){ 112 if(Lflag && b1[i]== byte '\n') 113 l++; 114 if(b1[i] != b2[i]){ 115 if(!lflag){ 116 if(!sflag){ 117 sys->print("%s %s differ: char %bd", name1, name2, nc+big i); 118 if(Lflag) 119 sys->print(" line %bd\n", l); 120 else 121 sys->print("\n"); 122 } 123 raise "fail:differ"; 124 } 125 sys->print("%6bd 0x%.2x 0x%.2x\n", nc+big i, int b1[i], int b2[i]); 126 diff = 1; 127 } 128 } 129 nc += big n; 130 b1 = b1[n:]; 131 b2 = b2[n:]; 132 } 133 if(len b1 != len b2) { 134 nc--; 135 if(len b1 > len b2) 136 sys->print("EOF on %s after %bd bytes\n", name2, nc); 137 else 138 sys->print("EOF on %s after %bd bytes\n", name1, nc); 139 raise "fail:EOF"; 140 } 141 if(diff) 142 raise "fail:differ"; 143 exit; 144} 145 146 147usage() 148{ 149 sys->fprint(stderr, "Usage: cmp [-lsL] file1 file2 [offset1 [offset2] ]\n"); 150 raise "fail:usage"; 151} 152