+long xdl_bogosqrt(long n) {
+ long i;
+
+ /*
+ * Classical integer square root approximation using shifts.
+ */
+ for (i = 1; n > 0; n >>= 2)
+ i <<= 1;
+
+ return i;
+}
+
+
int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
xdemitcb_t *ecb) {
- mmbuffer_t mb[2];
+ int i = 2;
+ mmbuffer_t mb[3];
mb[0].ptr = (char *) pre;
mb[0].size = psize;
mb[1].ptr = (char *) rec;
mb[1].size = size;
-
- if (ecb->outf(ecb->priv, mb, 2) < 0) {
+ if (size > 0 && rec[size - 1] != '\n') {
+ mb[2].ptr = (char *) "\n\\ No newline at end of file\n";
+ mb[2].size = strlen(mb[2].ptr);
+ i++;
+ }
+ if (ecb->outf(ecb->priv, mb, i) < 0) {
return -1;
}
return nl + 1;
}
+int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
+{
+ int i1, i2;
+
+ if (!(flags & XDF_WHITESPACE_FLAGS))
+ return s1 == s2 && !memcmp(l1, l2, s1);
+
+ i1 = 0;
+ i2 = 0;
+
+ /*
+ * -w matches everything that matches with -b, and -b in turn
+ * matches everything that matches with --ignore-space-at-eol.
+ *
+ * Each flavor of ignoring needs different logic to skip whitespaces
+ * while we have both sides to compare.
+ */
+ if (flags & XDF_IGNORE_WHITESPACE) {
+ goto skip_ws;
+ while (i1 < s1 && i2 < s2) {
+ if (l1[i1++] != l2[i2++])
+ return 0;
+ skip_ws:
+ while (i1 < s1 && isspace(l1[i1]))
+ i1++;
+ while (i2 < s2 && isspace(l2[i2]))
+ i2++;
+ }
+ } else if (flags & XDF_IGNORE_WHITESPACE_CHANGE) {
+ while (i1 < s1 && i2 < s2) {
+ if (isspace(l1[i1]) && isspace(l2[i2])) {
+ /* Skip matching spaces and try again */
+ while (i1 < s1 && isspace(l1[i1]))
+ i1++;
+ while (i2 < s2 && isspace(l2[i2]))
+ i2++;
+ continue;
+ }
+ if (l1[i1++] != l2[i2++])
+ return 0;
+ }
+ } else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL) {
+ while (i1 < s1 && i2 < s2 && l1[i1++] == l2[i2++])
+ ; /* keep going */
+ }
+
+ /*
+ * After running out of one side, the remaining side must have
+ * nothing but whitespace for the lines to match. Note that
+ * ignore-whitespace-at-eol case may break out of the loop
+ * while there still are characters remaining on both lines.
+ */
+ if (i1 < s1) {
+ while (i1 < s1 && isspace(l1[i1]))
+ i1++;
+ if (s1 != i1)
+ return 0;
+ }
+ if (i2 < s2) {
+ while (i2 < s2 && isspace(l2[i2]))
+ i2++;
+ return (s2 == i2);
+ }
+ return 1;
+}
+
+static unsigned long xdl_hash_record_with_whitespace(char const **data,
+ char const *top, long flags) {
+ unsigned long ha = 5381;
+ char const *ptr = *data;
+
+ for (; ptr < top && *ptr != '\n'; ptr++) {
+ if (isspace(*ptr)) {
+ const char *ptr2 = ptr;
+ int at_eol;
+ while (ptr + 1 < top && isspace(ptr[1])
+ && ptr[1] != '\n')
+ ptr++;
+ at_eol = (top <= ptr + 1 || ptr[1] == '\n');
+ if (flags & XDF_IGNORE_WHITESPACE)
+ ; /* already handled */
+ else if (flags & XDF_IGNORE_WHITESPACE_CHANGE
+ && !at_eol) {
+ ha += (ha << 5);
+ ha ^= (unsigned long) ' ';
+ }
+ else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL
+ && !at_eol) {
+ while (ptr2 != ptr + 1) {
+ ha += (ha << 5);
+ ha ^= (unsigned long) *ptr2;
+ ptr2++;
+ }
+ }
+ continue;
+ }
+ ha += (ha << 5);
+ ha ^= (unsigned long) *ptr;
+ }
+ *data = ptr < top ? ptr + 1: ptr;
+
+ return ha;
+}
+
-unsigned long xdl_hash_record(char const **data, char const *top) {
+unsigned long xdl_hash_record(char const **data, char const *top, long flags) {
unsigned long ha = 5381;
char const *ptr = *data;
+ if (flags & XDF_WHITESPACE_FLAGS)
+ return xdl_hash_record_with_whitespace(data, top, flags);
+
for (; ptr < top && *ptr != '\n'; ptr++) {
ha += (ha << 5);
ha ^= (unsigned long) *ptr;
}
-int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, xdemitcb_t *ecb) {
+int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
+ const char *func, long funclen, xdemitcb_t *ecb) {
int nb = 0;
mmbuffer_t mb;
char buf[128];
memcpy(buf, "@@ -", 4);
nb += 4;
- nb += xdl_num_out(buf + nb, c1 ? s1: 0);
+ nb += xdl_num_out(buf + nb, c1 ? s1: s1 - 1);
- memcpy(buf + nb, ",", 1);
- nb += 1;
+ if (c1 != 1) {
+ memcpy(buf + nb, ",", 1);
+ nb += 1;
- nb += xdl_num_out(buf + nb, c1);
+ nb += xdl_num_out(buf + nb, c1);
+ }
memcpy(buf + nb, " +", 2);
nb += 2;
- nb += xdl_num_out(buf + nb, c2 ? s2: 0);
+ nb += xdl_num_out(buf + nb, c2 ? s2: s2 - 1);
- memcpy(buf + nb, ",", 1);
- nb += 1;
+ if (c2 != 1) {
+ memcpy(buf + nb, ",", 1);
+ nb += 1;
- nb += xdl_num_out(buf + nb, c2);
+ nb += xdl_num_out(buf + nb, c2);
+ }
- memcpy(buf + nb, " @@\n", 4);
- nb += 4;
+ memcpy(buf + nb, " @@", 3);
+ nb += 3;
+ if (func && funclen) {
+ buf[nb++] = ' ';
+ if (funclen > sizeof(buf) - nb - 1)
+ funclen = sizeof(buf) - nb - 1;
+ memcpy(buf + nb, func, funclen);
+ nb += funclen;
+ }
+ buf[nb++] = '\n';
mb.ptr = buf;
mb.size = nb;
return 0;
}
-