#!/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 "$@";