Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0-only
0003 # Generate tags or cscope files
0004 # Usage tags.sh <mode>
0005 #
0006 # mode may be any of: tags, TAGS, cscope
0007 #
0008 # Uses the following environment variables:
0009 # SUBARCH, SRCARCH, srctree
0010 
0011 if [ "$KBUILD_VERBOSE" = "1" ]; then
0012         set -x
0013 fi
0014 
0015 # RCS_FIND_IGNORE has escaped ()s -- remove them.
0016 ignore="$(echo "$RCS_FIND_IGNORE" | sed 's|\\||g' )"
0017 # tags and cscope files should also ignore MODVERSION *.mod.c files
0018 ignore="$ignore ( -name *.mod.c ) -prune -o"
0019 
0020 # Use make KBUILD_ABS_SRCTREE=1 {tags|cscope}
0021 # to force full paths for a non-O= build
0022 if [ "${srctree}" = "." -o -z "${srctree}" ]; then
0023         tree=
0024 else
0025         tree=${srctree}/
0026 fi
0027 
0028 # Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH
0029 if [ "${ALLSOURCE_ARCHS}" = "" ]; then
0030         ALLSOURCE_ARCHS=${SRCARCH}
0031 elif [ "${ALLSOURCE_ARCHS}" = "all" ]; then
0032         ALLSOURCE_ARCHS=$(find ${tree}arch/ -mindepth 1 -maxdepth 1 -type d -printf '%f ')
0033 fi
0034 
0035 # find sources in arch/$1
0036 find_arch_sources()
0037 {
0038         for i in $archincludedir; do
0039                 prune="$prune -wholename $i -prune -o"
0040         done
0041         find ${tree}arch/$1 $ignore $prune -name "$2" -not -type l -print;
0042 }
0043 
0044 # find sources in arch/$1/include
0045 find_arch_include_sources()
0046 {
0047         include=$(find ${tree}arch/$1/ -name include -type d -print);
0048         if [ -n "$include" ]; then
0049                 archincludedir="$archincludedir $include"
0050                 find $include $ignore -name "$2" -not -type l -print;
0051         fi
0052 }
0053 
0054 # find sources in include/
0055 find_include_sources()
0056 {
0057         find ${tree}include $ignore -name config -prune -o -name "$1" \
0058                 -not -type l -print;
0059 }
0060 
0061 # find sources in rest of tree
0062 # we could benefit from a list of dirs to search in here
0063 find_other_sources()
0064 {
0065         find ${tree}* $ignore \
0066              \( -path ${tree}include -o -path ${tree}arch -o -name '.tmp_*' \) -prune -o \
0067                -name "$1" -not -type l -print;
0068 }
0069 
0070 find_sources()
0071 {
0072         find_arch_sources $1 "$2"
0073 }
0074 
0075 all_sources()
0076 {
0077         find_arch_include_sources ${SRCARCH} '*.[chS]'
0078         if [ ! -z "$archinclude" ]; then
0079                 find_arch_include_sources $archinclude '*.[chS]'
0080         fi
0081         find_include_sources '*.[chS]'
0082         for arch in $ALLSOURCE_ARCHS
0083         do
0084                 find_sources $arch '*.[chS]'
0085         done
0086         find_other_sources '*.[chS]'
0087 }
0088 
0089 all_compiled_sources()
0090 {
0091         {
0092                 echo include/generated/autoconf.h
0093                 find $ignore -name "*.cmd" -exec \
0094                         grep -Poh '(?(?=^source_.* \K).*|(?=^  \K\S).*(?= \\))' {} \+ |
0095                 awk '!a[$0]++'
0096         } | xargs realpath -esq $([ -z "$KBUILD_ABS_SRCTREE" ] && echo --relative-to=.) |
0097         sort -u
0098 }
0099 
0100 all_target_sources()
0101 {
0102         if [ -n "$COMPILED_SOURCE" ]; then
0103                 all_compiled_sources
0104         else
0105                 all_sources
0106         fi
0107 }
0108 
0109 all_kconfigs()
0110 {
0111         find ${tree}arch/ -maxdepth 1 $ignore \
0112                -name "Kconfig*" -not -type l -print;
0113         for arch in $ALLSOURCE_ARCHS; do
0114                 find_sources $arch 'Kconfig*'
0115         done
0116         find_other_sources 'Kconfig*'
0117 }
0118 
0119 docscope()
0120 {
0121         (echo \-k; echo \-q; all_target_sources) > cscope.files
0122         cscope -b -f cscope.out
0123 }
0124 
0125 dogtags()
0126 {
0127         all_target_sources | gtags -i -f -
0128 }
0129 
0130 # Basic regular expressions with an optional /kind-spec/ for ctags and
0131 # the following limitations:
0132 # - No regex modifiers
0133 # - Use \{0,1\} instead of \?, because etags expects an unescaped ?
0134 # - \s is not working with etags, use a space or [ \t]
0135 # - \w works, but does not match underscores in etags
0136 # - etags regular expressions have to match at the start of a line;
0137 #   a ^[^#] is prepended by setup_regex unless an anchor is already present
0138 regex_asm=(
0139         '/^\(ENTRY\|_GLOBAL\)([[:space:]]*\([[:alnum:]_\\]*\)).*/\2/'
0140 )
0141 regex_c=(
0142         '/^SYSCALL_DEFINE[0-9]([[:space:]]*\([[:alnum:]_]*\).*/sys_\1/'
0143         '/^BPF_CALL_[0-9]([[:space:]]*\([[:alnum:]_]*\).*/\1/'
0144         '/^COMPAT_SYSCALL_DEFINE[0-9]([[:space:]]*\([[:alnum:]_]*\).*/compat_sys_\1/'
0145         '/^TRACE_EVENT([[:space:]]*\([[:alnum:]_]*\).*/trace_\1/'
0146         '/^TRACE_EVENT([[:space:]]*\([[:alnum:]_]*\).*/trace_\1_rcuidle/'
0147         '/^DEFINE_EVENT([^,)]*,[[:space:]]*\([[:alnum:]_]*\).*/trace_\1/'
0148         '/^DEFINE_EVENT([^,)]*,[[:space:]]*\([[:alnum:]_]*\).*/trace_\1_rcuidle/'
0149         '/^DEFINE_INSN_CACHE_OPS([[:space:]]*\([[:alnum:]_]*\).*/get_\1_slot/'
0150         '/^DEFINE_INSN_CACHE_OPS([[:space:]]*\([[:alnum:]_]*\).*/free_\1_slot/'
0151         '/^PAGEFLAG([[:space:]]*\([[:alnum:]_]*\).*/Page\1/'
0152         '/^PAGEFLAG([[:space:]]*\([[:alnum:]_]*\).*/SetPage\1/'
0153         '/^PAGEFLAG([[:space:]]*\([[:alnum:]_]*\).*/ClearPage\1/'
0154         '/^TESTSETFLAG([[:space:]]*\([[:alnum:]_]*\).*/TestSetPage\1/'
0155         '/^TESTPAGEFLAG([[:space:]]*\([[:alnum:]_]*\).*/Page\1/'
0156         '/^SETPAGEFLAG([[:space:]]*\([[:alnum:]_]*\).*/SetPage\1/'
0157         '/\<__SETPAGEFLAG([[:space:]]*\([[:alnum:]_]*\).*/__SetPage\1/'
0158         '/\<TESTCLEARFLAG([[:space:]]*\([[:alnum:]_]*\).*/TestClearPage\1/'
0159         '/\<__TESTCLEARFLAG([[:space:]]*\([[:alnum:]_]*\).*/TestClearPage\1/'
0160         '/\<CLEARPAGEFLAG([[:space:]]*\([[:alnum:]_]*\).*/ClearPage\1/'
0161         '/\<__CLEARPAGEFLAG([[:space:]]*\([[:alnum:]_]*\).*/__ClearPage\1/'
0162         '/^__PAGEFLAG([[:space:]]*\([[:alnum:]_]*\).*/__SetPage\1/'
0163         '/^__PAGEFLAG([[:space:]]*\([[:alnum:]_]*\).*/__ClearPage\1/'
0164         '/^PAGEFLAG_FALSE([[:space:]]*\([[:alnum:]_]*\).*/Page\1/'
0165         '/\<TESTSCFLAG([[:space:]]*\([[:alnum:]_]*\).*/TestSetPage\1/'
0166         '/\<TESTSCFLAG([[:space:]]*\([[:alnum:]_]*\).*/TestClearPage\1/'
0167         '/\<SETPAGEFLAG_NOOP([[:space:]]*\([[:alnum:]_]*\).*/SetPage\1/'
0168         '/\<CLEARPAGEFLAG_NOOP([[:space:]]*\([[:alnum:]_]*\).*/ClearPage\1/'
0169         '/\<__CLEARPAGEFLAG_NOOP([[:space:]]*\([[:alnum:]_]*\).*/__ClearPage\1/'
0170         '/\<TESTCLEARFLAG_FALSE([[:space:]]*\([[:alnum:]_]*\).*/TestClearPage\1/'
0171         '/^PAGE_TYPE_OPS([[:space:]]*\([[:alnum:]_]*\).*/Page\1/'
0172         '/^PAGE_TYPE_OPS([[:space:]]*\([[:alnum:]_]*\).*/__SetPage\1/'
0173         '/^PAGE_TYPE_OPS([[:space:]]*\([[:alnum:]_]*\).*/__ClearPage\1/'
0174         '/^TASK_PFA_TEST([^,]*,[[:space:]]*\([[:alnum:]_]*\))/task_\1/'
0175         '/^TASK_PFA_SET([^,]*,[[:space:]]*\([[:alnum:]_]*\))/task_set_\1/'
0176         '/^TASK_PFA_CLEAR([^,]*,[[:space:]]*\([[:alnum:]_]*\))/task_clear_\1/'
0177         '/^DEF_MMIO_\(IN\|OUT\)_[XD]([[:space:]]*\([[:alnum:]_]*\),[^)]*)/\2/'
0178         '/^DEBUGGER_BOILERPLATE([[:space:]]*\([[:alnum:]_]*\))/\1/'
0179         '/^DEF_PCI_AC_\(\|NO\)RET([[:space:]]*\([[:alnum:]_]*\).*/\2/'
0180         '/^PCI_OP_READ([[:space:]]*\(\w*\).*[1-4])/pci_bus_read_config_\1/'
0181         '/^PCI_OP_WRITE([[:space:]]*\(\w*\).*[1-4])/pci_bus_write_config_\1/'
0182         '/\<DEFINE_\(RT_MUTEX\|MUTEX\|SEMAPHORE\|SPINLOCK\)([[:space:]]*\([[:alnum:]_]*\)/\2/v/'
0183         '/\<DEFINE_\(RAW_SPINLOCK\|RWLOCK\|SEQLOCK\)([[:space:]]*\([[:alnum:]_]*\)/\2/v/'
0184         '/\<DECLARE_\(RWSEM\|COMPLETION\)([[:space:]]*\([[:alnum:]_]\+\)/\2/v/'
0185         '/\<DECLARE_BITMAP([[:space:]]*\([[:alnum:]_]*\)/\1/v/'
0186         '/\(^\|\s\)\(\|L\|H\)LIST_HEAD([[:space:]]*\([[:alnum:]_]*\)/\3/v/'
0187         '/\(^\|\s\)RADIX_TREE([[:space:]]*\([[:alnum:]_]*\)/\2/v/'
0188         '/\<DEFINE_PER_CPU([^,]*,[[:space:]]*\([[:alnum:]_]*\)/\1/v/'
0189         '/\<DEFINE_PER_CPU_SHARED_ALIGNED([^,]*,[[:space:]]*\([[:alnum:]_]*\)/\1/v/'
0190         '/\<DECLARE_WAIT_QUEUE_HEAD([[:space:]]*\([[:alnum:]_]*\)/\1/v/'
0191         '/\<DECLARE_\(TASKLET\|WORK\|DELAYED_WORK\)([[:space:]]*\([[:alnum:]_]*\)/\2/v/'
0192         '/\(^\s\)OFFSET([[:space:]]*\([[:alnum:]_]*\)/\2/v/'
0193         '/\(^\s\)DEFINE([[:space:]]*\([[:alnum:]_]*\)/\2/v/'
0194         '/\<\(DEFINE\|DECLARE\)_HASHTABLE([[:space:]]*\([[:alnum:]_]*\)/\2/v/'
0195         '/\<DEFINE_ID\(R\|A\)([[:space:]]*\([[:alnum:]_]\+\)/\2/'
0196         '/\<DEFINE_WD_CLASS([[:space:]]*\([[:alnum:]_]\+\)/\1/'
0197         '/\<ATOMIC_NOTIFIER_HEAD([[:space:]]*\([[:alnum:]_]\+\)/\1/'
0198         '/\<RAW_NOTIFIER_HEAD([[:space:]]*\([[:alnum:]_]\+\)/\1/'
0199         '/\<DECLARE_FAULT_ATTR([[:space:]]*\([[:alnum:]_]\+\)/\1/'
0200         '/\<BLOCKING_NOTIFIER_HEAD([[:space:]]*\([[:alnum:]_]\+\)/\1/'
0201         '/\<DEVICE_ATTR_\(RW\|RO\|WO\)([[:space:]]*\([[:alnum:]_]\+\)/dev_attr_\2/'
0202         '/\<DRIVER_ATTR_\(RW\|RO\|WO\)([[:space:]]*\([[:alnum:]_]\+\)/driver_attr_\2/'
0203         '/\<\(DEFINE\|DECLARE\)_STATIC_KEY_\(TRUE\|FALSE\)\(\|_RO\)([[:space:]]*\([[:alnum:]_]\+\)/\4/'
0204         '/^SEQCOUNT_LOCKTYPE(\([^,]*\),[[:space:]]*\([^,]*\),[^)]*)/seqcount_\2_t/'
0205         '/^SEQCOUNT_LOCKTYPE(\([^,]*\),[[:space:]]*\([^,]*\),[^)]*)/seqcount_\2_init/'
0206 )
0207 regex_kconfig=(
0208         '/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/\2/'
0209         '/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/CONFIG_\2/'
0210 )
0211 setup_regex()
0212 {
0213         local mode=$1 lang tmp=() r
0214         shift
0215 
0216         regex=()
0217         for lang; do
0218                 case "$lang" in
0219                 asm)       tmp=("${regex_asm[@]}") ;;
0220                 c)         tmp=("${regex_c[@]}") ;;
0221                 kconfig)   tmp=("${regex_kconfig[@]}") ;;
0222                 esac
0223                 for r in "${tmp[@]}"; do
0224                         if test "$mode" = "exuberant"; then
0225                                 regex[${#regex[@]}]="--regex-$lang=${r}b"
0226                         else
0227                                 # Remove ctags /kind-spec/
0228                                 case "$r" in
0229                                 /*/*/?/)
0230                                         r=${r%?/}
0231                                 esac
0232                                 # Prepend ^[^#] unless already anchored
0233                                 case "$r" in
0234                                 /^*) ;;
0235                                 *)
0236                                         r="/^[^#]*${r#/}"
0237                                 esac
0238                                 regex[${#regex[@]}]="--regex=$r"
0239                         fi
0240                 done
0241         done
0242 }
0243 
0244 exuberant()
0245 {
0246         CTAGS_EXTRA="extra"
0247         if $1 --version 2>&1 | grep -iq universal; then
0248             CTAGS_EXTRA="extras"
0249         fi
0250         setup_regex exuberant asm c
0251         all_target_sources | xargs $1 -a                        \
0252         -I __initdata,__exitdata,__initconst,__ro_after_init    \
0253         -I __initdata_memblock                                  \
0254         -I __refdata,__attribute,__maybe_unused,__always_unused \
0255         -I __acquires,__releases,__deprecated,__always_inline   \
0256         -I __read_mostly,__aligned,____cacheline_aligned        \
0257         -I ____cacheline_aligned_in_smp                         \
0258         -I __cacheline_aligned,__cacheline_aligned_in_smp       \
0259         -I ____cacheline_internodealigned_in_smp                \
0260         -I __used,__packed,__packed2__,__must_check,__must_hold \
0261         -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL,ACPI_EXPORT_SYMBOL   \
0262         -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \
0263         -I static,const                                         \
0264         --$CTAGS_EXTRA=+fq --c-kinds=+px --fields=+iaS --langmap=c:+.h \
0265         "${regex[@]}"
0266 
0267         setup_regex exuberant kconfig
0268         all_kconfigs | xargs $1 -a                              \
0269         --langdef=kconfig --language-force=kconfig "${regex[@]}"
0270 
0271 }
0272 
0273 emacs()
0274 {
0275         setup_regex emacs asm c
0276         all_target_sources | xargs $1 -a "${regex[@]}"
0277 
0278         setup_regex emacs kconfig
0279         all_kconfigs | xargs $1 -a "${regex[@]}"
0280 }
0281 
0282 xtags()
0283 {
0284         if $1 --version 2>&1 | grep -iq exuberant; then
0285                 exuberant $1
0286         elif $1 --version 2>&1 | grep -iq emacs; then
0287                 emacs $1
0288         else
0289                 all_target_sources | xargs $1 -a
0290         fi
0291 }
0292 
0293 # Support um (which uses SUBARCH)
0294 if [ "${ARCH}" = "um" ]; then
0295         if [ "$SUBARCH" = "i386" ]; then
0296                 archinclude=x86
0297         elif [ "$SUBARCH" = "x86_64" ]; then
0298                 archinclude=x86
0299         else
0300                 archinclude=${SUBARCH}
0301         fi
0302 fi
0303 
0304 remove_structs=
0305 case "$1" in
0306         "cscope")
0307                 docscope
0308                 ;;
0309 
0310         "gtags")
0311                 dogtags
0312                 ;;
0313 
0314         "tags")
0315                 rm -f tags
0316                 xtags ctags
0317                 remove_structs=y
0318                 ;;
0319 
0320         "TAGS")
0321                 rm -f TAGS
0322                 xtags etags
0323                 remove_structs=y
0324                 ;;
0325 esac
0326 
0327 # Remove structure forward declarations.
0328 if [ -n "$remove_structs" ]; then
0329     LC_ALL=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' $1
0330 fi