diff options
Diffstat (limited to 'util/make-mask')
-rwxr-xr-x | util/make-mask | 55 |
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' |