#include #include #include #include #include #include #define BUFFER 4096 static int do_open(const char *name) { int fd; fd = open(name, O_RDONLY); if (fd >= 0) return fd; perror(name); exit(1); } static void usage(const char *name) { fprintf(stderr, "usage: %s [-w|-l] [-B] file1 file2\n" " -w compare words (16 bits; default is bytes)\n" " -l compare long words (32 bits; default is bytes)\n" " -B use big-endian (default: little-endian)\n" , name); exit(1); } int main(int argc, char *const *argv) { int little = 1; int bytes = 1; int c; int fd1, fd2; const char *name1, *name2; uint8_t buf1[BUFFER], buf2[BUFFER]; ssize_t got1, got2, len; uint32_t a, b; int i, j; static unsigned bin[32][2]; while ((c = getopt(argc, argv, "Blw")) != EOF) { switch (c) { case 'B': little = 0; break; case 'l': bytes = 4; break; case 'w': bytes = 2; break; default: usage(*argv); } } if (argc-optind != 2) usage(*argv); name1 = argv[optind]; name2 = argv[optind+1]; fd1 = do_open(name1); fd2 = do_open(name2); while (1) { memset(buf1, 0, BUFFER); memset(buf2, 0, BUFFER); got1 = read(fd1, buf1, BUFFER); if (got1 < 0) { perror(name1); return 1; } got2 = read(fd2, buf2, BUFFER); if (got2 < 0) { perror(name2); return 1; } if (got1 != got2) fprintf(stderr, "%s < %s\n", got1 < got2 ? name1 : name2, got1 < got2 ? name2 : name1); len = got1 < got2 ? got1 : got2; if (!len) break; for (i = 0; i < len; i += bytes) { a = b = 0; switch (bytes) { case 4: a |= buf1[i+2] << 16; b |= buf2[i+2] << 16; a |= buf1[i+3] << 24; b |= buf2[i+3] << 24; /* fall through */ case 2: a |= buf1[i+1] << 8; b |= buf2[i+1] << 8; /* fall through */ case 1: a |= buf1[i]; b |= buf2[i]; break; default: abort(); } for (j = 0; j != 32; j++) if ((a ^ b) & (1 << j)) bin[j][(b >> j) & 1]++; } } for (j = 0; j != 8*bytes; j++) { if (little) i = j; else i = 8*(bytes-1-(j >> 3))+(j & 7); if (bin[i][0] || bin[i][1]) printf("%2d: %u %u\n", j, bin[i][0], bin[i][1]); } return 0; }