@@ -279,7 +279,8 @@ hunk_matches (unsigned long orig_offset, unsigned long orig_count,
279279}
280280
281281static int
282- do_unified (FILE * f , char * header [2 ], int match , char * * line ,
282+ do_unified (FILE * f , char * * header , unsigned int num_headers ,
283+ int match , char * * line ,
283284 size_t * linelen , unsigned long * linenum ,
284285 unsigned long start_linenum , char status ,
285286 const char * bestname , const char * patchname ,
@@ -390,10 +391,13 @@ do_unified (FILE *f, char *header[2], int match, char **line,
390391 if (!header_displayed &&
391392 mode != mode_grep ) {
392393 // Display the header.
394+ unsigned int i ;
395+ for (i = 0 ; i < num_headers - 2 ; i ++ )
396+ output_header_line (header [i ]);
393397 if (number_lines != After )
394- output_header_line (header [0 ]);
398+ output_header_line (header [num_headers - 2 ]);
395399 if (number_lines != Before )
396- output_header_line (header [1 ]);
400+ output_header_line (header [num_headers - 1 ]);
397401 header_displayed = 1 ;
398402 }
399403 switch (number_lines ) {
@@ -476,16 +480,16 @@ do_unified (FILE *f, char *header[2], int match, char **line,
476480 }
477481 } else {
478482 if (match_tmpf ) {
479- if (!header_displayed &&
480- number_lines != After )
481- output_header_line (header [0 ]);
482-
483- if (!header_displayed &&
484- number_lines != Before )
485- output_header_line (header [1 ]);
486-
487- if (!header_displayed )
483+ if (!header_displayed ) {
484+ unsigned int i ;
485+ for (i = 0 ; i < num_headers - 2 ; i ++ )
486+ output_header_line (header [i ]);
487+ if (number_lines != After )
488+ output_header_line (header [num_headers - 2 ]);
489+ if (number_lines != Before )
490+ output_header_line (header [num_headers - 1 ]);
488491 header_displayed = 1 ;
492+ }
489493
490494 rewind (match_tmpf );
491495 while (!feof (match_tmpf )) {
@@ -533,7 +537,8 @@ do_unified (FILE *f, char *header[2], int match, char **line,
533537}
534538
535539static int
536- do_context (FILE * f , char * header [2 ], int match , char * * line ,
540+ do_context (FILE * f , char * * header , unsigned int num_headers ,
541+ int match , char * * line ,
537542 size_t * linelen , unsigned long * linenum ,
538543 unsigned long start_linenum , char status ,
539544 const char * bestname , const char * patchname ,
@@ -687,10 +692,13 @@ do_context (FILE *f, char *header[2], int match, char **line,
687692
688693 // Display the line counts.
689694 if (!header_displayed && mode == mode_filter ) {
695+ unsigned int i ;
696+ for (i = 0 ; i < num_headers - 2 ; i ++ )
697+ output_header_line (header [i ]);
690698 if (number_lines != After )
691- output_header_line (header [0 ]);
699+ output_header_line (header [num_headers - 2 ]);
692700 if (number_lines != Before )
693- output_header_line (header [1 ]);
701+ output_header_line (header [num_headers - 1 ]);
694702 header_displayed = 1 ;
695703 }
696704
@@ -787,10 +795,13 @@ do_context (FILE *f, char *header[2], int match, char **line,
787795 }
788796 } else {
789797 if (!header_displayed ) {
798+ unsigned int i ;
799+ for (i = 0 ; i < num_headers - 2 ; i ++ )
800+ output_header_line (header [i ]);
790801 if (number_lines != After )
791- output_header_line (header [0 ]);
802+ output_header_line (header [num_headers - 2 ]);
792803 if (number_lines != Before )
793- output_header_line (header [1 ]);
804+ output_header_line (header [num_headers - 1 ]);
794805 header_displayed = 1 ;
795806 }
796807
@@ -899,11 +910,13 @@ do_context (FILE *f, char *header[2], int match, char **line,
899910 return ret ;
900911}
901912
913+ #define MAX_HEADERS 5
902914static int filterdiff (FILE * f , const char * patchname )
903915{
904916 static unsigned long linenum = 1 ;
905917 char * names [2 ];
906- char * header [2 ] = { NULL , NULL };
918+ char * header [MAX_HEADERS ] = { NULL , NULL };
919+ unsigned int num_headers = 0 ;
907920 char * line = NULL ;
908921 size_t linelen = 0 ;
909922 char * p ;
@@ -918,18 +931,22 @@ static int filterdiff (FILE *f, const char *patchname)
918931 char status = '!' ;
919932 unsigned long start_linenum ;
920933 int orig_file_exists , new_file_exists ;
921- int is_context = 0 ;
934+ int is_context = -1 ;
922935 int result ;
923- int (* do_diff ) (FILE * , char * [2 ], int , char * * , size_t * ,
936+ int (* do_diff ) (FILE * , char * * , unsigned int ,
937+ int , char * * , size_t * ,
924938 unsigned long * , unsigned long ,
925939 char , const char * , const char * ,
926940 int * , int * );
927941
928942 orig_file_exists = 0 ; // shut gcc up
929943
930- // Search for start of patch ("--- " for unified diff,
931- // "*** " for context).
944+ // Search for start of patch ("diff ", or " --- " for
945+ // unified diff, "*** " for context).
932946 for (;;) {
947+ if (!strncmp (line , "diff " , 5 ))
948+ break ;
949+
933950 if (!strncmp (line , "--- " , 4 )) {
934951 is_context = 0 ;
935952 break ;
@@ -953,6 +970,70 @@ static int filterdiff (FILE *f, const char *patchname)
953970
954971 start_linenum = linenum ;
955972 header [0 ] = xstrdup (line );
973+ num_headers = 1 ;
974+
975+ if (is_context == -1 ) {
976+ int valid_extended = 1 ;
977+ for (;;) {
978+ if (getline (& line , & linelen , f ) == -1 )
979+ goto eof ;
980+ linenum ++ ;
981+
982+ if (!strncmp (line , "diff " , 5 )) {
983+ header [num_headers ++ ] = xstrdup (line );
984+ break ;
985+ }
986+
987+ if (!strncmp (line , "--- " , 4 ))
988+ is_context = 0 ;
989+ else if (!strncmp (line , "*** " , 4 ))
990+ is_context = 1 ;
991+ else if (strncmp (line , "old mode " , 9 ) &&
992+ strncmp (line , "new mode " , 9 ) &&
993+ strncmp (line , "deleted file mode " , 18 ) &&
994+ strncmp (line , "new file mode " , 15 ) &&
995+ strncmp (line , "copy from " , 10 ) &&
996+ strncmp (line , "copy to " , 8 ) &&
997+ strncmp (line , "rename from " , 12 ) &&
998+ strncmp (line , "rename to " , 10 ) &&
999+ strncmp (line , "similarity index " , 17 ) &&
1000+ strncmp (line , "dissimilarity index " , 20 ) &&
1001+ strncmp (line , "index " , 6 ))
1002+ valid_extended = 0 ;
1003+
1004+ if (!valid_extended )
1005+ break ;
1006+
1007+ /* Drop excess header lines */
1008+ if (num_headers < MAX_HEADERS - 2 )
1009+ header [num_headers ++ ] = xstrdup (line );
1010+
1011+ if (is_context != -1 )
1012+ break ;
1013+ }
1014+
1015+ if (!valid_extended )
1016+ goto flush_continue ;
1017+ }
1018+
1019+ if (is_context == -1 ) {
1020+ /* We don't yet do anything with diffs with
1021+ * zero hunks. */
1022+ unsigned int i = 0 ;
1023+ flush_continue :
1024+ if (mode == mode_filter && (pat_exclude || verbose )
1025+ && !clean_comments ) {
1026+ for (i = 0 ; i < num_headers ; i ++ )
1027+ fputs (header [i ], stdout );
1028+ }
1029+ for (i = 0 ; i < num_headers ; i ++ ) {
1030+ free (header [i ]);
1031+ header [i ] = NULL ;
1032+ }
1033+ num_headers = 0 ;
1034+ continue ;
1035+ }
1036+
9561037 names [0 ] = filename_from_header (line + 4 );
9571038 if (mode != mode_filter && show_status )
9581039 orig_file_exists = file_exists (names [0 ], line + 4 +
@@ -972,17 +1053,12 @@ static int filterdiff (FILE *f, const char *patchname)
9721053 if (strncmp (line , is_context ? "--- " : "+++ " , 4 )) {
9731054 /* Show non-diff lines if excluding, or if
9741055 * in verbose mode, and if --clean isn't specified. */
975- if (mode == mode_filter && (pat_exclude || verbose )
976- && !clean_comments )
977- fputs (header [0 ], stdout );
9781056 free (names [0 ]);
979- free (header [0 ]);
980- header [0 ] = NULL ;
981- continue ;
1057+ goto flush_continue ;
9821058 }
9831059
9841060 filecount ++ ;
985- header [1 ] = xstrdup (line );
1061+ header [num_headers ++ ] = xstrdup (line );
9861062 names [1 ] = filename_from_header (line + 4 );
9871063
9881064 if (mode != mode_filter && show_status )
@@ -1007,7 +1083,8 @@ static int filterdiff (FILE *f, const char *patchname)
10071083 else
10081084 do_diff = do_unified ;
10091085
1010- result = do_diff (f , header , match , & line ,
1086+ result = do_diff (f , header , num_headers ,
1087+ match , & line ,
10111088 & linelen , & linenum ,
10121089 start_linenum , status , p , patchname ,
10131090 & orig_file_exists , & new_file_exists );
@@ -1033,15 +1110,17 @@ static int filterdiff (FILE *f, const char *patchname)
10331110 }
10341111
10351112 next_diff :
1036- for (i = 0 ; i < 2 ; i ++ ) {
1113+ for (i = 0 ; i < 2 ; i ++ )
10371114 free (names [i ]);
1115+ for (i = 0 ; i < num_headers ; i ++ ) {
10381116 free (header [i ]);
10391117 header [i ] = NULL ;
10401118 }
1119+ num_headers = 0 ;
10411120 }
10421121
10431122 eof :
1044- for (i = 0 ; i < 2 ; i ++ )
1123+ for (i = 0 ; i < num_headers ; i ++ )
10451124 if (header [i ])
10461125 free (header [i ]);
10471126
0 commit comments