static int
readline(Biobuf *bp, char *buf)
{
int c;
char *p, *e;
p = buf;
e = p + MAXLINELEN-1;
do {
c = Bgetc(bp);
if (c < 0) {
if (p == buf)
return -1;
break;
}
if (c == '\n')
break;
*p++ = c;
} while (p < e);
*p = 0;
if (c != '\n' && c >= 0) {
do c = Bgetc(bp);
while (c >= 0 && c != '\n');
}
return p - buf;
}
/*
* hashing has the effect of
* arranging line in 7-bit bytes and then
* summing 1-s complement in 16-bit hunks
*/
static int
readhash(Biobuf *bp, char *buf)
{
long sum;
unsigned shift;
char *p;
int len, space;
sum = 1;
shift = 0;
if ((len = readline(bp, buf)) == -1)
return 0;
p = buf;
switch(bflag) /* various types of white space handling */
{
case 0:
while (len--) {
sum += (long)*p++ << (shift &= (HALFLONG-1));
shift += 7;
}
break;
case 1:
/*
* coalesce multiple white-space
*/
for (space = 0; len--; p++) {
if (isspace(*p)) {
space++;
continue;
}
if (space) {
shift += 7;
space = 0;
}
sum += (long)*p << (shift &= (HALFLONG-1));
shift += 7;
}
break;
default:
/*
* strip all white-space
*/
while (len--) {
if (isspace(*p)) {
p++;
continue;
}
sum += (long)*p++ << (shift &= (HALFLONG-1));
shift += 7;
}
break;
}
sum = low(sum) + high(sum);
return ((short)low(sum) + (short)high(sum));
}
Biobuf *
prepare(int i, char *arg)
{
struct line *p;
int j, h;
Biobuf *bp;
char *cp, buf[MAXLINELEN];
int nbytes;
Rune r;
bp = Bopen(arg, OREAD);
if (!bp) {
panic(mflag ? 0: 2, "cannot open %s: %r\n", arg);
return 0;
}
if (binary)
return bp;
nbytes = Bread(bp, buf, MIN(1024, MAXLINELEN));
if (nbytes > 0) {
cp = buf;
while (cp < buf+nbytes-UTFmax) {
/*
* heuristic for a binary file in the
* brave new UNICODE world
*/
cp += chartorune(&r, cp);
if (r == 0 || (r > 0x7f && r <= 0xa0)) {
binary++;
return bp;
}
}
Bseek(bp, 0, 0);
}
p = MALLOC(struct line, 3);
for (j = 0; h = readhash(bp, buf); p[j].value = h)
p = REALLOC(p, struct line, (++j+3));
len[i] = j;
file[i] = p;
input[i] = bp; /*fix*/
if (i == 0) { /*fix*/
file1 = arg;
firstchange = 0;
}
else
file2 = arg;
return bp;
}
static int
squishspace(char *buf)
{
char *p, *q;
int space;
for (space = 0, q = p = buf; *q; q++) {
if (isspace(*q)) {
space++;
continue;
}
if (space && bflag == 1) {
*p++ = ' ';
space = 0;
}
*p++ = *q;
}
*p = 0;
return p - buf;
}
/*
* need to fix up for unexpected EOF's
*/
void
check(Biobuf *bf, Biobuf *bt)
{
int f, t, flen, tlen;
char fbuf[MAXLINELEN], tbuf[MAXLINELEN];