summaryrefslogtreecommitdiffstats
path: root/util/make-mask
blob: 1285f52556a876df0ced4e904df309d4ff52a57c (plain) (blame)
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
#!/bin/sh

set -e

test $# -ge 1

lowercase () { printf '%s\n' "$*" | tr '[A-Z]' '[a-z]'; }

symbols="$(lowercase "$1")"
shift 1

trailing_zeroes () {
	r=0
	x=$1
	while (( (x & 1) == 0 )); do
		: $(( r++ ))
		x=$(( x >> 1 ))
	done
	if (( x > 1 )); then
		printf 'Invalid bitmask value: %s = %#x: multiple bits set\n' $2 $1 >&2
		exit 1
	fi
	printf '%i\n' $r
}

ifzero=
printf	'static const char *\n'
printf	'extract_symbol_%s(struct libsyscalls_symbol_printer_data *data, ' "$symbols"
printf                    'unsigned long long int *valuep, char *fallback_out) /* 1 */\n'
printf	'{\n'
printf	'	const char *ret;\n'
printf	'	signed char bit = trailing_zeroes(*valuep);\n'
printf	'	*fallback_out = %s;\n' "'x'"
printf	'	switch (bit) {\n'
while read name value; do
 if test $value = 0; then ifzero="$name"; continue; fi
printf	'	case %i: ret = "%s"; break;\n' $(trailing_zeroes $value $name) $name
done
if test -n "$ifzero"; then
printf	'	case -1: return "%s";\n' $ifzero
fi
printf	'	default:\n'
if test $# -ge 1; then
 for use; do
printf	'		if ((ret = extract_symbol_%s(data, valuep, fallback_out))) return ret;\n' "$(lowercase "$use")"
 done
fi
printf	'		return NULL;\n'
printf	'	}\n'
printf	'	*valuep ^= 1ULL << (unsigned)bit;\n'
if test $# = 0; then
printf	'	(void) data;\n'
fi
printf	'	return ret;\n'
printf	'}\n'