2011-08-17 12:59:05 +03:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
|
|
|
|
#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;
|
2011-08-17 19:36:02 +03:00
|
|
|
uint32_t a, b;
|
2011-08-17 12:59:05 +03:00
|
|
|
int i, j;
|
2011-08-17 19:36:02 +03:00
|
|
|
static unsigned bin[32][2];
|
2011-08-17 12:59:05 +03:00
|
|
|
|
|
|
|
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;
|
2011-08-17 13:11:06 +03:00
|
|
|
for (i = 0; i < len; i += bytes) {
|
2011-08-17 19:36:02 +03:00
|
|
|
a = b = 0;
|
2011-08-17 12:59:05 +03:00
|
|
|
switch (bytes) {
|
|
|
|
case 4:
|
2011-08-17 19:36:02 +03:00
|
|
|
a |= buf1[i+2] << 16;
|
|
|
|
b |= buf2[i+2] << 16;
|
|
|
|
a |= buf1[i+3] << 24;
|
|
|
|
b |= buf2[i+3] << 24;
|
2011-08-17 12:59:05 +03:00
|
|
|
/* fall through */
|
|
|
|
case 2:
|
2011-08-17 19:36:02 +03:00
|
|
|
a |= buf1[i+1] << 8;
|
|
|
|
b |= buf2[i+1] << 8;
|
2011-08-17 12:59:05 +03:00
|
|
|
/* fall through */
|
|
|
|
case 1:
|
2011-08-17 19:36:02 +03:00
|
|
|
a |= buf1[i];
|
|
|
|
b |= buf2[i];
|
2011-08-17 12:59:05 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
for (j = 0; j != 32; j++)
|
2011-08-17 19:36:02 +03:00
|
|
|
if ((a ^ b) & (1 << j))
|
|
|
|
bin[j][(b >> j) & 1]++;
|
2011-08-17 12:59:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j != 8*bytes; j++) {
|
|
|
|
if (little)
|
|
|
|
i = j;
|
|
|
|
else
|
|
|
|
i = 8*(bytes-1-(j >> 3))+(j & 7);
|
2011-08-17 19:36:02 +03:00
|
|
|
if (bin[i][0] || bin[i][1])
|
|
|
|
printf("%2d: %u %u\n", j, bin[i][0], bin[i][1]);
|
2011-08-17 12:59:05 +03:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|