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!