diff: fix bug 613 (diff -ub segfaults)

function                                             old     new   delta
dump_unified_vec                                     435     457     +22
diff_main                                            855     860      +5
diffreg                                             1786    1781      -5
do_diff                                              428     416     -12
change                                               325     283     -42
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/3 up/down: 27/-59)            Total: -32 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/editors/diff.c b/editors/diff.c
index e3933e7..42aba9a 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -102,7 +102,7 @@
 	bool anychange;
 	smallint exit_status;
 	int opt_U_context;
-	size_t max_context;     /* size of context_vec_start */
+	int context_idx;
 	IF_FEATURE_DIFF_DIR(int dl_count;)
 	IF_FEATURE_DIFF_DIR(char **dl;)
 	char *opt_S_start;
@@ -119,9 +119,7 @@
 	long *ixold;            /* will be overlaid on klist */
 	struct line *nfile[2];
 	struct line *sfile[2];  /* shortened by pruning common prefix/suffix */
-	struct context_vec *context_vec_start;
-	struct context_vec *context_vec_end;
-	struct context_vec *context_vec_ptr;
+	struct context_vec *context_vector;
 	char *tempname1, *tempname2;
 	struct stat stb1, stb2;
 };
@@ -129,7 +127,7 @@
 #define anychange          (G.anychange         )
 #define exit_status        (G.exit_status       )
 #define opt_U_context      (G.opt_U_context     )
-#define max_context        (G.max_context       )
+#define context_idx        (G.context_idx       )
 #define dl_count           (G.dl_count          )
 #define dl                 (G.dl                )
 #define opt_S_start        (G.opt_S_start       )
@@ -147,9 +145,7 @@
 #define ixold              (G.ixold             )
 #define nfile              (G.nfile             )
 #define sfile              (G.sfile             )
-#define context_vec_start  (G.context_vec_start )
-#define context_vec_end    (G.context_vec_end   )
-#define context_vec_ptr    (G.context_vec_ptr   )
+#define context_vector     (G.context_vector    )
 #define stb1               (G.stb1              )
 #define stb2               (G.stb2              )
 #define tempname1          (G.tempname1         )
@@ -157,7 +153,7 @@
 #define INIT_G() do { \
 	SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
 	opt_U_context = 3; \
-	max_context = 64; \
+	context_vector = xrealloc_vector(context_vector, 6, 0); \
 } while (0)
 
 
@@ -230,11 +226,10 @@
 }
 static int readhash(FILE *fp)
 {
-	int i, t, space;
+	int i, t;
 	int sum;
 
 	sum = 1;
-	space = 0;
 	i = 0;
 	if (!(option_mask32 & (FLAG_b | FLAG_w))) {
 		while ((t = getc(fp)) != '\n') {
@@ -247,8 +242,11 @@
 			i = 1;
 		}
 	} else {
+		int space = 0;
+
 		while (1) {
-			switch (t = getc(fp)) {
+			t = getc(fp);
+			switch (t) {
 			case '\t':
 			case '\r':
 			case '\v':
@@ -763,19 +761,19 @@
 /* dump accumulated "unified" diff changes */
 static void dump_unified_vec(FILE *f1, FILE *f2)
 {
-	struct context_vec *cvp = context_vec_start;
+	struct context_vec *cvp = context_vector;
 	int lowa, upb, lowc, upd;
 	int a, b, c, d;
 	char ch;
 
-	if (context_vec_start > context_vec_ptr)
+	if (context_idx < 0)
 		return;
 
 	b = d = 0;			/* gcc */
 	lowa = MAX(1, cvp->a - opt_U_context);
-	upb = MIN(nlen[0], context_vec_ptr->b + opt_U_context);
+	upb = MIN(nlen[0], context_vector[context_idx].b + opt_U_context);
 	lowc = MAX(1, cvp->c - opt_U_context);
-	upd = MIN(nlen[1], context_vec_ptr->d + opt_U_context);
+	upd = MIN(nlen[1], context_vector[context_idx].d + opt_U_context);
 
 	printf("@@ -");
 	uni_range(lowa, upb);
@@ -787,7 +785,7 @@
 	 * Output changes in "unified" diff format--the old and new lines
 	 * are printed together.
 	 */
-	for (; cvp <= context_vec_ptr; cvp++) {
+	for (; cvp <= &context_vector[context_idx]; cvp++) {
 		a = cvp->a;
 		b = cvp->b;
 		c = cvp->c;
@@ -834,7 +832,7 @@
 	}
 	fetch(ixnew, d + 1, upd, f2, ' ');
 
-	context_vec_ptr = context_vec_start - 1;
+	context_idx = -1;
 }
 
 
@@ -866,25 +864,13 @@
 		return;
 	}
 
-	/*
-	 * Allocate change records as needed.
-	 */
-	if (context_vec_ptr == context_vec_end - 1) {
-		ptrdiff_t offset = context_vec_ptr - context_vec_start;
-
-		max_context <<= 1;
-		context_vec_start = xrealloc(context_vec_start,
-				max_context * sizeof(struct context_vec));
-		context_vec_end = context_vec_start + max_context;
-		context_vec_ptr = context_vec_start + offset;
-	}
 	if (anychange == 0) {
 		/*
 		 * Print the context/unidiff header first time through.
 		 */
 		print_header(file1, file2);
-	} else if (a > context_vec_ptr->b + (2 * opt_U_context) + 1
-	        && c > context_vec_ptr->d + (2 * opt_U_context) + 1
+	} else if (a > context_vector[context_idx].b + (2 * opt_U_context) + 1
+	        && c > context_vector[context_idx].d + (2 * opt_U_context) + 1
 	) {
 		/*
 		 * If this change is more than 'context' lines from the
@@ -893,11 +879,12 @@
 // dump_unified_vec() seeks!
 		dump_unified_vec(f1, f2);
 	}
-	context_vec_ptr++;
-	context_vec_ptr->a = a;
-	context_vec_ptr->b = b;
-	context_vec_ptr->c = c;
-	context_vec_ptr->d = d;
+	context_idx++;
+	context_vector = xrealloc_vector(context_vector, 6, context_idx);
+	context_vector[context_idx].a = a;
+	context_vector[context_idx].b = b;
+	context_vector[context_idx].c = c;
+	context_vector[context_idx].d = d;
 	anychange = 1;
 }
 
@@ -1010,7 +997,7 @@
 	int i;
 
 	anychange = 0;
-	context_vec_ptr = context_vec_start - 1;
+	context_idx = -1;
 	tempname1 = tempname2 = NULL;
 
 	/* Is any of them a directory? Then it's simple */