summaryrefslogtreecommitdiffstats
path: root/util/make-mask
diff options
context:
space:
mode:
Diffstat (limited to 'util/make-mask')
-rwxr-xr-xutil/make-mask55
1 files changed, 55 insertions, 0 deletions
diff --git a/util/make-mask b/util/make-mask
new file mode 100755
index 0000000..1285f52
--- /dev/null
+++ b/util/make-mask
@@ -0,0 +1,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'