wernermisc/bitcmp/bitcmp.c

130 lines
2.2 KiB
C

#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;
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;
}