strace/maint/gen_xlat_defs.sh
Eugene Syromyatnikov 769946f50a maint: add a Linux UAPI headers crawler
This script is going to be used to generate xlat fallback values.

* maint/gen_xlat_defs.sh: New file.

Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-08-05 18:57:25 +00:00

231 lines
5.8 KiB
Bash
Executable File

#! /bin/bash -eu
# Generate xlat .in file based on the existing file and Linux UAPI headers.
#
# Copyright (c) 2018 The strace developers.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
warn()
{
printf >&2 '%s: %s\n' "$0" "$*"
}
fatal()
{
warn "$@"
exit 1
}
usage()
{
s="${0//?/ }"
cat >&2 <<-EOF
$0 -f VAL_PRINT_FMT \\
$s -p REGEXP_PATTERN \\
$s -d LINUX_SRC_DIR \\
$s -c COMMON_DEFS_GLOB_PATTERN \\
$s -a ARCH_DEFS_FILE \\
$s < xlat/xlat_file_name.in
Examples:
$0 -f 'd' -p 'MADV_' -d '/path/to/linux' -c 'asm-generic/mman-common.h' -a 'asm/mman.h' < xlat/madvise_cmds.in
$0 -f '#x' -p '_?MAP_' -d '/path/to/linux' -c 'asm-generic/mman*.h' -a 'asm/mman.h' < xlat/mmap_flags.in
$0 -f '#o' -p '[_OF]' -d '/path/to/linux' -c 'asm-generic/fcntl.h' -a 'asm/fcntl.h' < xlat/open_mode_flags.in
$0 -f 'u' -p 'SO_' -d '/path/to/linux' -c 'asm-generic/socket.h' -a 'asm/socket.h' < xlat/sock_options.in
EOF
exit 1
}
VAL_PRINT_FMT=
REGEXP_PATTERN=
COMMON_DEFS_GLOB_PATTERN=
ARCH_DEFS_FILE=
LINUX_SRC=
comment_re='[^/]*\/\*.*\*\/.*'
comment_glob='*/\**\*/*'
while [ 0 -lt "$#" ]; do
case "$1" in
-p)
shift
REGEXP_PATTERN="$1"
;;
-d)
shift
LINUX_SRC="$1"
;;
-c)
shift
COMMON_DEFS_GLOB_PATTERN="$1"
;;
-a)
shift
ARCH_DEFS_FILE="$1"
;;
-f)
shift
VAL_PRINT_FMT="$1"
;;
-[h?])
usage
;;
-*)
fatal "$1: unknown option"
;;
*)
fatal "$1: unexpected argument"
;;
esac
shift
done
for v in \
VAL_PRINT_FMT \
REGEXP_PATTERN \
COMMON_DEFS_GLOB_PATTERN \
ARCH_DEFS_FILE \
LINUX_SRC \
; do
eval [ -n \"\$$v\" ] || fatal "$v has not been specified"
done
printf "/* Generated by %s -f '%s' -p '%s' -c '%s' -a '%s' */\\n" \
"$0" "$VAL_PRINT_FMT" "$REGEXP_PATTERN" \
"$COMMON_DEFS_GLOB_PATTERN" "$ARCH_DEFS_FILE"
sed -rn '/^\/\* Generated by .*\*\//d;s/^((# .*|'"$comment_re"'|'"$REGEXP_PATTERN"'[^[:space:]]*).*)?$/\2/p' |
uniq |
while read name_ rest; do
# Empty lines, comments, and "# " directives are passed verbatim.
case "$name_ $rest" in
\ )
echo
continue ;;
\#\ *|${comment_glob})
printf '%s\n' "$name_ $rest"
continue ;;
esac
sed -rn 's/#define[[:space:]]+('"$name_"')[[:space:]]+([x[:xdigit:]]+).*$/\2\t\1/p' \
$LINUX_SRC/include/uapi/$COMMON_DEFS_GLOB_PATTERN |
sort -n | {
def=
name=
read def name ||:
if [ -n "$def" ]; then
warn "$name_ is defined to $def"
else
warn "No def for $name_"
name="$name_"
fi
grep -oEH '#define[[:space:]]+'"$name"'[[:space:]]+(0x[[:xdigit:]]+|[[:digit:]]+)' \
$LINUX_SRC/arch/*/include/uapi/$ARCH_DEFS_FILE |
sed -rn 's|^[^#]*/arch/([^/]+)/include/uapi/'"$ARCH_DEFS_FILE"':#define[[:space:]]+'"$name"'[[:space:]]+([^[:space:]]+)([[:space:]].*)?$|\1\t\2|p' |
sed s/parisc/hppa/ |
sort |
awk -vname="$name" -vdef="$def" -vfmt="$VAL_PRINT_FMT" '
# Like strtonum, but also supports octal and hexadecimal
# representation.
# Taken from https://www.gnu.org/software/gawk/manual/html_node/Strtonum-Function.html
function mystrtonum(str, ret, n, i, k, c)
{
if (str ~ /^0[0-7]*$/) {
# octal
n = length(str)
ret = 0
for (i = 1; i <= n; i++) {
c = substr(str, i, 1)
# index() returns 0 if c not in string,
# includes c == "0"
k = index("1234567", c)
ret = ret * 8 + k
}
} else if (str ~ /^0[xX][[:xdigit:]]+$/) {
# hexadecimal
str = substr(str, 3) # lop off leading 0x
n = length(str)
ret = 0
for (i = 1; i <= n; i++) {
c = substr(str, i, 1)
c = tolower(c)
# index() returns 0 if c not in string,
# includes c == "0"
k = index("123456789abcdef", c)
ret = ret * 16 + k
}
} else if (str ~ \
/^[-+]?([0-9]+([.][0-9]*([Ee][0-9]+)?)?|([.][0-9]+([Ee][-+]?[0-9]+)?))$/) {
# decimal number, possibly floating point
ret = str + 0
} else {
ret = "NOT-A-NUMBER"
}
return ret
}
BEGIN {
d = mystrtonum(def)
}
{
i = mystrtonum($2)
if (i == d) next
if (a[i])
a[i] = a[i] " || defined __" $1 "__"
else
a[i] = "defined __" $1 "__"
}
END {
iftext = "#if"
for (i in a) {
printf("%s %s\n%s\t%" fmt "\n", iftext, a[i],
name, i)
iftext = "#elif"
}
if (iftext != "#if")
print "#else"
if (def == "")
printf("%s\n", name)
else
printf("%s\t%" fmt "\n", name, d)
if (iftext != "#if")
print "#endif"
}' |
sed -e 's/defined __arm64__/& || defined __aarch64__/g' \
-e 's/defined __x86__/defined __x86_64__ || defined __i386__/g'
}
done