summaryrefslogblamecommitdiffstats
path: root/bin/grepc
blob: 6c24765d4622b509370a3eb943fae1cd9a2a76b2 (plain) (tree)
1
2
3
4
5
6
7
8
9
         

 
           
         
              
          
         
         
           


            




                          

             
           
                


                 

 

             
                                                            




                 
                                         
                              


                                  



                                    


                                  


                                    
                  
                                  

                                    







                                             














                                                           





                                              


                                            











                                                  






                                            


                                      





                                        
                            
 
                             



                                


                             
                         
           
 

 
                  
 
                                   
                                    
            
                                    
            
                             
                                            


 
              
 
                   

                                          
                
                                                                




                                                    


 
                     
 
                      

                                
                                                                                                                  


 
                  
 
                      
                       
               
                                                                                                                              


 
                
 
                      
                       
               
                                                                                                                                 


 











                                              
                                
 
                      
                                                 
               
                                                             


 
                              
 
                      
                                   
               
                                                          


 
                  
 
                                            
                                          


 
            
 
                              
                            
                              
                              


 
                  

                      
                               
               
                                                            


 
                    

                      
                                   
               
                                                                  




             
                              
                                


 
                              
 
                      
                                                               
               
                                                                                                                                           


 
                           
 
                      
                              
                   
                                                


 
                                      
 
                      
                                                          
                                            
                                                                                                                                                   


 




                              
                                                                   


 
                    
 
                                       
                                                  
                                     


 
            
 
                                          
                                


 




                      
                                                                                                              


 




                      
                                                                                                                                                    







                                  
                                                                        




















                                              
                                                                                            


 




                                
                                                                                                                                                                         







                               
                                                       







                                                     
                                                                                                                                                     










                                                 

           
                            

                             
                            


 
                      
 

                                 
                         



                        



                                          





                                                 
















                                                                            






                                               

                                             












                                                           
                   



           
      
 

                                            
                             
                                                 
                                    





                                  


 
          
#!/bin/sh


# Defaults:
git='no';
ext='\.[ch]$';
FILES='.';
iflag='';
lflag='';
kflag='no';
tflag='no';
t_enum='no';
t_func='no';
t_func_proto='no';
t_func_def='no';
t_func_syscall='no';
t_func_syscall_proto='no';
t_func_syscall_def='no';
t_macro='no';
t_type='no';
t_use='no';
t_use_enum='no';
t_use_func='no';
t_use_macro='no';
t_use_type='no';


grepc_usage()
{
	echo "Usage: $0 [OPTION ...] IDENTIFIER [FILE ...]";
}


