tags.sh 9.06 KB
Newer Older
1
#!/bin/bash
2 3 4 5 6 7
# Generate tags or cscope files
# Usage tags.sh <mode>
#
# mode may be any of: tags, TAGS, cscope
#
# Uses the following environment variables:
Michal Marek's avatar
Michal Marek committed
8
# ARCH, SUBARCH, SRCARCH, srctree, src, obj
9

10
if [ "$KBUILD_VERBOSE" = "1" ]; then
11 12 13
	set -x
fi

14 15 16 17
# RCS_FIND_IGNORE has escaped ()s -- remove them.
ignore="$(echo "$RCS_FIND_IGNORE" | sed 's|\\||g' )"
# tags and cscope files should also ignore MODVERSION *.mod.c files
ignore="$ignore ( -name *.mod.c ) -prune -o"
18

19
# Do not use full path if we do not use O=.. builds
20 21
# Use make O=. {tags|cscope}
# to force full paths for a non-O= build
22
if [ "${KBUILD_SRC}" = "" ]; then
23 24
	tree=
else
Jiri Slaby's avatar
Jiri Slaby committed
25
	tree=${srctree}/
26 27
fi

28 29 30
# ignore userspace tools
ignore="$ignore ( -path ${tree}tools ) -prune -o"

31 32 33 34 35 36 37 38 39
# Find all available archs
find_all_archs()
{
	ALLSOURCE_ARCHS=""
	for arch in `ls ${tree}arch`; do
		ALLSOURCE_ARCHS="${ALLSOURCE_ARCHS} "${arch##\/}
	done
}

40 41 42
# Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH
if [ "${ALLSOURCE_ARCHS}" = "" ]; then
	ALLSOURCE_ARCHS=${SRCARCH}
43 44
elif [ "${ALLSOURCE_ARCHS}" = "all" ]; then
	find_all_archs
45 46
fi

47 48 49
# find sources in arch/$ARCH
find_arch_sources()
{
50 51 52
	for i in $archincludedir; do
		prune="$prune -wholename $i -prune -o"
	done
53 54
	find ${tree}arch/$1 $ignore $subarchprune $prune -name "$2" \
		-not -type l -print;
55 56 57 58 59
}

# find sources in arch/$1/include
find_arch_include_sources()
{
60 61
	include=$(find ${tree}arch/$1/ $subarchprune \
					-name include -type d -print);
62 63
	if [ -n "$include" ]; then
		archincludedir="$archincludedir $include"
64
		find $include $ignore -name "$2" -not -type l -print;
65
	fi
66 67 68 69 70
}

# find sources in include/
find_include_sources()
{
71 72
	find ${tree}include $ignore -name config -prune -o -name "$1" \
		-not -type l -print;
73 74 75 76 77 78 79 80
}

# find sources in rest of tree
# we could benefit from a list of dirs to search in here
find_other_sources()
{
	find ${tree}* $ignore \
	     \( -name include -o -name arch -o -name '.tmp_*' \) -prune -o \
81
	       -name "$1" -not -type l -print;
82 83 84 85
}

find_sources()
{
Jiri Slaby's avatar
Jiri Slaby committed
86
	find_arch_sources $1 "$2"
87 88 89 90
}

all_sources()
{
Michal Marek's avatar
Michal Marek committed
91
	find_arch_include_sources ${SRCARCH} '*.[chS]'
92
	if [ ! -z "$archinclude" ]; then
Jiri Slaby's avatar
Jiri Slaby committed
93
		find_arch_include_sources $archinclude '*.[chS]'
94
	fi
95
	find_include_sources '*.[chS]'
96 97 98 99
	for arch in $ALLSOURCE_ARCHS
	do
		find_sources $arch '*.[chS]'
	done
100
	find_other_sources '*.[chS]'
101 102
}

103 104 105 106 107 108
all_compiled_sources()
{
	for i in $(all_sources); do
		case "$i" in
			*.[cS])
				j=${i/\.[cS]/\.o}
109
				j="${j#$tree}"
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
				if [ -e $j ]; then
					echo $i
				fi
				;;
			*)
				echo $i
				;;
		esac
	done
}

all_target_sources()
{
	if [ -n "$COMPILED_SOURCE" ]; then
		all_compiled_sources
	else
		all_sources
	fi
}

130 131
all_kconfigs()
{
132 133 134 135
	for arch in $ALLSOURCE_ARCHS; do
		find_sources $arch 'Kconfig*'
	done
	find_other_sources 'Kconfig*'
136 137 138 139
}

docscope()
{
140
	(echo \-k; echo \-q; all_target_sources) > cscope.files
141 142 143
	cscope -b -f cscope.out
}

