#!/bin/bash # Generate tags or cscope files # Usage tags.sh # # mode may be any of: tags, TAGS, cscope # # Uses the following environment variables: # ARCH, SUBARCH, SRCARCH, srctree, src, obj if test $KBUILD_VERBOSE = "1" { set -x } # RCS_FIND_IGNORE has escaped ()s -- remove them. setglobal ignore = $[echo $RCS_FIND_IGNORE | sed 's|\\||g] # tags and cscope files should also ignore MODVERSION *.mod.c files setglobal ignore = ""$ignore ( -name *.mod.c ) -prune -o"" # Do not use full path if we do not use O=.. builds # Use make O=. {tags|cscope} # to force full paths for a non-O= build if test $(KBUILD_SRC) = "" { setglobal tree = '' } else { setglobal tree = "$(srctree)/" } # ignore userspace tools setglobal ignore = ""$ignore ( -path $(tree)tools ) -prune -o"" # Find all available archs proc find_all_archs { setglobal ALLSOURCE_ARCHS = ''"" for arch in [$[ls $(tree)arch]] { setglobal ALLSOURCE_ARCHS = ""$(ALLSOURCE_ARCHS) "$(arch##\/)" } } # Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH if test $(ALLSOURCE_ARCHS) = "" { setglobal ALLSOURCE_ARCHS = $(SRCARCH) } elif test $(ALLSOURCE_ARCHS) = "all" { find_all_archs } # find sources in arch/$ARCH proc find_arch_sources { for i in [$archincludedir] { setglobal prune = ""$prune -wholename $i -prune -o"" } find $(tree)arch/$1 $ignore $subarchprune $prune -name $2 \ -not -type l -print; } # find sources in arch/$1/include proc find_arch_include_sources { setglobal include = $[find $(tree)arch/$1/ $subarchprune \ -name include -type d -print]; if test -n $include { setglobal archincludedir = ""$archincludedir $include"" find $include $ignore -name $2 -not -type l -print; } } # find sources in include/ proc find_include_sources { find $(tree)include $ignore -name config -prune -o -name $1 \ -not -type l -print; } # find sources in rest of tree # we could benefit from a list of dirs to search in here proc find_other_sources { find $(tree)* $ignore \ '(' -name include -o -name arch -o -name '.tmp_*' ')' -prune -o \ -name $1 -not -type l -print; } proc find_sources { find_arch_sources $1 $2 } proc all_sources { find_arch_include_sources $(SRCARCH) '*.[chS]' if test ! -z $archinclude { find_arch_include_sources $archinclude '*.[chS]' } find_include_sources '*.[chS]' for arch in [$ALLSOURCE_ARCHS] { find_sources $arch '*.[chS]' } find_other_sources '*.[chS]' } proc all_compiled_sources { for i in [$[all_sources]] { match $i { with *.[cS] setglobal j = $(i/\.[cS]/\.o) if test -e $j { echo $i } with * echo $i } } } proc all_target_sources { if test -n $COMPILED_SOURCE { all_compiled_sources } else { all_sources } } proc all_kconfigs { for arch in [$ALLSOURCE_ARCHS] { find_sources $arch 'Kconfig*' } find_other_sources 'Kconfig*' } proc docscope { shell {echo '-'k; echo '-'q; all_target_sources} > cscope.files cscope -b -f cscope.out } proc dogtags { all_target_sources | gtags -i -f - } # Basic regular expressions with an optional /kind-spec/ for ctags and # the following limitations: # - No regex modifiers # - Use \{0,1\} instead of \?, because etags expects an unescaped ? # - \s is not working with etags, use a space or [ \t] # - \w works, but does not match underscores in etags # - etags regular expressions have to match at the start of a line; # a ^[^#] is prepended by setup_regex unless an anchor is already present setglobal regex_asm = '( ''/^\(ENTRY\|_GLOBAL\)(\([[:alnum:]_\\]*\)).*/\2/' ) setglobal regex_c = '( ''/^SYSCALL_DEFINE[0-9](\([[:alnum:]_]*\).*/sys_\1/' '/^COMPAT_SYSCALL_DEFINE[0-9](\([[:alnum:]_]*\).*/compat_sys_\1/' '/^TRACE_EVENT(\([[:alnum:]_]*\).*/trace_\1/' '/^TRACE_EVENT(\([[:alnum:]_]*\).*/trace_\1_rcuidle/' '/^DEFINE_EVENT([^,)]*, *\([[:alnum:]_]*\).*/trace_\1/' '/^DEFINE_EVENT([^,)]*, *\([[:alnum:]_]*\).*/trace_\1_rcuidle/' '/^DEFINE_INSN_CACHE_OPS(\([[:alnum:]_]*\).*/get_\1_slot/' '/^DEFINE_INSN_CACHE_OPS(\([[:alnum:]_]*\).*/free_\1_slot/' '/^PAGEFLAG(\([[:alnum:]_]*\).*/Page\1/' '/^PAGEFLAG(\([[:alnum:]_]*\).*/SetPage\1/' '/^PAGEFLAG(\([[:alnum:]_]*\).*/ClearPage\1/' '/^TESTSETFLAG(\([[:alnum:]_]*\).*/TestSetPage\1/' '/^TESTPAGEFLAG(\([[:alnum:]_]*\).*/Page\1/' '/^SETPAGEFLAG(\([[:alnum:]_]*\).*/SetPage\1/' '/\<__SETPAGEFLAG(\([[:alnum:]_]*\).*/__SetPage\1/' '/\ !1 | grep -iq exuberant { exuberant $1 } elif $1 --version !2 > !1 | grep -iq emacs { emacs $1 } else { all_target_sources | xargs $1 -a } } # Support um (which uses SUBARCH) if test $(ARCH) = "um" { if test $SUBARCH = "i386" { setglobal archinclude = 'x86' } elif test $SUBARCH = "x86_64" { setglobal archinclude = 'x86' } else { setglobal archinclude = $(SUBARCH) } } elif test $(SRCARCH) = "arm" -a $(SUBARCH) != "" { setglobal subarchdir = $[find $(tree)arch/$SRCARCH/ -name "mach-*" -type d -o \ -name "plat-*" -type d]; for i in [$subarchdir] { match $i { with *"mach-"${SUBARCH} with *"plat-"${SUBARCH} with * setglobal subarchprune = ""$subarchprune \ -wholename $i -prune -o"" } } } setglobal remove_structs = '' match $1 { with "cscope" docscope with "gtags" dogtags with "tags" rm -f tags xtags ctags setglobal remove_structs = 'y' with "TAGS" rm -f TAGS xtags etags setglobal remove_structs = 'y' } # Remove structure forward declarations. if test -n $remove_structs { env LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' $1 }