grepc_parse_cmd()
{
	while getopts "ghiklt:x:" opt; do
		case "$opt" in
		g)
			git='yes';
			;;
		h)
			grepc_usage;
			exit 0;
			;;
		i)
			iflag='i';
			;;
		k)
			kflag='yes';
			;;
		l)
			lflag='l';
			kflag='yes';
			;;
		t)
			case "$OPTARG" in
			e)
				t_enum='yes';
				;;
			f)
				t_func='yes';
				;;
			fp)
				t_func_proto='yes';
				;;
			fd)
				t_func_def='yes';
				;;
			fs)
				t_func_syscall='yes';
				;;
			fsp)
				t_func_syscall_proto='yes';
				;;
			fsd)
				t_func_syscall_def='yes';
				;;
			m)
				t_macro='yes';
				;;
			t)
				t_type='yes';
				;;
			u)
				t_use='yes';
				;;
			ue)
				t_use_enum='yes';
				;;
			uf)
				t_use_func='yes';
				;;
			um)
				t_use_macro='yes';
				;;
			ut)
				t_use_type='yes';
				;;
			*)
				grepc_usage;
				exit 1;
				;;
			esac;
			tflag='yes';
			;;
		x)
			ext="$OPTARG";
			;;
		?)
			grepc_usage >&2;
			exit 1;
			;;
		esac;
	done;
	shift $((OPTIND-1));

	if [ $# -lt 1 ]; then
		grepc_usage >&2;
		exit 1;
	fi;
	identifier=$1;
	shift;

	if [ $# -gt 0 ]; then
		FILES=$*;
	fi;
}


grepc_find_files()
{
	if [ "$git" = 'yes' ]; then
		git ls-files $FILES;
	else
		find $FILES -type f;
	fi \
	| grep -P -- "$ext" \
	| xargs grep -${iflag}lPI -- "$1\b";
}


grepc_helper()
{
	<"$files" \
	xargs grep -${iflag}lPI -- "$1" \
	| xargs grep -${iflag}lP -- "$2" \
	| sort \
	| xargs pcregrep -${iflag}${lflag}Mn -- "$3" /dev/null \
	| if [ "$kflag" = 'no' ]; then
		sed -E 's/^[^: ]+:[0-9]+:/\n\n&\n/';
	else
		cat;
	fi;
}


grepc_enum_constant()
{
	grepc_helper \
	  '\benum\b' \
	  "^[ \t]*$1\b\s*[,=]" \
	  '(?s)^([\w[]+[\w\s]*)?\benum\b[ \t]*([\w \t[\]]|::)*\n*([ \t]*){[^}]*^[ \t]*'"$1"'\b\s*[=,].*?^\3}.*?;';
}


grepc_func_proto()
{
	grepc_helper \
	  "\b$1\s*\(" \
	  '.' \
	  '(?s)^[\w[]([\w\s\(,\)[\]*]|::)+[\w\s\)*\]]\s+\**'"$1"'\s*\(([\w\s\(,\)[\]*]|::)+?(\.\.\.)?\)([\w\s\(,\)[\]]|::)*;';
}


grepc_func_def()
{
	grepc_helper \
	  "\b$1\s*\(" \
	  '.' \
	  '(?s)^[\w[]([\w\s\(,\)[\]*]|::)*[\w\s\)*\]]\s+\**'"$1"'\s*\(([\w\s\(,\)[\]*]|::)+?(\.\.\.)?\)[ \t]*\n([ \t]*){.*?^\4}';
}


grepc_glibc_func_math()
{
	grepc_func_def "M_DECL_FUNC \(__$1\)";
}


grepc_glibc_func()
{
	grepc_glibc_func_math "$1";
}


grepc_linux_func_syscall_proto()
{
	grepc_helper \
	  "^asmlinkage\s+[\w\s]+\**sys_$1\s*\(" \
	  '.' \
	  '(?s)^asmlinkage\s+[\w\s]+\**'"sys_$1"'\s*\(.*?\)';
}


grepc_linux_func_syscall_def()
{
	grepc_helper \
	  "SYSCALL_DEFINE.\($1\b" \
	  '.' \
	  '(?s)^(COMPAT_)?SYSCALL_DEFINE.\('"$1"'\b.*?^}';
}


grepc_linux_func()
{
	grepc_linux_func_syscall_proto "$1";
	grepc_linux_func_syscall_def "$1";
}


grepc_func()
{
	grepc_func_proto "$1";
	grepc_func_def "$1";
	grepc_glibc_func "$1";
	grepc_linux_func "$1";
}


grepc_macro_func()
{
	grepc_helper \
	  "#\s*define\s+$1\(" \
	  '.' \
	  '(?s)^[ \t]*#\s*define\s[\s\\]*'"$1"'\(.*?[^\\]$';
}


grepc_macro_object()
{
	grepc_helper \
	  "#\s*define\s+$1\b[^(]" \
	  '.' \
	  '(?s)^[ \t]*#\s*define\s[\s\\]*'"$1"'\b(?!\().*?[^\\]$';
}


grepc_macro()
{
	grepc_macro_func "$1";
	grepc_macro_object "$1";
}


grepc_type_struct_union_enum()
{
	grepc_helper \
	  '\b(struct|union|enum)\b([\w \t[\]]|::)+\b'"$1"'\b' \
	  '.' \
	  '(?s)^([\w[]([\w\s\(,\)[\]*]|::)*[\w\s\)*\]]\s+)?\b(struct|union|enum)\b([\w \t[\]]|::)+\b'"$1"'\b[ \t]*\n*([ \t]*){.*?^\5}.*?;';
}


grepc_type_typedef_simple()
{
	grepc_helper \
	  '^[ \t]*typedef\s' \
	  "\b$1;" \
	  '(?s)^[ \t]*typedef\s+[^{};]+'"$1"';';
}


grepc_type_typedef_struct_union_enum()
{
	grepc_helper \
	  '^[ \t]*typedef\s+(struct|union|enum)\b[^;]*$' \
	  "^[ \t]*}\s*$1(\[[\w\(,\)]\])*;" \
	  '(?s)^[ \t]*typedef\s+(struct|union|enum)\b(?:(?!\W'"$1"'\W)([\w \t[\]]|::))*\n*([ \t]*){(?:(?!^\3?}).)*?^\3}\s*'"$1"'(\[[\w\(,\)]\])*;';
}


grepc_type_typedef_func()
{
	grepc_helper \
	  '^[ \t]*typedef\s' \
	  "\(\**$1\)\s*\(" \
	  '(?s)^[ \t]*typedef\s+[^{};]+\(\**'"$1"'\)\s*\([^{};]+;';
}


grepc_type_typedef()
{
	grepc_type_typedef_simple "$1";
	grepc_type_typedef_struct_union_enum "$1";
	grepc_type_typedef_func "$1";
}


grepc_type()
{
	grepc_type_struct_union_enum "$1";
	grepc_type_typedef "$1";
}


grepc_use_enum()
{
	grepc_helper \
	  '\benum\b' \
	  "\b$1\b" \
	  '(?s)^([\w[]+[\w\s]*)?\benum\b([\w \t[\]]|::)*\n*([ \t]*){[^}]*^\s*\w+[\w\s[\]=]*'"$1"'.*?^\3}.*?;';
}


grepc_use_func_def()
{
	grepc_helper \
	  "\b$1\b" \
	  '.' \
	  '(?s)^[\w[]([\w\s\(,\)[\]*]|::)*[\w\s\)*\]]\s+\**\w+\s*\(([\w\s\(,\)[\]*]|::)+?(\.\.\.)?\)[ \t]*\n*([ \t]*){(?:(?!^\4?}).)*'"$1"'.*?^\4}';
}


grepc_linux_use_func_syscall_def()
{
	grepc_helper \
	  "SYSCALL_DEFINE.\(" \
	  "\b$1\b" \
	  '(?s)^(COMPAT_)?SYSCALL_DEFINE.\(\w+\b(?:(?!^}).)*'"$1"'.?^}';
}


grepc_linux_use_func()
{
	grepc_linux_use_func_syscall_def "$1";
}


grepc_use_func()
{
	grepc_use_func_def "$1";
	grepc_linux_use_func "$1";
}


grepc_use_macro()
{
	grepc_helper \
	  "\b$1\b" \
	  'define' \
	  '(?s)^[ \t]*#\s*define\s[\s\\]*\w+\b(\([^\)]*\))?(?:(?![^\\]$).)*'"$1"'.*?[^\\]$';
}


grepc_use_type_struct_union()
{
	grepc_helper \
	  "\b(struct|union)\b" \
	  "\b$1\b" \
	  '(?s)^(?!^[ \t]*typedef\b)([\w[]([\w\s\(,\)[\]*]|::)*[\w\s\)*\]]\s+)?\b(struct|union)\b([\w \t[\]]|::)*\w+[ \t]*\n*([ \t]*){(?:(?!^\5?}).)*?'"$1"'.*?^\5}.*?;';
}


grepc_use_type_typedef_simple()
{
	grepc_helper \
	  '^[ \t]*typedef\s' \
	  "\b$1\b" \
	  '(?s)^[ \t]*typedef\s+[^{};]*'"$1"'[^{};]+;';
}


grepc_use_type_typedef_struct_union()
{
	grepc_helper \
	  '^[ \t]*typedef\s+(struct|union)\b[^;]*$' \
	  "\b$1\b" \
	  '(?s)^[ \t]*typedef\s+(struct|union)\b([\w \t[\]]|::)*\n*([ \t]*){(?:(?!^\3?}|^\s*typedef).)*'"$1"'(?:(?!^\3?}|^\s*typedef).)*^\3}\s*\w+;';
}


grepc_use_type()
{
	grepc_use_type_struct_union "$1";
	grepc_use_type_typedef_simple "$1";
	grepc_use_type_typedef_struct_union "$1";
}


grepc_use()
{
	grepc_use_enum "$1";
	grepc_use_func "$1";
	grepc_use_macro "$1";
	grepc_use_type "$1";
}


grepc_search_default()
{
	grepc_enum_constant "$1";
	grepc_func "$1";
	grepc_macro "$1";
	grepc_type "$1";
}


grepc_search()
{
	if [ "$tflag" = 'no' ]; then
		grepc_search_default "$1";
	else
		if [ "$t_enum" = 'yes' ]; then
			grepc_enum_constant "$1";
		fi;
		if [ "$t_func" = 'yes' ]; then
			grepc_func "$1";
		else
			if [ "$t_func_proto" = 'yes' ]; then
				grepc_func_proto "$1";
			fi;
			if [ "$t_func_def" = 'yes' ]; then
				grepc_func_def "$1";
			fi;
			if [ "$t_func_syscall" = 'yes' ]; then
				grepc_linux_func "$1";
			else
				if [ "$t_func_syscall_proto" = 'yes' ]; then
					grepc_linux_func_syscall_proto "$1";
				fi;
				if [ "$t_func_syscall_def" = 'yes' ]; then
					grepc_linux_func_syscall_def "$1";
				fi;
			fi;
		fi;
		if [ "$t_macro" = 'yes' ]; then
			grepc_macro "$1";
		fi;
		if [ "$t_type" = 'yes' ]; then
			grepc_type "$1";
		fi;
		if [ "$t_use" = 'yes' ]; then
			grepc_use "$1";
		else
			if [ "$t_use_enum" = 'yes' ]; then
				grepc_use_enum "$1";
			fi;
			if [ "$t_use_func" = 'yes' ]; then
				grepc_use_func "$1";
			fi;
			if [ "$t_use_macro" = 'yes' ]; then
				grepc_use_macro "$1";
			fi;
			if [ "$t_use_type" = 'yes' ]; then
				grepc_use_type "$1";
			fi;
		fi;
	fi;
}


main()
{
	files="$(mktemp -t 'grepc.XXXXXX')";

	grepc_parse_cmd "$@";
	grepc_find_files "$identifier" >"$files";
	grepc_search "$identifier" \
	| if [ -n "$lflag" ]; then
		sort \
		| uniq;
	else
		sed -n '/./,$p';
	fi;
}


main "$@";