]> granicus.if.org Git - strace/commitdiff
maint: add a Linux UAPI headers crawler
authorEugene Syromyatnikov <evgsyr@gmail.com>
Sun, 5 Aug 2018 14:26:15 +0000 (16:26 +0200)
committerDmitry V. Levin <ldv@altlinux.org>
Sun, 5 Aug 2018 18:57:25 +0000 (18:57 +0000)
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>
maint/gen_xlat_defs.sh [new file with mode: 0755]

diff --git a/maint/gen_xlat_defs.sh b/maint/gen_xlat_defs.sh
new file mode 100755 (executable)
index 0000000..31da7f5
--- /dev/null
@@ -0,0 +1,230 @@
+#! /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