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!




Reply via email to