In diff.c:882 we have in main():
exit_status = compare_files (&noparent, de_unknowns, argv[optind],
argv[optind + 1]);.
This function is defined in diff.c, starting at lines #1376 (comments) or #1387
(code). It has close to its end on line #1633/1634:
if (status == EXIT_SUCCESS)
status = compare_prepped_files (parent, &cmp, O_RDONLY | oflags);
compare_prepped_files() is new, compared to diffutils 3.10, and is also defined
in diff.c, lines #1158 (comments) or #1162 (code). It has at its end on line
#1372:
return diff_2_files (cmp);
This function is defined in analyze.c, starting at lines #451 (comments) or
#452 (code). It has inside a switch statement
621 switch (output_style)
622 {
623 case OUTPUT_CONTEXT:
624 print_context_script (script, false);
625 break;
626
627 case OUTPUT_UNIFIED:
628 print_context_script (script, true);
629 break;
So it's the print_context_script() branch of function calls that contains the
faulty code. It's defined in context.c, starting at lines #109 (comments) or
#111 (code). It makes a comparison between context and unified diff:
123 if (unidiff)
124 print_script (script, find_hunk, pr_unidiff_hunk);
125 else
126 print_script (script, find_hunk, pr_context_hunk);
The array script was created before, it is created in (almost?) any case:
context.c:124: print_script (script, find_hunk, pr_unidiff_hunk);
context.c:126: print_script (script, find_hunk, pr_context_hunk);
ed.c:33: print_script (script, find_change, print_ed_hunk);
ed.c:97: print_script (script, find_change, pr_forward_ed_hunk);
ed.c:136: print_script (script, find_change, print_rcs_hunk);
ifdef.c:54: print_script (script, find_change, print_ifdef_hunk);
normal.c:31: print_script (script, find_change, print_normal_hunk);
side.c:41: print_script (script, find_change, print_sdiff_hunk);
The function print_script() is defined in util.c, starting at lines #941
(comments) or #952 (code), find_hunk() and find_change() are functions
(find_change() is defined in util.c, find_hunk() is defined in context.c) and
presumingly OK (although I could see contradicting line numbers in output?).
The third argument of print_script() varies a bit in name (pr_ vs. print_),
they are defined in different files, each working on a particular diff case (ed
script, "normal", side-by-side, and context/unified). So it's possible that
pr_unidiff_hunk and pr_context_hunk can have the faulty code, twice?
find_hunk() has only one argument (struct change *script), works on its
contents and returns the finished struct. Rather negligible:
429 /* Scan a (forward-ordered) edit script for the first place that more
than
430 2*CONTEXT unchanged lines appear, and return a pointer
431 to the 'struct change' for the last change before those lines. */
432
433 static struct change * ATTRIBUTE_PURE
434 find_hunk (struct change *script)
435 {
436 /* Threshold distance is CONTEXT if the second change is ignorable,
437 min (2 * CONTEXT + 1, LIN_MAX) otherwise. */
438 lin ignorable_threshold = context;
439 lin non_ignorable_threshold = (ckd_mul (&non_ignorable_threshold,
context, 2)
440 ? LIN_MAX
441 : non_ignorable_threshold + 1);
442
443 for (struct change *next; ; script = next)
444 {
445 next = script->link;
446 /* Compute number of first line in each file beyond this changed.
*/
447 lin top0 = script->line0 + script->deleted;
448 lin top1 = script->line1 + script->inserted;
449 lin thresh = (next && next->ignore
450 ? ignorable_threshold
451 : non_ignorable_threshold);
452 /* It is not supposed to matter which file we check in the
end-test. */
453 dassert (!next || next->line0 - top0 == next->line1 - top1);
454
455 /* Keep going if less than THRESH lines elapse
456 before the affected line. */
457 if (!next || thresh <= next->line0 - top0)
458 return script;
459 }
460 }
pr_context_hunk()/pr_unidiff_hunk() make internal use of the curr struct,
change its contents, obviously not a file name or such. Instead they call
begin_output() – a function that is also used in the other diff cases… But it
has a special clause near its end:
886 /* A special header is needed at the beginning of context
output. */
887 if (output_style == OUTPUT_CONTEXT || output_style ==
OUTPUT_UNIFIED)
888 print_context_header (curr.file, names,
889 output_style == OUTPUT_UNIFIED);
Only in our two faulty cases, unified and context diff, the malfunction
happens. So 'print_context_header()' must contain the bug, but it's too simple,
in context.c:
92 /* Print a header for a context diff, with the file names and
dates. */
93
94 void
95 print_context_header (struct file_data inf[], char const *const
*names, bool unidiff)
96 {
97 if (unidiff)
98 {
99 print_context_label ("---", &inf[0], names[0],
file_label[0]);
100 print_context_label ("+++", &inf[1], names[1],
file_label[1]);
101 }
102 else
103 {
104 print_context_label ("***", &inf[0], names[0],
file_label[0]);
105 print_context_label ("---", &inf[1], names[1],
file_label[1]);
106 }
107 }
This function has the declaration 'char const *const *names', but definition of
'print_context_label()' starts with:
40 static void
41 print_context_label (char const *mark,
42 struct file_data *inf,
43 char const *name,
44 char const *label)
45 {
To me "char const *const *" is not the same as "char const *" – could be for
PPC Mac OS X 10.4.11 too? I do not understand these code differences anyway.
Comparing the function definition in both versions 3.12 and 3.10 I see that
time is handled differently – cause found? In the end both functions simply
have:
set_color_context (RESET_CONTEXT);
putc ('\n', outfile);
The newer version has
24 int nsec = ts.tv_nsec;
On Tiger /usr/include/time.h has:
87 #ifndef _TIMESPEC 88 #define _TIMESPEC
89 struct timespec {
90 time_t tv_sec; /* seconds */
91 long tv_nsec; /* and nanoseconds */
92 };
93 #endif
94
95 struct tm {
96 int tm_sec; /* seconds after the minute [0-60] */
97 int tm_min; /* minutes after the hour [0-59] */
98 int tm_hour; /* hours since midnight [0-23] */
99 int tm_mday; /* day of the month [1-31] */
100 int tm_mon; /* months since January [0-11] */
101 int tm_year; /* years since 1900 */
102 int tm_wday; /* days since Sunday [0-6] */
103 int tm_yday; /* days since January 1 [0-365] */
104 int tm_isdst; /* Daylight Savings Time flag */
105 long tm_gmtoff; /* offset from CUT in seconds */
106 char *tm_zone; /* timezone abbreviation */
107 };
nstrftime() is not known on Tiger, but defined in lib/strftime.h. I'll check
that area, either (much) later or tomorrow!
--
Greetings
Pete
We also sponsor National Invisible Chronic Illness Awareness Week annually in
September.
Join the millions!