144 145
dogtags()
{
146
	all_target_sources | gtags -i -f -
147 148
}

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
# 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
regex_asm=(
	'/^\(ENTRY\|_GLOBAL\)(\([[:alnum:]_\\]*\)).*/\2/'
)
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/'
167 168
	'/^DEFINE_INSN_CACHE_OPS(\([[:alnum:]_]*\).*/get_\1_slot/'
	'/^DEFINE_INSN_CACHE_OPS(\([[:alnum:]_]*\).*/free_\1_slot/'
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
	'/^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/'
	'/\<TESTCLEARFLAG(\([[:alnum:]_]*\).*/TestClearPage\1/'
	'/\<__TESTCLEARFLAG(\([[:alnum:]_]*\).*/TestClearPage\1/'
	'/\<CLEARPAGEFLAG(\([[:alnum:]_]*\).*/ClearPage\1/'
	'/\<__CLEARPAGEFLAG(\([[:alnum:]_]*\).*/__ClearPage\1/'
	'/^__PAGEFLAG(\([[:alnum:]_]*\).*/__SetPage\1/'
	'/^__PAGEFLAG(\([[:alnum:]_]*\).*/__ClearPage\1/'
	'/^PAGEFLAG_FALSE(\([[:alnum:]_]*\).*/Page\1/'
	'/\<TESTSCFLAG(\([[:alnum:]_]*\).*/TestSetPage\1/'
	'/\<TESTSCFLAG(\([[:alnum:]_]*\).*/TestClearPage\1/'
	'/\<SETPAGEFLAG_NOOP(\([[:alnum:]_]*\).*/SetPage\1/'
	'/\<CLEARPAGEFLAG_NOOP(\([[:alnum:]_]*\).*/ClearPage\1/'
	'/\<__CLEARPAGEFLAG_NOOP(\([[:alnum:]_]*\).*/__ClearPage\1/'
	'/\<TESTCLEARFLAG_FALSE(\([[:alnum:]_]*\).*/TestClearPage\1/'
