11#include "cache.h"
22#include "grep.h"
3+ #include "userdiff.h"
34#include "xdiff-interface.h"
45
56void append_header_grep_pattern (struct grep_opt * opt , enum grep_header_field field , const char * pat )
@@ -490,6 +491,17 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
490491{
491492 int rest = eol - bol ;
492493
494+ if (opt -> pre_context || opt -> post_context ) {
495+ if (opt -> last_shown == 0 ) {
496+ if (opt -> show_hunk_mark )
497+ fputs ("--\n" , stdout );
498+ else
499+ opt -> show_hunk_mark = 1 ;
500+ } else if (lno > opt -> last_shown + 1 )
501+ fputs ("--\n" , stdout );
502+ }
503+ opt -> last_shown = lno ;
504+
493505 if (opt -> null_following_name )
494506 sign = '\0' ;
495507 if (opt -> pathname )
@@ -520,22 +532,95 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
520532 printf ("%.*s\n" , rest , bol );
521533}
522534
535+ static int match_funcname (struct grep_opt * opt , char * bol , char * eol )
536+ {
537+ xdemitconf_t * xecfg = opt -> priv ;
538+ if (xecfg && xecfg -> find_func ) {
539+ char buf [1 ];
540+ return xecfg -> find_func (bol , eol - bol , buf , 1 ,
541+ xecfg -> find_func_priv ) >= 0 ;
542+ }
543+
544+ if (bol == eol )
545+ return 0 ;
546+ if (isalpha (* bol ) || * bol == '_' || * bol == '$' )
547+ return 1 ;
548+ return 0 ;
549+ }
550+
551+ static void show_funcname_line (struct grep_opt * opt , const char * name ,
552+ char * buf , char * bol , unsigned lno )
553+ {
554+ while (bol > buf ) {
555+ char * eol = -- bol ;
556+
557+ while (bol > buf && bol [-1 ] != '\n' )
558+ bol -- ;
559+ lno -- ;
560+
561+ if (lno <= opt -> last_shown )
562+ break ;
563+
564+ if (match_funcname (opt , bol , eol )) {
565+ show_line (opt , bol , eol , name , lno , '=' );
566+ break ;
567+ }
568+ }
569+ }
570+
571+ static void show_pre_context (struct grep_opt * opt , const char * name , char * buf ,
572+ char * bol , unsigned lno )
573+ {
574+ unsigned cur = lno , from = 1 , funcname_lno = 0 ;
575+ int funcname_needed = opt -> funcname ;
576+
577+ if (opt -> pre_context < lno )
578+ from = lno - opt -> pre_context ;
579+ if (from <= opt -> last_shown )
580+ from = opt -> last_shown + 1 ;
581+
582+ /* Rewind. */
583+ while (bol > buf && cur > from ) {
584+ char * eol = -- bol ;
585+
586+ while (bol > buf && bol [-1 ] != '\n' )
587+ bol -- ;
588+ cur -- ;
589+ if (funcname_needed && match_funcname (opt , bol , eol )) {
590+ funcname_lno = cur ;
591+ funcname_needed = 0 ;
592+ }
593+ }
594+
595+ /* We need to look even further back to find a function signature. */
596+ if (opt -> funcname && funcname_needed )
597+ show_funcname_line (opt , name , buf , bol , cur );
598+
599+ /* Back forward. */
600+ while (cur < lno ) {
601+ char * eol = bol , sign = (cur == funcname_lno ) ? '=' : '-' ;
602+
603+ while (* eol != '\n' )
604+ eol ++ ;
605+ show_line (opt , bol , eol , name , cur , sign );
606+ bol = eol + 1 ;
607+ cur ++ ;
608+ }
609+ }
610+
523611static int grep_buffer_1 (struct grep_opt * opt , const char * name ,
524612 char * buf , unsigned long size , int collect_hits )
525613{
526614 char * bol = buf ;
527615 unsigned long left = size ;
528616 unsigned lno = 1 ;
529- struct pre_context_line {
530- char * bol ;
531- char * eol ;
532- } * prev = NULL , * pcl ;
533617 unsigned last_hit = 0 ;
534- unsigned last_shown = 0 ;
535618 int binary_match_only = 0 ;
536- const char * hunk_mark = "" ;
537619 unsigned count = 0 ;
538620 enum grep_context ctx = GREP_CONTEXT_HEAD ;
621+ xdemitconf_t xecfg ;
622+
623+ opt -> last_shown = 0 ;
539624
540625 if (buffer_is_binary (buf , size )) {
541626 switch (opt -> binary ) {
@@ -550,10 +635,16 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
550635 }
551636 }
552637
553- if (opt -> pre_context )
554- prev = xcalloc (opt -> pre_context , sizeof (* prev ));
555- if (opt -> pre_context || opt -> post_context )
556- hunk_mark = "--\n" ;
638+ memset (& xecfg , 0 , sizeof (xecfg ));
639+ if (opt -> funcname && !opt -> unmatch_name_only && !opt -> status_only &&
640+ !opt -> name_only && !binary_match_only && !collect_hits ) {
641+ struct userdiff_driver * drv = userdiff_find_by_path (name );
642+ if (drv && drv -> funcname .pattern ) {
643+ const struct userdiff_funcname * pe = & drv -> funcname ;
644+ xdiff_set_find_func (& xecfg , pe -> pattern , pe -> cflags );
645+ opt -> priv = & xecfg ;
646+ }
647+ }
557648
558649 while (left ) {
559650 char * eol , ch ;
@@ -601,45 +692,20 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
601692 * the context which is nonsense, but the user
602693 * deserves to get that ;-).
603694 */
604- if (opt -> pre_context ) {
605- unsigned from ;
606- if (opt -> pre_context < lno )
607- from = lno - opt -> pre_context ;
608- else
609- from = 1 ;
610- if (from <= last_shown )
611- from = last_shown + 1 ;
612- if (last_shown && from != last_shown + 1 )
613- fputs (hunk_mark , stdout );
614- while (from < lno ) {
615- pcl = & prev [lno - from - 1 ];
616- show_line (opt , pcl -> bol , pcl -> eol ,
617- name , from , '-' );
618- from ++ ;
619- }
620- last_shown = lno - 1 ;
621- }
622- if (last_shown && lno != last_shown + 1 )
623- fputs (hunk_mark , stdout );
695+ if (opt -> pre_context )
696+ show_pre_context (opt , name , buf , bol , lno );
697+ else if (opt -> funcname )
698+ show_funcname_line (opt , name , buf , bol , lno );
624699 if (!opt -> count )
625700 show_line (opt , bol , eol , name , lno , ':' );
626- last_shown = last_hit = lno ;
701+ last_hit = lno ;
627702 }
628703 else if (last_hit &&
629704 lno <= last_hit + opt -> post_context ) {
630705 /* If the last hit is within the post context,
631706 * we need to show this line.
632707 */
633- if (last_shown && lno != last_shown + 1 )
634- fputs (hunk_mark , stdout );
635708 show_line (opt , bol , eol , name , lno , '-' );
636- last_shown = lno ;
637- }
638- if (opt -> pre_context ) {
639- memmove (prev + 1 , prev ,
640- (opt -> pre_context - 1 ) * sizeof (* prev ));
641- prev -> bol = bol ;
642- prev -> eol = eol ;
643709 }
644710
645711 next_line :
@@ -650,7 +716,6 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
650716 lno ++ ;
651717 }
652718
653- free (prev );
654719 if (collect_hits )
655720 return 0 ;
656721
@@ -662,6 +727,9 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
662727 return 1 ;
663728 }
664729
730+ xdiff_clear_find_func (& xecfg );
731+ opt -> priv = NULL ;
732+
665733 /* NEEDSWORK:
666734 * The real "grep -c foo *.c" gives many "bar.c:0" lines,
667735 * which feels mostly useless but sometimes useful. Maybe
0 commit comments