eggert@twinsun.com (Paul Eggert) (11/11/89)
We evaluated a test copy of Saber C by trying it out on GNU DIFF 1.10, and found a few bugs. We delinted DIFF first so that Saber C could focus on runtime errors. Here are many lint fixes and some runtime fixes to GNU DIFF 1.10. Patches are relative to a previous bug report that sped up GNU DIFF 1.10. The runtime fixes are: shift_boundaries() referenced one past the end of files[f].equivs when end==i_end. Interchanging the order of tests fixed the problem (analyze.c:517 below). diff_2_files() did a free(script) followed by a return script?1:0; ANSI C doesn't let a program examine a pointer to freed storage. (analyze.c:816 below). line_cmp() referred to uninitialized storage when going one past the end of the input file. (fix in io.c:122 below). find_equiv_class(n) referred to current->linbuf[n] even when n < current->prefix_lines, causing a reference to uninitialized storage. (fixes near io.c:499 below). The lint fixes are: Adding procedure declarations. Removing code and variables that were never used. In particular: Many routines took a struct file_data * parameter and never used it. The regex code permits obscure syntax, but this is never used. Casting ...alloc() size arguments to unsigned. Adding "" arguments to message routines. 'preceeding' -> 'preceding' =================================================================== RCS file: RCS/analyze.c,v retrieving revision 1.1 diff -c -r1.1 analyze.c *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:13 1989 --- analyze.c Thu Nov 9 22:00:31 1989 *************** *** 23,28 **** --- 23,38 ---- #include "diff.h" + void finish_output (); + void pr_forward_ed_script (); + void print_context_header (); + void print_context_script (); + void print_ed_script (); + void print_ifdef_script (); + void print_normal_script (); + void print_rcs_script (); + void setup_output (); + extern int no_discards; static int *xvec, *yvec; /* Vectors being compared. */ *************** *** 248,259 **** files[0].changed_flag[files[0].realindexes[xoff++]] = 1; else { ! int c, d, f, b; /* Find a point of correspondence in the middle of the files. */ d = diag (xoff, xlim, yoff, ylim, &c); - f = fdiag[d]; b = bdiag[d]; if (c == 1) --- 258,268 ---- files[0].changed_flag[files[0].realindexes[xoff++]] = 1; else { ! int c, d, b; /* Find a point of correspondence in the middle of the files. */ d = diag (xoff, xlim, yoff, ylim, &c); b = bdiag[d]; if (c == 1) *************** *** 276,285 **** { /* Use that point to split this problem into two subproblems. */ compareseq (xoff, b, yoff, b - d); - /* This used to use f instead of b, - but that is incorrect! - It is not necessarily the case that diagonal d - has a snake from b to f. */ compareseq (b, xlim, b - d, ylim); } } --- 285,290 ---- *************** *** 301,307 **** discard_confusing_lines (filevec) struct file_data filevec[]; { ! int f, i, j, k; char *discarded[2]; int *equiv_count[2]; --- 306,312 ---- discard_confusing_lines (filevec) struct file_data filevec[]; { ! int f, i; char *discarded[2]; int *equiv_count[2]; *************** *** 329,336 **** /* Set up tables of which lines are going to be discarded. */ ! discarded[0] = (char *) xmalloc (filevec[0].buffered_lines); ! discarded[1] = (char *) xmalloc (filevec[1].buffered_lines); bzero (discarded[0], filevec[0].buffered_lines); bzero (discarded[1], filevec[1].buffered_lines); --- 334,341 ---- /* Set up tables of which lines are going to be discarded. */ ! discarded[0] = (char *) xmalloc ((unsigned) filevec[0].buffered_lines); ! discarded[1] = (char *) xmalloc ((unsigned) filevec[1].buffered_lines); bzero (discarded[0], filevec[0].buffered_lines); bzero (discarded[1], filevec[1].buffered_lines); *************** *** 421,427 **** { char *discards = discarded[f]; int end = filevec[f].buffered_lines; ! j = 0; for (i = 0; i < end; ++i) if (no_discards || discards[i] == 0) { --- 426,432 ---- { char *discards = discarded[f]; int end = filevec[f].buffered_lines; ! int j = 0; for (i = 0; i < end; ++i) if (no_discards || discards[i] == 0) { *************** *** 468,476 **** int i = 0; int j = 0; int i_end = filevec[f].buffered_lines; ! int j_end = filevec[1-f].buffered_lines; ! int preceeding = -1; ! int other_preceeding = -1; while (1) { --- 473,480 ---- int i = 0; int j = 0; int i_end = filevec[f].buffered_lines; ! int preceding = -1; ! int other_preceding = -1; while (1) { *************** *** 483,490 **** { while (other_changed[j++]) /* Non-corresponding lines in the other file ! will count as the preceeding batch of changes. */ ! other_preceeding = j; i++; } --- 487,494 ---- { while (other_changed[j++]) /* Non-corresponding lines in the other file ! will count as the preceding batch of changes. */ ! other_preceding = j; i++; } *************** *** 510,521 **** /* You might ask, how could this run follow right after another? Only because the previous run was shifted here. */ ! if (files[f].equivs[start] == files[f].equivs[end] && !other_changed[j] ! && end != i_end ! && !((preceeding >= 0 && start == preceeding) ! || (other_preceeding >= 0 ! && other_start == other_preceeding))) { changed[end++] = 1; changed[start++] = 0; --- 514,525 ---- /* You might ask, how could this run follow right after another? Only because the previous run was shifted here. */ ! if (end != i_end ! && files[f].equivs[start] == files[f].equivs[end] && !other_changed[j] ! && !((preceding >= 0 && start == preceding) ! || (other_preceding >= 0 ! && other_start == other_preceding))) { changed[end++] = 1; changed[start++] = 0; *************** *** 529,536 **** break; } ! preceeding = i; ! other_preceeding = j; } } } --- 533,540 ---- break; } ! preceding = i; ! other_preceding = j; } } } *************** *** 686,694 **** && output_style != OUTPUT_RCS) { if (filevec[0].missing_newline) ! message ("No newline at end of file %s\n", filevec[0].name); if (filevec[1].missing_newline) ! message ("No newline at end of file %s\n", filevec[1].name); } /* Allocate vectors for the results of comparison: --- 690,698 ---- && output_style != OUTPUT_RCS) { if (filevec[0].missing_newline) ! message ("No newline at end of file %s\n", filevec[0].name, ""); if (filevec[1].missing_newline) ! message ("No newline at end of file %s\n", filevec[1].name, ""); } /* Allocate vectors for the results of comparison: *************** *** 696,703 **** is an insertion or deletion. Allocate an extra element, always zero, at each end of each vector. */ ! filevec[0].changed_flag = (char *) xmalloc (filevec[0].buffered_lines + 2); ! filevec[1].changed_flag = (char *) xmalloc (filevec[1].buffered_lines + 2); bzero (filevec[0].changed_flag, filevec[0].buffered_lines + 2); bzero (filevec[1].changed_flag, filevec[1].buffered_lines + 2); filevec[0].changed_flag++; --- 700,707 ---- is an insertion or deletion. Allocate an extra element, always zero, at each end of each vector. */ ! filevec[0].changed_flag = (char *) xmalloc ((unsigned)filevec[0].buffered_lines + 2); ! filevec[1].changed_flag = (char *) xmalloc ((unsigned)filevec[1].buffered_lines + 2); bzero (filevec[0].changed_flag, filevec[0].buffered_lines + 2); bzero (filevec[1].changed_flag, filevec[1].buffered_lines + 2); filevec[0].changed_flag++; *************** *** 799,804 **** --- 803,811 ---- free (filevec[i].linbuf); } + if (!script) + return 0; + for (e = script; e; e = p) { p = e->link; *************** *** 805,809 **** free (e); } ! return script ? 1 : 0; } --- 812,816 ---- free (e); } ! return 1; } =================================================================== RCS file: RCS/context.c,v retrieving revision 1.1 diff -c -r1.1 context.c *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:13 1989 --- context.c Thu Nov 9 21:43:40 1989 *************** *** 20,29 **** #include "diff.h" #include "regex.h" static void pr_context_hunk (); static struct change *find_hunk (); static void mark_ignorable (); ! static int find_function (); /* Last place find_function started searching from. */ static int find_function_last_search; --- 20,31 ---- #include "diff.h" #include "regex.h" + void translate_range (); + static void pr_context_hunk (); static struct change *find_hunk (); static void mark_ignorable (); ! static void find_function (); /* Last place find_function started searching from. */ static int find_function_last_search; *************** *** 64,70 **** print_script (script, find_hunk, pr_context_hunk); } ! /* Print a pair of line numbers with a comma, translated for file FILE. If the second number is smaller, use the first in place of it. Args A and B are internal line numbers. --- 66,72 ---- print_script (script, find_hunk, pr_context_hunk); } ! /* Print a pair of line numbers with a comma. If the second number is smaller, use the first in place of it. Args A and B are internal line numbers. *************** *** 71,82 **** We print the translated (real) line numbers. */ static void ! print_context_number_range (file, a, b) ! struct file_data *file; int a, b; { int trans_a, trans_b; ! translate_range (file, a, b, &trans_a, &trans_b); /* Note: we can have B < A in the case of a range of no lines. In this case, we should print the line number before the range, --- 73,83 ---- We print the translated (real) line numbers. */ static void ! print_context_number_range (a, b) int a, b; { int trans_a, trans_b; ! translate_range (a, b, &trans_a, &trans_b); /* Note: we can have B < A in the case of a range of no lines. In this case, we should print the line number before the range, *************** *** 101,107 **** int first0, last0, first1, last1, show_from, show_to, i; struct change *next; char *prefix; - int lastline; char *function; int function_length; --- 102,107 ---- *************** *** 122,128 **** /* If desired, find the preceding function definition line in file 0. */ function = 0; if (function_regexp) ! find_function (&files[0], first0, &function, &function_length); /* If we looked for and found a function this is part of, include its name in the header of the diff section. */ --- 122,128 ---- /* If desired, find the preceding function definition line in file 0. */ function = 0; if (function_regexp) ! find_function (first0, &function, &function_length); /* If we looked for and found a function this is part of, include its name in the header of the diff section. */ *************** *** 135,141 **** } fprintf (outfile, "\n*** "); ! print_context_number_range (&files[0], first0, last0); fprintf (outfile, " ****\n"); if (show_from) --- 135,141 ---- } fprintf (outfile, "\n*** "); ! print_context_number_range (first0, last0); fprintf (outfile, " ****\n"); if (show_from) *************** *** 164,170 **** } fprintf (outfile, "--- "); ! print_context_number_range (&files[1], first1, last1); fprintf (outfile, " ----\n"); if (show_to) --- 164,170 ---- } fprintf (outfile, "--- "); ! print_context_number_range (first1, last1); fprintf (outfile, " ----\n"); if (show_to) *************** *** 258,272 **** } } ! /* Find the last function-header line in FILE prior to line number LINENUM. This is a line containing a match for the regexp in `function_regexp'. Store the address of the line text into LINEP and the length of the line into LENP. Do not store anything if no function-header is found. */ ! static int ! find_function (file, linenum, linep, lenp) ! struct file_data *file; int linenum; char **linep; int *lenp; --- 258,271 ---- } } ! /* Find the last function-header line prior to line number LINENUM. This is a line containing a match for the regexp in `function_regexp'. Store the address of the line text into LINEP and the length of the line into LENP. Do not store anything if no function-header is found. */ ! static void ! find_function (linenum, linep, lenp) int linenum; char **linep; int *lenp; *************** *** 288,294 **** *linep = files[0].linbuf[i].text; *lenp = files[0].linbuf[i].length; find_function_last_match = i; ! return 1; } } /* If we search back to where we started searching the previous time, --- 287,293 ---- *linep = files[0].linbuf[i].text; *lenp = files[0].linbuf[i].length; find_function_last_match = i; ! return; } } /* If we search back to where we started searching the previous time, *************** *** 298,304 **** i = find_function_last_match; *linep = files[0].linbuf[i].text; *lenp = files[0].linbuf[i].length; - return 1; } - return 0; } --- 297,301 ---- =================================================================== RCS file: RCS/diff.c,v retrieving revision 1.2 diff -c -r1.2 diff.c *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:14 1989 --- diff.c Thu Nov 9 21:40:50 1989 *************** *** 48,54 **** int count; { int i; ! int length = 0; char *result; for (i = 0; i < count; i++) --- 48,54 ---- int count; { int i; ! unsigned length = 0; char *result; for (i = 0; i < count; i++) *************** *** 300,307 **** val = re_compile_pattern (ignore_regexp, strlen (ignore_regexp), &ignore_regexp_compiled); if (val != 0) ! error ("-I option: ", val); ! ignore_regexp_compiled.fastmap = (char *) xmalloc (256); } if (function_regexp) --- 300,307 ---- val = re_compile_pattern (ignore_regexp, strlen (ignore_regexp), &ignore_regexp_compiled); if (val != 0) ! error ("-I option: ", "", ""); ! ignore_regexp_compiled.fastmap = (char *) xmalloc ((unsigned)256); } if (function_regexp) *************** *** 311,318 **** val = re_compile_pattern (function_regexp, strlen (function_regexp), &function_regexp_compiled); if (val != 0) ! error ("-F option: ", val); ! function_regexp_compiled.fastmap = (char *) xmalloc (256); } if (output_style != OUTPUT_CONTEXT) --- 311,318 ---- val = re_compile_pattern (function_regexp, strlen (function_regexp), &function_regexp_compiled); if (val != 0) ! error ("-F option: ", "", ""); ! function_regexp_compiled.fastmap = (char *) xmalloc ((unsigned)256); } if (output_style != OUTPUT_CONTEXT) *************** *** 323,329 **** switch_string = option_list (argv + 1, optind - 1); ! val = compare_files (0, argv[optind], 0, argv[optind + 1], 0); /* Print any messages that were saved up for last. */ print_message_queue (); --- 323,329 ---- switch_string = option_list (argv + 1, optind - 1); ! val = compare_files ((char *)0, argv[optind], (char *)0, argv[optind + 1], 0); /* Print any messages that were saved up for last. */ print_message_queue (); *************** *** 345,351 **** { if (output_style != OUTPUT_NORMAL && output_style != style) ! error ("conflicting specifications of output style"); output_style = style; } --- 345,351 ---- { if (output_style != OUTPUT_NORMAL && output_style != style) ! error ("conflicting specifications of output style", "", ""); output_style = style; } =================================================================== RCS file: RCS/diff.h,v retrieving revision 1.1 diff -c -r1.1 diff.h *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:15 1989 --- diff.h Thu Nov 9 21:23:55 1989 *************** *** 321,331 **** void *xmalloc (); void *xrealloc (); - void *xcalloc(); char *concat (); void free (); char *rindex (); char *index (); void message (); void print_message_queue (); --- 321,337 ---- void *xmalloc (); void *xrealloc (); char *concat (); void free (); char *rindex (); char *index (); + void analyze_hunk (); + void error (); + void fatal (); void message (); + void perror_with_name (); + void pfatal_with_name (); + void print_1_line (); void print_message_queue (); + void print_script (); =================================================================== RCS file: RCS/dir.c,v retrieving revision 1.1 diff -c -r1.1 dir.c *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:15 1989 --- dir.c Thu Nov 9 21:47:29 1989 *************** *** 39,45 **** register DIR *reading; register struct direct *next; struct dirdata dirdata; - int compare_names (); /* Address of block containing the files that are described. */ char **files; --- 39,44 ---- =================================================================== RCS file: RCS/ed.c,v retrieving revision 1.1 diff -c -r1.1 ed.c *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:16 1989 --- ed.c Thu Nov 9 21:21:01 1989 *************** *** 22,28 **** static void print_rcs_hunk (); static void print_ed_hunk (); static void pr_forward_ed_hunk (); ! static void print_range_length (); void translate_range (); struct change *find_change (); struct change *find_reverse_change (); --- 22,28 ---- static void print_rcs_hunk (); static void print_ed_hunk (); static void pr_forward_ed_hunk (); ! void print_number_range (); void translate_range (); struct change *find_change (); struct change *find_reverse_change (); *************** *** 58,64 **** return; /* Print out the line number header for this hunk */ ! print_number_range (',', &files[0], f0, l0); fprintf (outfile, "%c\n", change_letter (inserts, deletes)); /* Print new/changed lines from second file, if needed */ --- 58,64 ---- return; /* Print out the line number header for this hunk */ ! print_number_range (',', f0, l0); fprintf (outfile, "%c\n", change_letter (inserts, deletes)); /* Print new/changed lines from second file, if needed */ *************** *** 71,77 **** /* Resume the insert, if we stopped. */ if (! inserting) fprintf (outfile, "%da\n", ! i - f1 + translate_line_number (&files[0], f0) - 1); inserting = 1; /* If the file's line is just a dot, it would confuse `ed'. --- 71,77 ---- /* Resume the insert, if we stopped. */ if (! inserting) fprintf (outfile, "%da\n", ! i - f1 + translate_line_number (f0) - 1); inserting = 1; /* If the file's line is just a dot, it would confuse `ed'. *************** *** 86,92 **** fprintf (outfile, ".\n"); /* Now change that double dot to the desired single dot. */ fprintf (outfile, "%ds/^\\.\\././\n", ! i - f1 + translate_line_number (&files[0], f0)); inserting = 0; } else --- 86,92 ---- fprintf (outfile, ".\n"); /* Now change that double dot to the desired single dot. */ fprintf (outfile, "%ds/^\\.\\././\n", ! i - f1 + translate_line_number (f0)); inserting = 0; } else *************** *** 125,131 **** return; fprintf (outfile, "%c", change_letter (inserts, deletes)); ! print_number_range (' ', files, f0, l0); fprintf (outfile, "\n"); /* If deletion only, print just the number range. */ --- 125,131 ---- return; fprintf (outfile, "%c", change_letter (inserts, deletes)); ! print_number_range (' ', f0, l0); fprintf (outfile, "\n"); /* If deletion only, print just the number range. */ *************** *** 169,175 **** if (!deletes && !inserts) return; ! translate_range (&files[0], f0, l0, &tf0, &tl0); if (deletes) { --- 169,175 ---- if (!deletes && !inserts) return; ! translate_range (f0, l0, &tf0, &tl0); if (deletes) { *************** *** 186,192 **** fprintf (outfile, "a"); /* Take last-line-number from file 0 and # lines from file 1. */ ! translate_range (&files[1], f1, l1, &tf1, &tl1); fprintf (outfile, "%d %d\n", tl0, (tl1 >= tf1 ? tl1 - tf1 + 1 : 1)); --- 186,192 ---- fprintf (outfile, "a"); /* Take last-line-number from file 0 and # lines from file 1. */ ! translate_range (f1, l1, &tf1, &tl1); fprintf (outfile, "%d %d\n", tl0, (tl1 >= tf1 ? tl1 - tf1 + 1 : 1)); =================================================================== RCS file: RCS/io.c,v retrieving revision 1.1 diff -c -r1.1 io.c *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:17 1989 --- io.c Thu Nov 9 22:43:22 1989 *************** *** 69,75 **** else if ((current->stat.st_mode & S_IFMT) == S_IFREG) { current->bufsize = current->stat.st_size; ! current->buffer = (char *) xmalloc (current->bufsize + 2); current->buffered_chars = read (current->desc, current->buffer, current->bufsize); if (current->buffered_chars < 0) --- 69,75 ---- else if ((current->stat.st_mode & S_IFMT) == S_IFREG) { current->bufsize = current->stat.st_size; ! current->buffer = (char *) xmalloc ((unsigned)current->bufsize + 2); current->buffered_chars = read (current->desc, current->buffer, current->bufsize); if (current->buffered_chars < 0) *************** *** 80,86 **** int cc; current->bufsize = 4096; ! current->buffer = (char *) xmalloc (current->bufsize + 2); current->buffered_chars = 0; /* Not a regular file; read it in a little at a time, growing the --- 80,86 ---- int cc; current->bufsize = 4096; ! current->buffer = (char *) xmalloc ((unsigned)current->bufsize + 2); current->buffered_chars = 0; /* Not a regular file; read it in a little at a time, growing the *************** *** 95,101 **** { current->bufsize = current->bufsize * 2; current->buffer = (char *) xrealloc (current->buffer, ! current->bufsize + 2); } } if (cc < 0) --- 95,101 ---- { current->bufsize = current->bufsize * 2; current->buffer = (char *) xrealloc (current->buffer, ! (unsigned)current->bufsize + 2); } } if (cc < 0) *************** *** 119,124 **** --- 119,127 ---- else current->missing_newline = 0; + /* Don't use uninitialized storage. */ + current->buffer[current->buffered_chars] = '\0'; + return 0; } *************** *** 487,494 **** find_equiv_class (n) int n; { ! int bucket = current->linbuf[n].hash % nbuckets; ! struct equivclass *b = buckets[bucket], *p = NULL; /* Equivalence class 0 is permanently allocated to lines that were not hashed because they were parts of identical prefixes or --- 490,497 ---- find_equiv_class (n) int n; { ! int bucket; ! struct equivclass *b, *p = NULL; /* Equivalence class 0 is permanently allocated to lines that were not hashed because they were parts of identical prefixes or *************** *** 497,506 **** || current->linbuf[n].text >= current->suffix_begin) return 0; /* Check through the appropriate bucket to see if there isn't already an equivalence class for this line. */ ! while (b) ! { if (b->line.hash == current->linbuf[n].hash && (b->line.length == current->linbuf[n].length /* Lines of different lengths can match with certain options. */ --- 500,510 ---- || current->linbuf[n].text >= current->suffix_begin) return 0; + bucket = current->linbuf[n].hash % nbuckets; + /* Check through the appropriate bucket to see if there isn't already an equivalence class for this line. */ ! for (b = buckets[bucket]; b; p = b, b = b->next) if (b->line.hash == current->linbuf[n].hash && (b->line.length == current->linbuf[n].length /* Lines of different lengths can match with certain options. */ *************** *** 507,514 **** || length_varies) && !line_cmp (&b->line, ¤t->linbuf[n])) return b - equivs; - p = b, b = b->next; - } /* Create a new equivalence class in this bucket. */ --- 511,516 ---- *************** *** 529,535 **** struct file_data filevec[]; { int i, j; - struct equivclass *b, *f; int binary = 0; int this_binary; --- 531,536 ---- =================================================================== RCS file: RCS/normal.c,v retrieving revision 1.1 diff -c -r1.1 normal.c *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:18 1989 --- normal.c Thu Nov 9 20:36:56 1989 *************** *** 51,59 **** return; /* Print out the line number header for this hunk */ ! print_number_range (',', &files[0], first0, last0); fprintf (outfile, "%c", change_letter (inserts, deletes)); ! print_number_range (',', &files[1], first1, last1); fprintf (outfile, "\n"); /* Print the lines that the first file has. */ --- 51,59 ---- return; /* Print out the line number header for this hunk */ ! print_number_range (',', first0, last0); fprintf (outfile, "%c", change_letter (inserts, deletes)); ! print_number_range (',', first1, last1); fprintf (outfile, "\n"); /* Print the lines that the first file has. */ =================================================================== RCS file: RCS/regex.c,v retrieving revision 1.1 diff -c -r1.1 regex.c *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:18 1989 --- regex.c Thu Nov 9 21:44:02 1989 *************** *** 53,58 **** --- 53,61 ---- #ifdef sparc #include <alloca.h> #endif + + void *malloc(); + void *realloc(); #endif /* *************** *** 117,122 **** --- 120,130 ---- #define SIGN_EXTEND_CHAR(x) (x) #endif + #ifdef diff + #define obscurable 0 + #else + #define obscurable 1 + static int obscure_syntax = 0; /* Specify the precise syntax of regexp for compilation. *************** *** 135,140 **** --- 143,149 ---- obscure_syntax = syntax; return ret; } + #endif /* re_compile_pattern takes a regular-expression string and converts it into a buffer full of byte commands for matching. *************** *** 280,285 **** --- 289,295 ---- switch (c) { case '$': + #if obscurable if (obscure_syntax & RE_TIGHT_VBAR) { if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p != pend) *************** *** 291,307 **** PATPUSH (endline); break; } /* $ means succeed if at end of line, but only in special contexts. If randomly in the middle of a pattern, it is a normal character. */ if (p == pend || *p == '\n' ! || (obscure_syntax & RE_CONTEXT_INDEP_OPS) || (obscure_syntax & RE_NO_BK_PARENS ? *p == ')' ! : *p == '\\' && p[1] == ')') ! || (obscure_syntax & RE_NO_BK_VBAR ? *p == '|' ! : *p == '\\' && p[1] == '|')) { PATPUSH (endline); break; --- 301,326 ---- PATPUSH (endline); break; } + #endif /* $ means succeed if at end of line, but only in special contexts. If randomly in the middle of a pattern, it is a normal character. */ if (p == pend || *p == '\n' ! || ( ! #if obscurable ! obscure_syntax & RE_CONTEXT_INDEP_OPS) || (obscure_syntax & RE_NO_BK_PARENS ? *p == ')' ! : ! #endif ! *p == '\\' && p[1] == ')') ! || ( ! #if obscurable ! obscure_syntax & RE_NO_BK_VBAR ? *p == '|' ! : ! #endif ! *p == '\\' && p[1] == '|')) { PATPUSH (endline); break; *************** *** 312,319 **** /* ^ means succeed if at beg of line, but only if no preceding pattern. */ if (laststart && p[-2] != '\n' ! && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) goto normal_char; if (obscure_syntax & RE_TIGHT_VBAR) { if (p != pattern + 1 --- 331,342 ---- /* ^ means succeed if at beg of line, but only if no preceding pattern. */ if (laststart && p[-2] != '\n' ! #if obscurable ! && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS) ! #endif ! ) goto normal_char; + #if obscurable if (obscure_syntax & RE_TIGHT_VBAR) { if (p != pattern + 1 *************** *** 323,339 **** begalt = b; } else PATPUSH (begline); break; case '+': case '?': if (obscure_syntax & RE_BK_PLUS_QM) goto normal_char; handle_plus: case '*': /* If there is no previous pattern, char not special. */ ! if (!laststart && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) goto normal_char; /* If there is a sequence of repetition chars, collapse it down to equivalent to just one. */ --- 346,369 ---- begalt = b; } else + #endif PATPUSH (begline); break; case '+': case '?': + #if obscurable if (obscure_syntax & RE_BK_PLUS_QM) goto normal_char; handle_plus: + #endif case '*': /* If there is no previous pattern, char not special. */ ! if (!laststart ! #if obscurable ! && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS) ! #endif ! ) goto normal_char; /* If there is a sequence of repetition chars, collapse it down to equivalent to just one. */ *************** *** 348,356 **** PATFETCH (c); if (c == '*') ; ! else if (!(obscure_syntax & RE_BK_PLUS_QM) ! && (c == '+' || c == '?')) ; else if ((obscure_syntax & RE_BK_PLUS_QM) && c == '\\') { --- 378,391 ---- PATFETCH (c); if (c == '*') ; ! else if ( ! #if obscurable ! !(obscure_syntax & RE_BK_PLUS_QM) ! && ! #endif ! (c == '+' || c == '?')) ; + #if obscurable else if ((obscure_syntax & RE_BK_PLUS_QM) && c == '\\') { *************** *** 364,369 **** --- 399,405 ---- } c = c1; } + #endif else { PATUNFETCH; *************** *** 423,428 **** --- 459,465 ---- { PATFETCH (c); + #if obscurable /* If awk, \ escapes characters when inside [...]. */ if ((obscure_syntax & RE_AWK_CLASS_HACK) && c == '\\') { *************** *** 430,435 **** --- 467,473 ---- b[c1 / BYTEWIDTH] |= 1 << (c1 % BYTEWIDTH); continue; } + #endif if (c == ']' && p != p1 + 1) break; if (*p == '-' && p[1] != ']') *************** *** 452,479 **** break; case '(': ! if (! (obscure_syntax & RE_NO_BK_PARENS)) ! goto normal_char; ! else goto handle_open; case ')': ! if (! (obscure_syntax & RE_NO_BK_PARENS)) ! goto normal_char; ! else goto handle_close; case '\n': ! if (! (obscure_syntax & RE_NEWLINE_OR)) ! goto normal_char; ! else goto handle_bar; case '|': ! if (! (obscure_syntax & RE_NO_BK_VBAR)) ! goto normal_char; ! else goto handle_bar; case '\\': if (p == pend) goto invalid_pattern; --- 490,525 ---- break; case '(': ! #if obscurable ! if (obscure_syntax & RE_NO_BK_PARENS) goto handle_open; + else + #endif + goto normal_char; case ')': ! #if obscurable ! if (obscure_syntax & RE_NO_BK_PARENS) goto handle_close; + else + #endif + goto normal_char; case '\n': ! #if obscurable ! if (obscure_syntax & RE_NEWLINE_OR) goto handle_bar; + else + #endif + goto normal_char; case '|': ! #if obscurable ! if (obscure_syntax & RE_NO_BK_VBAR) goto handle_bar; + else + #endif + goto normal_char; case '\\': if (p == pend) goto invalid_pattern; *************** *** 481,489 **** --- 527,537 ---- switch (c) { case '(': + #if obscurable if (obscure_syntax & RE_NO_BK_PARENS) goto normal_backsl; handle_open: + #endif if (stackp == stacke) goto nesting_too_deep; if (regnum < RE_NREGS) { *************** *** 500,508 **** --- 548,558 ---- break; case ')': + #if obscurable if (obscure_syntax & RE_NO_BK_PARENS) goto normal_backsl; handle_close: + #endif if (stackp == stackb) goto unmatched_close; begalt = *--stackp + bufp->buffer; if (fixup_jump) *************** *** 520,528 **** --- 570,580 ---- break; case '|': + #if obscurable if (obscure_syntax & RE_NO_BK_VBAR) goto normal_backsl; handle_bar: + #endif insert_jump (on_failure_jump, begalt, b + 6, b); pending_exact = 0; b += 3; *************** *** 608,620 **** PATPUSH (c1); break; case '+': case '?': if (obscure_syntax & RE_BK_PLUS_QM) goto handle_plus; - default: normal_backsl: /* You might think it would be useful for \ to mean not to translate; but if we don't translate it it will never match anything. */ --- 660,675 ---- PATPUSH (c1); break; + #if obscurable case '+': case '?': if (obscure_syntax & RE_BK_PLUS_QM) goto handle_plus; normal_backsl: + #endif + + default: /* You might think it would be useful for \ to mean not to translate; but if we don't translate it it will never match anything. */ *************** *** 627,635 **** normal_char: if (!pending_exact || pending_exact + *pending_exact + 1 != b || *pending_exact == 0177 || *p == '*' || *p == '^' ! || ((obscure_syntax & RE_BK_PLUS_QM) ? *p == '\\' && (p[1] == '+' || p[1] == '?') ! : (*p == '+' || *p == '?'))) { laststart = b; PATPUSH (exactn); --- 682,694 ---- normal_char: if (!pending_exact || pending_exact + *pending_exact + 1 != b || *pending_exact == 0177 || *p == '*' || *p == '^' ! || ( ! #if obscurable ! (obscure_syntax & RE_BK_PLUS_QM) ? *p == '\\' && (p[1] == '+' || p[1] == '?') ! : ! #endif ! (*p == '+' || *p == '?'))) { laststart = b; PATPUSH (exactn); *************** *** 677,683 **** static int store_jump (from, opcode, to) char *from, *to; ! char opcode; { from[0] = opcode; from[1] = (to - (from + 3)) & 0377; --- 736,742 ---- static int store_jump (from, opcode, to) char *from, *to; ! enum regexpcode opcode; { from[0] = opcode; from[1] = (to - (from + 3)) & 0377; *************** *** 693,699 **** static int insert_jump (op, from, to, current_end) ! char op; char *from, *to, *current_end; { register char *pto = current_end + 3; --- 752,758 ---- static int insert_jump (op, from, to, current_end) ! enum regexpcode op; char *from, *to, *current_end; { register char *pto = current_end + 3; *************** *** 717,727 **** struct re_pattern_buffer *bufp; { unsigned char *pattern = (unsigned char *) bufp->buffer; - int size = bufp->used; register char *fastmap = bufp->fastmap; register unsigned char *p = pattern; ! register unsigned char *pend = pattern + size; ! register int j, k; unsigned char *translate = (unsigned char *) bufp->translate; unsigned char *stackb[NFAILURES]; --- 776,785 ---- struct re_pattern_buffer *bufp; { unsigned char *pattern = (unsigned char *) bufp->buffer; register char *fastmap = bufp->fastmap; register unsigned char *p = pattern; ! register unsigned char *pend = pattern + bufp->used; ! register int j; unsigned char *translate = (unsigned char *) bufp->translate; unsigned char *stackb[NFAILURES]; *************** *** 900,906 **** int size, startpos, range; struct re_registers *regs; { ! return re_search_2 (pbufp, 0, 0, string, size, startpos, range, regs, size); } /* Like re_match_2 but tries first a match starting at index STARTPOS, --- 958,964 ---- int size, startpos, range; struct re_registers *regs; { ! return re_search_2 (pbufp, (char *)0, 0, string, size, startpos, range, regs, size); } /* Like re_match_2 but tries first a match starting at index STARTPOS, *************** *** 1012,1018 **** return -1; } ! #ifndef emacs /* emacs never uses this */ int re_match (pbufp, string, size, pos, regs) struct re_pattern_buffer *pbufp; --- 1070,1076 ---- return -1; } ! #if !defined (emacs) && !defined (diff) int re_match (pbufp, string, size, pos, regs) struct re_pattern_buffer *pbufp; *************** *** 1572,1578 **** /* Entry points compatible with bsd4.2 regex library */ ! #ifndef emacs static struct re_pattern_buffer re_comp_buf; --- 1630,1636 ---- /* Entry points compatible with bsd4.2 regex library */ ! #if !defined (emacs) && !defined (diff) static struct re_pattern_buffer re_comp_buf; =================================================================== RCS file: RCS/regex.h,v retrieving revision 1.1 diff -c -r1.1 regex.h *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:19 1989 --- regex.h Thu Nov 9 21:23:35 1989 *************** *** 183,189 **** /* Is this really advertised? */ extern void re_compile_fastmap (); extern int re_search (), re_search_2 (); ! extern int re_match (), re_match_2 (); /* 4.2 bsd compatibility (yuck) */ extern char *re_comp (); --- 183,192 ---- /* Is this really advertised? */ extern void re_compile_fastmap (); extern int re_search (), re_search_2 (); ! #ifndef diff ! extern int re_match (); ! #endif ! extern int re_match_2 (); /* 4.2 bsd compatibility (yuck) */ extern char *re_comp (); =================================================================== RCS file: RCS/util.c,v retrieving revision 1.2 diff -c -r1.2 util.c *** /tmp/,RCSt1a21584 Fri Nov 10 11:48:20 1989 --- util.c Thu Nov 9 21:41:06 1989 *************** *** 19,24 **** --- 19,26 ---- #include "diff.h" + void perror (); + /* Use when a system call returns non-zero status. TEXT should normally be the file name. */ *************** *** 65,71 **** char *text; { print_message_queue (); ! error ("%s", text); exit (2); } --- 67,73 ---- char *text; { print_message_queue (); ! error ("%s", text, ""); exit (2); } *************** *** 448,454 **** /* Translate an internal line number (an index into diff's table of lines) into an actual line number in the input file. ! The internal line number is LNUM. FILE points to the data on the file. Internal line numbers count from 0 within the current chunk. Actual line numbers count from 1 within the entire file; --- 450,456 ---- /* Translate an internal line number (an index into diff's table of lines) into an actual line number in the input file. ! The internal line number is LNUM. Internal line numbers count from 0 within the current chunk. Actual line numbers count from 1 within the entire file; *************** *** 457,464 **** The `ltran' feature is no longer in use. */ int ! translate_line_number (file, lnum) ! struct file_data *file; int lnum; { return lnum + 1; --- 459,465 ---- The `ltran' feature is no longer in use. */ int ! translate_line_number (lnum) int lnum; { return lnum + 1; *************** *** 465,480 **** } void ! translate_range (file, a, b, aptr, bptr) ! struct file_data *file; int a, b; int *aptr, *bptr; { ! *aptr = translate_line_number (file, a - 1) + 1; ! *bptr = translate_line_number (file, b + 1) - 1; } ! /* Print a pair of line numbers with SEPCHAR, translated for file FILE. If the two numbers are identical, print just one number. Args A and B are internal line numbers. --- 466,480 ---- } void ! translate_range (a, b, aptr, bptr) int a, b; int *aptr, *bptr; { ! *aptr = translate_line_number (a - 1) + 1; ! *bptr = translate_line_number (b + 1) - 1; } ! /* Print a pair of line numbers with SEPCHAR. If the two numbers are identical, print just one number. Args A and B are internal line numbers. *************** *** 481,493 **** We print the translated (real) line numbers. */ void ! print_number_range (sepchar, file, a, b) char sepchar; - struct file_data *file; int a, b; { int trans_a, trans_b; ! translate_range (file, a, b, &trans_a, &trans_b); /* Note: we can have B < A in the case of a range of no lines. In this case, we should print the line number before the range, --- 481,492 ---- We print the translated (real) line numbers. */ void ! print_number_range (sepchar, a, b) char sepchar; int a, b; { int trans_a, trans_b; ! translate_range (a, b, &trans_a, &trans_b); /* Note: we can have B < A in the case of a range of no lines. In this case, we should print the line number before the range, *************** *** 540,546 **** || 0 > re_search (&ignore_regexp_compiled, files[0].linbuf[i].text, files[0].linbuf[i].length, 0, ! files[0].linbuf[i].length, 0))) nontrivial = 1; for (i = next->line1; i <= l1 && ! nontrivial; i++) --- 539,545 ---- || 0 > re_search (&ignore_regexp_compiled, files[0].linbuf[i].text, files[0].linbuf[i].length, 0, ! files[0].linbuf[i].length, (struct re_registers *)0))) nontrivial = 1; for (i = next->line1; i <= l1 && ! nontrivial; i++) *************** *** 549,555 **** || 0 > re_search (&ignore_regexp_compiled, files[1].linbuf[i].text, files[1].linbuf[i].length, 0, ! files[1].linbuf[i].length, 0))) nontrivial = 1; } --- 548,554 ---- || 0 > re_search (&ignore_regexp_compiled, files[1].linbuf[i].text, files[1].linbuf[i].length, 0, ! files[1].linbuf[i].length, (struct re_registers *)0))) nontrivial = 1; } *************** *** 574,580 **** xmalloc (size) unsigned size; { ! register void *value = (void *) malloc (size); if (!value) fatal ("virtual memory exhausted"); --- 573,580 ---- xmalloc (size) unsigned size; { ! extern void *malloc(); ! register void *value = malloc (size); if (!value) fatal ("virtual memory exhausted"); *************** *** 588,594 **** void *old; unsigned int size; { ! register void *value = (void *) realloc (old, size); if (!value) fatal ("virtual memory exhausted"); --- 588,595 ---- void *old; unsigned int size; { ! extern void *realloc(); ! register void *value = realloc (old, size); if (!value) fatal ("virtual memory exhausted"); *************** *** 595,611 **** return value; } - void * - xcalloc (nitems, size) - int nitems, size; - { - void *value = (void *) calloc (nitems, size); - - if (! value) - fatal ("virtual memory exhausted"); - return value; - } - /* Concatenate three strings, returning a newly malloc'd string. */ char * --- 596,601 ---- *************** *** 612,618 **** concat (s1, s2, s3) char *s1, *s2, *s3; { ! int len = strlen (s1) + strlen (s2) + strlen (s3); char *new = (char *) xmalloc (len + 1); strcpy (new, s1); strcat (new, s2); --- 602,608 ---- concat (s1, s2, s3) char *s1, *s2, *s3; { ! unsigned len = strlen (s1) + strlen (s2) + strlen (s3); char *new = (char *) xmalloc (len + 1); strcpy (new, s1); strcat (new, s2); *************** *** 620,625 **** --- 610,616 ---- return new; } + #ifdef DEBUG debug_script (sp) struct change *sp; { *************** *** 629,631 **** --- 620,623 ---- sp->line0, sp->line1, sp->deleted, sp->inserted); fflush (stderr); } + #endif