summaryrefslogtreecommitdiff
path: root/geany_tagger.sh
blob: abccc760b894475667b27b74a09f7ad573841fe3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/bin/zsh
#
# Author:  Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
# License: GPL v2 or later
#
# Create a C tags file for Geany from a C/C++ header file
#

header="$1"
tagfile="$2"

progname="$(basename $0)"
if [[ -z $header ]] || [[ -z $tagfile ]];then
	echo "Usage: $progname header_file tag_file"
	exit
elif [[ "${tagfile/.c.tags}" = "$tagfile" ]];then
	echo "tag_file must end with .c.tags!"
	exit
fi

stdheaders=(assert.h complex.h ctype.h errno.h fenv.h float.h inttypes.h iso646.h limits.h locale.h math.h setjmp.h signal.h stdarg.h stdbool.h stddef.h stdint.h stdio.h stdlib.h string.h time.h wchar.h wctype.h)

grab_headers(){
	echo -e "***Finding more headers from: ${new[@]}\n"
	list=(${updates[@]})
	updates=()
	for h in ${list[@]};do
		echo -e "\t***Grabbing headers from $h"
		new=($(sed -n 's/^#include ["<]\(.*\)[">]/\1/p' "$h"|awk '{print $1}'))
		[[ -z "${new[@]}" ]] && continue
		#remove c99 headers
		for x in ${stdheaders[@]};do
			new=(${new[@]/#%$x})
		done
		[[ -z "${new[@]}" ]] && continue
		echo -e "\t***Pruning pre-existing headers from new list [1/2]..."
		for x in ${headers[@]};do
#			echo $x
			new=(${new[@]/#%$x})
		done
		[[ -z "${new[@]}" ]] && continue
		echo -e "\t***Pruning pre-existing headers from new list [2/2]..."
		for x in ${new[@]};do
#			echo $x
			if (echo "${headers[@]}"|grep -q $x) ; then
				new=(${new[@]/#%$x})
			fi
		done
		[[ -z "${new[@]}" ]] && continue
		#remove duplicates
		echo -e "\t***Removing duplicates from new list..."
		new=($(printf "%s\n" ${new[@]}|sort -u))
		[[ -z "${new[@]}" ]] && continue
		echo -e "\t***Mapping the following headers to absolute paths: ${new[@]}\n"
		for x in ${new[@]};do
			#if already mapped, ignore
			[[ -f $x ]] && continue

			if [[ "$(dirname $h)" != "/usr/include" ]] && ! echo $x | grep -q '^/' ; then
				if echo $x|grep -q /; then
					y=$(find "$(dirname $h)" -path "$x" |head -n1)
				else
					y=$(find "$(dirname $h)" -name "$x" |head -n1)
				fi
			fi

			#try looking only in /usr/include after
			[[ -n "$y" && -f "$y" ]] || y=$(find /usr/include -mindepth 1 -path "*/$x"|head -n1)
			#replace with absolute path
			[[ -n "$y" && -f "$y" ]] && new=(${new[@]/#%$x/$y})
		done
		for x in ${new[@]};do
			[[ -f $x ]] && continue
			t=$(find /usr/include -mindepth 1 -path "*/$x"|head -n1)
			[[ -n "$t" && -f "$t" ]] && new=(${new[@]/#%$x/$t})
		done
		echo -e "\t***Added ${new[@]}"
		updates+=(${new[@]})
	done
	updates=($(printf "%s\n" ${updates[@]}|sort -u))
	headers+=(${updates[@]})
}

#grab initial headers to include
if [[ ! -f $(readlink -f $header) ]];then
	echo "ERROR: $progname requires the header to be passed with its absolute path" 
	exit 1
fi
updates=($header)
headers=(${new[@]})
#run at least twice
grab_headers
grab_headers
#run while grabbing is still possible
prev_headers=()
while [[ -n "${updates[@]}" ]];do
	grab_headers
done
echo -e "\t***Removing nonexistent filenames..."
for x in ${headers[@]};do
	[[ -f $x ]] && continue
	echo -e "\t\tRemoved $x"
	headers=(${headers[@]/#%$x})
done
headers=($(printf "%s\n" ${headers[@]}|sort -u))
echo -e "***Generating tags for the following headers: ${headers[@]}\n"
geany -P -g "$tagfile" ${headers[@]}

#remove static variables
sed -i '/^_/d' "$tagfile"