summaryrefslogtreecommitdiff
path: root/tools/notsd-fixup--includes
blob: 315be32c8dac7dff7a75a886a7fae8b4cc22f3f4 (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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
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
#!/usr/bin/env bash

panic() {
	>&2 echo panic
	exit 2
}

out() {
	printf '%q ' "$@"
}

# system
# linux
# public
# protected
# private
classify() {
	local path=$1
	if [[ "$path" = linux/* ]]; then
		out linux "$path"
	elif [[ -f "${current_file%/*}/${path}" ]]; then
		out private "$path"
	elif [[ "$path" != systemd/* ]] &&
	     [[ "$path" != libudev.h ]] &&
	     cpp -include "$path" <<<'' &>/dev/null; then
		out system "$path"
	else
		case "$path" in
			*-to-name.h|*-from-name.h)
				base="${path##*/}"
				base="${base%-to-name.h}"
				base="${base%-from-name.h}"
				case "$base" in
					dns_type)	     d=src/grp-resolve/systemd-resolved;;
					keyboard-keys)	     d=src/grp-udev/libudev-core;;
					af|arphrd|cap|errno) d=src/libbasic/include/basic;;
					audit_type)	     d=src/libsystemd/src/sd-journal;;
					*)
						>&2 printf 'Unknown gperf base: %q\n' "$base"
						>&2 printf 'Cannot figure out: %q\n' "$path"
						exit 2
						;;
				esac
				file="$d/${path##*/}"
				if [[ "$current_file" = "$d"/* ]]; then
					out private "${file##*/}"
				elif [[ "$file" = */include/* ]]; then
					out protected "${file##*/include/}"
				else
					out protected "${file##*/}"
				fi
				;;
			asm/sgidefs.h|dbus/dbus.h|efi.h|efilib.h|gio/gio.h|glib.h|libmount.h)
				out system "$path"
				;;
			util.h|*/util.h)
				if [[ "$current_file" = */systemd-boot/* ]]; then
					out private util.h
				else
					out protected basic/util.h
				fi
				;;
			*)
				file=$(find src -type f -name "${path##*/}")
				if [[ -f "$file" ]]; then
					case "$file" in
						*/src/*)
							if [[ "${current_file%/*}" = "${file%/*}" ]]; then
								out private "${file##*/}"
							else
								out protected "${file##*/src/}"
							fi
							;;
						*/libsystemd/include/*|*/libudev/include/*)
							out public "${file##*/include/}"
							;;
						*/include/*)
							out protected "${file##*/include/}"
							;;
						*)
							if [[ "${current_file%/*}" = "${file%/*}" ]]; then
								out private "${file##*/}"
							else
								out protected "${file##*/}"
							fi
							;;
					esac
				else
					>&2 printf 'Cannot figure out: %q\n' "$path"
					exit 2
				fi
				;;
		esac
	fi
}

phase=phase0
hook=:

phase0() {
	phase=phase0
	hook=:
	local line="$1"
	case "$line" in
		'#include'*|'typedef '*';')
			phase1 "$line"
			;;
		*)
			printf '%s\n' "$line"
			;;
	esac
}

phase1_init() {
	phase1_tail=
	system=()
	linux=()
	public=()
	protected=()
	typedef=(); typedef_last=true
	private=()
}
phase1_init
phase1_flush() {
	local b=:
	if [[ ${#system[@]} -gt 0 ]]; then
		printf '%s\n' "${system[@]}" | sort -u
		b=echo
	fi
	if [[ ${#linux[@]} -gt 0 ]]; then
		$b
		printf '%s\n' "${linux[@]}"
		b=echo
	fi
	if [[ ${#public[@]} -gt 0 ]]; then
		$b
		printf '%s\n' "${public[@]}" | sort -u
		b=echo
	fi
	if [[ ${#protected[@]} -gt 0 ]]; then
		$b
		printf '%s\n' "${protected[@]}" | sort -u
		b=echo
	fi
	if [[ ${#typedef[@]} -gt 0 ]] && ! $typedef_last; then
		$b
		printf '%s\n' "${typedef[@]}" | sort -u
		b=echo
	fi
	if [[ ${#private[@]} -gt 0 ]]; then
		$b
		printf '%s\n' "${private[@]}" | sort -u
		b=echo
	fi
	if [[ ${#typedef[@]} -gt 0 ]] && $typedef_last; then
		$b
		printf '%s\n' "${typedef[@]}"
	fi
	printf '%s' "$phase1_tail"
	phase1_init
}
phase1() {
	phase=phase1
	hook=phase1_flush
	local line="$1"
	case "$line" in
		'')
			phase1_tail+=$'\n'
			;;
		'#include'*)
			phase1_tail=''
			local re='^#include [<"]([^">]*)[">](.*)'
			if [[ "$line" =~ $re ]]; then
				IFS=' '
				local buf
				buf="$(classify "${BASH_REMATCH[1]}")" || panic
				read -r class path <<<"$buf"
				case "$class" in
					system)
						printf -v line '#include <%s>%s' "$path" "${BASH_REMATCH[2]}"
						system+=("$line")
						;;
					linux)
						printf -v line '#include <%s>%s' "$path" "${BASH_REMATCH[2]}"
						linux+=("$line")
						;;
					public)
						printf -v line '#include <%s>%s' "$path" "${BASH_REMATCH[2]}"
						public+=("$line")
						;;
					protected)
						printf -v line '#include "%s"%s' "$path" "${BASH_REMATCH[2]}"
						protected+=("$line")
						;;
					private)
						if [[ ${#typedef[@]} -gt 0 ]]; then
							typedef_last=false
						fi
						printf -v line '#include "%s"%s' "$path" "${BASH_REMATCH[2]}"
						private+=("$line")
						;;
				esac
			else
				panic
			fi
			;;
		'typedef '*';')
			phase1_tail=''
			typedef+=("$line")
			;;
		*)
			phase1_flush
			phase0 "$line"
			;;
	esac
}

main() {
	current_file="$1"
	printf ' => %q %q\n' "$0" "$current_file"
	set -o pipefail
	trap 'rm -f -- "$current_file.tmp"' EXIT
	{
		IFS=''
		while read -r line; do
			"$phase" "$line"
			IFS=''
		done
		"$hook"
	} < "$current_file" > "$current_file.tmp"
	# I specificially don't use write-ifchanged because I don't want the
	# temporary file to have the .c suffix.
	if cmp -s "$current_file.tmp" "$current_file"; then
		rm -f "$current_file.tmp" || :
	else
		mv -Tf "$current_file.tmp" "$current_file"
	fi
}

main "$@"