189 190 191
	'/^PAGE_MAPCOUNT_OPS(\([[:alnum:]_]*\).*/Page\1/'
	'/^PAGE_MAPCOUNT_OPS(\([[:alnum:]_]*\).*/__SetPage\1/'
	'/^PAGE_MAPCOUNT_OPS(\([[:alnum:]_]*\).*/__ClearPage\1/'
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
	'/^TASK_PFA_TEST([^,]*, *\([[:alnum:]_]*\))/task_\1/'
	'/^TASK_PFA_SET([^,]*, *\([[:alnum:]_]*\))/task_set_\1/'
	'/^TASK_PFA_CLEAR([^,]*, *\([[:alnum:]_]*\))/task_clear_\1/'
	'/^DEF_MMIO_\(IN\|OUT\)_[XD](\([[:alnum:]_]*\),[^)]*)/\2/'
	'/^DEBUGGER_BOILERPLATE(\([[:alnum:]_]*\))/\1/'
	'/^DEF_PCI_AC_\(\|NO\)RET(\([[:alnum:]_]*\).*/\2/'
	'/^PCI_OP_READ(\(\w*\).*[1-4])/pci_bus_read_config_\1/'
	'/^PCI_OP_WRITE(\(\w*\).*[1-4])/pci_bus_write_config_\1/'
	'/\<DEFINE_\(MUTEX\|SEMAPHORE\|SPINLOCK\)(\([[:alnum:]_]*\)/\2/v/'
	'/\<DEFINE_\(RAW_SPINLOCK\|RWLOCK\|SEQLOCK\)(\([[:alnum:]_]*\)/\2/v/'
	'/\<DECLARE_\(RWSEM\|COMPLETION\)(\([[:alnum:]_]\+\)/\2/v/'
	'/\<DECLARE_BITMAP(\([[:alnum:]_]*\)/\1/v/'
	'/\(^\|\s\)\(\|L\|H\)LIST_HEAD(\([[:alnum:]_]*\)/\3/v/'
	'/\(^\|\s\)RADIX_TREE(\([[:alnum:]_]*\)/\2/v/'
	'/\<DEFINE_PER_CPU([^,]*, *\([[:alnum:]_]*\)/\1/v/'
	'/\<DEFINE_PER_CPU_SHARED_ALIGNED([^,]*, *\([[:alnum:]_]*\)/\1/v/'
	'/\<DECLARE_WAIT_QUEUE_HEAD(\([[:alnum:]_]*\)/\1/v/'
	'/\<DECLARE_\(TASKLET\|WORK\|DELAYED_WORK\)(\([[:alnum:]_]*\)/\2/v/'
	'/\(^\s\)OFFSET(\([[:alnum:]_]*\)/\2/v/'
	'/\(^\s\)DEFINE(\([[:alnum:]_]*\)/\2/v/'
	'/\<DEFINE_HASHTABLE(\([[:alnum:]_]*\)/\1/v/'
)
regex_kconfig=(
	'/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/\2/'
	'/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/CONFIG_\2/'
)
setup_regex()
{
	local mode=$1 lang tmp=() r
	shift

	regex=()
	for lang; do
		case "$lang" in
		asm)       tmp=("${regex_asm[@]}") ;;
		c)         tmp=("${regex_c[@]}") ;;
		kconfig)   tmp=("${regex_kconfig[@]}") ;;
		esac
		for r in "${tmp[@]}"; do
			if test "$mode" = "exuberant"; then
				regex[${#regex[@]}]="--regex-$lang=${r}b"
			else
				# Remove ctags /kind-spec/
				case "$r" in
				/*/*/?/)
					r=${r%?/}
				esac
				# Prepend ^[^#] unless already anchored
				case "$r" in
				/^*) ;;
				*)
					r="/^[^#]*${r#/}"
				esac
				regex[${#regex[@]}]="--regex=$r"
			fi
		done
	done
}

251 252
exuberant()
{
253
	setup_regex exuberant asm c
254
	all_target_sources | xargs $1 -a                        \
255
	-I __initdata,__exitdata,__initconst,			\
256
	-I __initdata_memblock					\
257
	-I __refdata,__attribute,__maybe_unused,__always_unused \
258 259
	-I __acquires,__releases,__deprecated			\
	-I __read_mostly,__aligned,____cacheline_aligned        \
260
	-I ____cacheline_aligned_in_smp                         \
261
	-I __cacheline_aligned,__cacheline_aligned_in_smp	\
262
	-I ____cacheline_internodealigned_in_smp                \
263
	-I __used,__packed,__packed2__,__must_check,__must_hold	\
264
	-I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL,ACPI_EXPORT_SYMBOL   \
Stefani Seibold's avatar
Stefani Seibold committed
265
	-I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \
266
	-I static,const						\
267 268
	--extra=+fq --c-kinds=+px --fields=+iaS --langmap=c:+.h \
	"${regex[@]}"
269

270
	setup_regex exuberant kconfig
271
	all_kconfigs | xargs $1 -a                              \
272
	--langdef=kconfig --language-force=kconfig "${regex[@]}"
273 274 275 276 277

}

emacs()
{
278 279
	setup_regex emacs asm c
	all_target_sources | xargs $1 -a "${regex[@]}"
280

281 282
	setup_regex emacs kconfig
	all_kconfigs | xargs $1 -a "${regex[@]}"
283 284 285 286 287 288 289 290 291
}

xtags()
{
	if $1 --version 2>&1 | grep -iq exuberant; then
		exuberant $1
	elif $1 --version 2>&1 | grep -iq emacs; then
		emacs $1
	else
292
		all_target_sources | xargs $1 -a
293
	fi
294 295 296
}

# Support um (which uses SUBARCH)
297 298
if [ "${ARCH}" = "um" ]; then
	if [ "$SUBARCH" = "i386" ]; then
299
		archinclude=x86
300
	elif [ "$SUBARCH" = "x86_64" ]; then
301 302 303 304
		archinclude=x86
	else
		archinclude=${SUBARCH}
	fi
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
elif [ "${SRCARCH}" = "arm" -a "${SUBARCH}" != "" ]; then
	subarchdir=$(find ${tree}arch/$SRCARCH/ -name "mach-*" -type d -o \
							-name "plat-*" -type d);
	for i in $subarchdir; do
		case "$i" in
			*"mach-"${SUBARCH})
				;;
			*"plat-"${SUBARCH})
				;;
			*)
				subarchprune="$subarchprune \
						-wholename $i -prune -o"
				;;
		esac
	done
320 321
fi

322
remove_structs=
323 324 325 326 327
case "$1" in
	"cscope")
		docscope
		;;

328 329 330 331
	"gtags")
		dogtags
		;;

332
	"tags")
333
		rm -f tags
334
		xtags ctags
335
		remove_structs=y
336 337 338
		;;

	"TAGS")
339
		rm -f TAGS
340
		xtags etags
341
		remove_structs=y
342 343
		;;
esac
344 345

# Remove structure forward declarations.
346
if [ -n "$remove_structs" ]; then
347 348
    LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' $1
fi