[PATCH] sim: common: change gennltvals helper to Python
Lancelot SIX
lsix@lancelotsix.com
Tue Jan 19 13:10:30 GMT 2021
Le Mon, Jan 18, 2021 at 11:02:49PM -0500, Mike Frysinger via Gdb-patches a écrit :
> This tool is only run by developers and not in a release build,
> so rewrite it in Python to make it more maintainable.
> ---
> sim/Makefile.in | 2 +-
> sim/common/gennltvals.py | 229 +++++++++++++++++++++++++++++++++++++
> sim/common/gennltvals.sh | 238 ---------------------------------------
> sim/common/nltvals.def | 3 +-
> 4 files changed, 232 insertions(+), 240 deletions(-)
> create mode 100755 sim/common/gennltvals.py
> delete mode 100755 sim/common/gennltvals.sh
>
> diff --git a/sim/Makefile.in b/sim/Makefile.in
> index a35f807d6f0b..1a2dbb145e66 100644
> --- a/sim/Makefile.in
> +++ b/sim/Makefile.in
> @@ -232,7 +232,7 @@ config.status: configure
> # An alternative is to slurp in the tables at runtime.
> .PHONY: nltvals
> nltvals:
> - $(SHELL) $(abs_srcdir)/common/gennltvals.sh --cpp "$(CPP)" --output nltvals.def --srcroot $(srcroot) && \
> + $(abs_srcdir)/common/gennltvals.py --cpp "$(CPP)" --output nltvals.def --srcroot $(srcroot) && \
> $(SHELL) $(srcroot)/move-if-change nltvals.def $(abs_srcdir)/common/nltvals.def
>
> # Utility to run autoconf in each directory that uses the common framework.
> diff --git a/sim/common/gennltvals.py b/sim/common/gennltvals.py
> new file mode 100755
> index 000000000000..a13a285b4b01
> --- /dev/null
> +++ b/sim/common/gennltvals.py
> @@ -0,0 +1,229 @@
> +#!/usr/bin/env python3
> +# Copyright (C) 1996-2021 Free Software Foundation, Inc.
> +#
> +# This file is part of the GNU simulators.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> +"""Helper to generate nltvals.def.
> +
> +nltvals.def is a file that describes various newlib/libgloss target values used
> +by the host/target interface. This needs to be rerun whenever the newlib source
> +changes. Developers manually run it.
> +
> +If the path to newlib is not specified, it will be searched for in:
> +- the root of this source tree
> +- alongside this source tree
> +"""
> +
> +import argparse
> +from pathlib import Path
> +import re
> +import subprocess
> +import sys
> +from typing import Iterable, List, TextIO
> +
> +
> +PROG = Path(__file__).name
> +
> +# Unfortunately, each newlib/libgloss port has seen fit to define their own
> +# syscall.h file. This means that system call numbers can vary for each port.
> +# Support for all this crud is kept here, rather than trying to get too fancy.
> +# If you want to try to improve this, please do, but don't break anything.
> +# Note that there is a standard syscall.h file (libgloss/syscall.h) now which
> +# hopefully more targets can use.
> +#
> +# NB: New ports should use libgloss, not newlib.
> +TARGET_DIRS = {
> + 'cr16': 'libgloss/cr16/sys',
> + 'd10v': 'newlib/libc/sys/d10v/sys',
> + 'i960': 'libgloss/i960',
> + 'mcore': 'libgloss/mcore',
> + 'v850': 'libgloss/v850/sys',
> +}
> +TARGETS = {
> + 'bfin',
> + 'cr16',
> + 'd10v',
> + 'fr30',
> + 'frv',
> + 'i960',
> + 'lm32',
> + 'm32r',
> + 'mcore',
> + 'mn10200',
> + 'mn10300',
> + 'msp430',
> + 'pru',
> + 'sparc',
> + 'v850',
> +}
> +
> +# Make sure TARGET_DIRS doesn't gain any typos.
> +assert not set(TARGET_DIRS) - TARGETS
> +
> +# The header for the generated def file.
> +FILE_HEADER = f"""\
> +/* Newlib/libgloss macro values needed by remote target support. */
> +/* This file is machine generated by {PROG}. */\
> +"""
> +
> +
> +def gentvals(output: TextIO, cpp: str, srctype: str, srcdir: Path,
> + headers: Iterable[str],
> + pattern,
Hi,
This is a super tiny comment but you forgot the str type annotatin for
pattern.
Lancelot.
> + target: str = None):
> + """Extract constants from the specified files using a regular expression.
> +
> + We'll run things through the preprocessor.
> + """
> + headers = tuple(headers)
> +
> + # Require all files exist in order to regenerate properly.
> + for header in headers:
> + fullpath = srcdir / header
> + assert fullpath.exists(), f'{fullpath} does not exist'
> +
> + if target is None:
> + print(f'#ifdef {srctype}_defs', file=output)
> + else:
> + print(f'#ifdef NL_TARGET_{target}', file=output)
> + print(f'#ifdef {srctype}_defs', file=output)
> +
> + print('\n'.join(f'/* from {x} */' for x in headers), file=output)
> +
> + if target is None:
> + print(f'/* begin {srctype} target macros */', file=output)
> + else:
> + print(f'/* begin {target} {srctype} target macros */', file=output)
> +
> + # Extract all the symbols.
> + srcfile = ''.join(f'#include <{x}>\n' for x in headers)
> + syms = set()
> + for header in headers:
> + with open(srcdir / header, 'r', encoding='utf-8') as fp:
> + data = fp.read()
> + for line in data.splitlines():
> + m = re.match(r'^#\s*define\s+(' + pattern + ')', line)
> + if m:
> + syms.add(m.group(1))
> + for sym in sorted(syms):
> + srcfile += f'#ifdef {sym}\nDEFVAL {{ "{sym}", {sym} }},\n#endif\n'
> +
> + result = subprocess.run(
> + f'{cpp} -E -I"{srcdir}" -', shell=True, check=True, encoding='utf-8',
> + input=srcfile, capture_output=True)
> + for line in result.stdout.splitlines():
> + if line.startswith('DEFVAL '):
> + print(line[6:].rstrip(), file=output)
> +
> + if target is None:
> + print(f'/* end {srctype} target macros */', file=output)
> + print('#endif', file=output)
> + else:
> + print(f'/* end {target} {srctype} target macros */', file=output)
> + print('#endif', file=output)
> + print('#endif', file=output)
> +
> +
> +def gen_common(output: TextIO, newlib: Path, cpp: str):
> + """Generate the common C library constants.
> +
> + No arch should override these.
> + """
> + gentvals(output, cpp, 'errno', newlib / 'newlib/libc/include',
> + ('errno.h', 'sys/errno.h'), 'E[A-Z0-9]*')
> +
> + gentvals(output, cpp, 'signal', newlib / 'newlib/libc/include',
> + ('signal.h', 'sys/signal.h'), r'SIG[A-Z0-9]*')
> +
> + gentvals(output, cpp, 'open', newlib / 'newlib/libc/include',
> + ('fcntl.h', 'sys/fcntl.h', 'sys/_default_fcntl.h'), r'O_[A-Z0-9]*')
> +
> +
> +def gen_targets(output: TextIO, newlib: Path, cpp: str):
> + """Generate the target-specific lists."""
> + for target in sorted(TARGETS):
> + subdir = TARGET_DIRS.get(target, 'libgloss')
> + gentvals(output, cpp, 'sys', newlib / subdir, ('syscall.h',),
> + r'SYS_[_a-zA-Z0-9]*', target=target)
> +
> +
> +def gen(output: TextIO, newlib: Path, cpp: str):
> + """Generate all the things!"""
> + print(FILE_HEADER, file=output)
> + gen_common(output, newlib, cpp)
> + gen_targets(output, newlib, cpp)
> +
> +
> +def get_parser() -> argparse.ArgumentParser:
> + """Get CLI parser."""
> + parser = argparse.ArgumentParser(
> + description=__doc__,
> + formatter_class=argparse.RawDescriptionHelpFormatter)
> + parser.add_argument(
> + '-o', '--output', type=Path,
> + help='write to the specified file instead of stdout')
> + parser.add_argument(
> + '--cpp', type=str, default='cpp',
> + help='the preprocessor to use')
> + parser.add_argument(
> + '--srcroot', type=Path,
> + help='the root of this source tree')
> + parser.add_argument(
> + 'newlib', nargs='?', type=Path,
> + help='path to the newlib+libgloss source tree')
> + return parser
> +
> +
> +def parse_args(argv: List[str]) -> argparse.Namespace:
> + """Process the command line & default options."""
> + parser = get_parser()
> + opts = parser.parse_args(argv)
> +
> + if opts.srcroot is None:
> + opts.srcroot = Path(__file__).resolve().parent.parent.parent
> +
> + if opts.newlib is None:
> + # Try to find newlib relative to our source tree.
> + if (opts.srcroot / 'newlib').is_dir():
> + # If newlib is manually in the same source tree, use it.
> + if (opts.srcroot / 'libgloss').is_dir():
> + opts.newlib = opts.srcroot
> + else:
> + opts.newlib = opts.srcroot / 'newlib'
> + elif (opts.srcroot.parent / 'newlib').is_dir():
> + # Or see if it's alongside the gdb/binutils repo.
> + opts.newlib = opts.srcroot.parent / 'newlib'
> + if opts.newlib is None or not opts.newlib.is_dir():
> + parser.error('unable to find newlib')
> +
> + return opts
> +
> +
> +def main(argv: List[str]) -> int:
> + """The main entry point for scripts."""
> + opts = parse_args(argv)
> +
> + if opts.output is not None:
> + output = open(opts.output, 'w', encoding='utf-8')
> + else:
> + output = sys.stdout
> +
> + gen(output, opts.newlib, opts.cpp)
> + return 0
> +
> +
> +if __name__ == '__main__':
> + sys.exit(main(sys.argv[1:]))
> diff --git a/sim/common/gennltvals.sh b/sim/common/gennltvals.sh
> deleted file mode 100755
> index 869cba273ccf..000000000000
> --- a/sim/common/gennltvals.sh
> +++ /dev/null
> @@ -1,238 +0,0 @@
> -#! /bin/sh
> -# Copyright (C) 1996-2021 Free Software Foundation, Inc.
> -#
> -# This file is part of the GNU simulators.
> -#
> -# This program is free software; you can redistribute it and/or modify
> -# it under the terms of the GNU General Public License as published by
> -# the Free Software Foundation; either version 3 of the License, or
> -# (at your option) any later version.
> -#
> -# This program is distributed in the hope that it will be useful,
> -# but WITHOUT ANY WARRANTY; without even the implied warranty of
> -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> -# GNU General Public License for more details.
> -#
> -# You should have received a copy of the GNU General Public License
> -# along with this program. If not, see <http://www.gnu.org/licenses/>.
> -
> -# Display the tool usage and exit.
> -usage() {
> - cat <<EOF
> -Usage: $0 [path to newlib source tree]
> -
> -Generate nltvals.def, a file that describes various newlib/libgloss target
> -values used by the host/target interface. This needs to be rerun whenever
> -the newlib source changes. Developers manually run it.
> -
> -If the path to newlib is not specified, it will be searched for in:
> -- the root of this source tree
> -- alongside this source tree
> -
> -Options:
> - -o, --output <file> Write to the specified file instead of stdout.
> - --cpp <cpp> The preprocessor to use.
> - --srcroot <dir> The root of this source tree.
> - -h, --help This text you're reading!
> -EOF
> - if [ $# -gt 0 ]; then
> - error "$*"
> - fi
> - exit 0
> -}
> -
> -# Show an error message and exit.
> -error() {
> - echo "$0: error: $*" >&2
> - exit 1
> -}
> -
> -ARG_CPP="cpp"
> -ARG_SRCROOT=""
> -ARG_NEWLIB=""
> -ARG_OUTPUT=""
> -
> -# Emit the header for this generated def file.
> -gen_header() {
> - cat <<EOF
> -/* Newlib/libgloss macro values needed by remote target support. */
> -/* This file is machine generated by gennltvals.sh. */
> -EOF
> -}
> -
> -# Extract constants from the specified files using a regular expression and the
> -# preprocessor.
> -gentvals() {
> - target=$1
> - type=$2
> - dir=$3
> - # FIXME: Would be nice to process #include's in these files.
> - files=$4
> - pattern=$5
> -
> - # Require all files exist in order to regenerate properly.
> - for f in ${files}; do
> - if [ ! -f "${dir}/${f}" ]; then
> - error "file does not exist: ${dir}/${f}"
> - fi
> - done
> -
> - if [ -z "${target}" ]; then
> - echo "#ifdef ${type}_defs"
> - else
> - echo "#ifdef NL_TARGET_${target}"
> - echo "#ifdef ${type}_defs"
> - fi
> -
> - printf "/* from %s */\n" ${files}
> -
> - if [ -z "${target}" ]; then
> - echo "/* begin ${type} target macros */"
> - else
> - echo "/* begin ${target} ${type} target macros */"
> - fi
> -
> - # Extract all the symbols.
> - (
> - printf '#include <%s>\n' ${files}
> - for f in ${files}; do
> - sed -E -n -e "/^# *define[[:space:]]${pattern}/{\
> - s|# *define[[:space:]](${pattern})[[:space:]]*([^[:space:]][^[:space:]]*).*$|\1|; \
> - p}" \
> - "${dir}/${f}"
> - done |
> - sort -u |
> - while read -r sym; do
> - echo "#ifdef ${sym}"
> - echo "DEFVAL { \"${sym}\", ${sym} },"
> - echo "#endif"
> - done
> - ) |
> - ${ARG_CPP} -E -I"${dir}" - |
> - sed -E -n -e '/^DEFVAL/{s/DEFVAL//; s/[[:space:]]+/ /; p}'
> -
> - if [ -z "${target}" ]; then
> - echo "/* end ${type} target macros */"
> - echo "#endif"
> - else
> - echo "/* end ${target} ${type} target macros */"
> - echo "#endif"
> - echo "#endif"
> - fi
> -}
> -
> -# Generate the common C library constants. No arch should override these.
> -gen_common() {
> - gentvals "" errno ${ARG_NEWLIB}/newlib/libc/include \
> - "errno.h sys/errno.h" 'E[[:upper:][:digit:]]*'
> -
> - gentvals "" signal ${ARG_NEWLIB}/newlib/libc/include \
> - "signal.h sys/signal.h" 'SIG[[:upper:][:digit:]]*'
> -
> - gentvals "" open ${ARG_NEWLIB}/newlib/libc/include \
> - "fcntl.h sys/fcntl.h sys/_default_fcntl.h" 'O_[[:upper:][:digit:]]*'
> -}
> -
> -# Unfortunately, each newlib/libgloss port has seen fit to define their own
> -# syscall.h file. This means that system call numbers can vary for each port.
> -# Support for all this crud is kept here, rather than trying to get too fancy.
> -# If you want to try to improve this, please do, but don't break anything.
> -# Note that there is a standard syscall.h file (libgloss/syscall.h) now which
> -# hopefully more targets can use.
> -#
> -# NB: New ports should use libgloss, not newlib.
> -gen_arch() {
> - target="$1"
> - dir="${2:-libgloss}"
> - gentvals "${target}" sys "${ARG_NEWLIB}/${dir}" "syscall.h" 'SYS_[_[:alnum:]]*'
> -}
> -
> -gen_arches() {
> - gen_arch bfin
> - gen_arch cr16 libgloss/cr16/sys
> - gen_arch d10v newlib/libc/sys/d10v/sys
> - gen_arch fr30
> - gen_arch frv
> - gen_arch i960 libgloss/i960
> - gen_arch lm32
> - gen_arch m32r
> - gen_arch mcore libgloss/mcore
> - gen_arch mn10200
> - gen_arch mn10300
> - gen_arch msp430
> - gen_arch pru
> - gen_arch sparc
> - gen_arch v850 libgloss/v850/sys
> -}
> -
> -# Process the script command line options.
> -parse_opts() {
> - while [ $# -gt 0 ]; do
> - case $1 in
> - --cpp)
> - ARG_CPP="$2"
> - shift
> - ;;
> - -o|--output)
> - ARG_OUTPUT="$2"
> - shift
> - ;;
> - --srcroot)
> - ARG_SRCROOT="$2"
> - shift
> - ;;
> - -h|--help)
> - usage
> - ;;
> - --)
> - shift
> - break
> - ;;
> - -*)
> - usage "unknown option: $1"
> - ;;
> - *)
> - break
> - ;;
> - esac
> - shift
> - done
> -
> - if [ $# -gt 2 ]; then
> - error "too many arguments: $*"
> - elif [ $# -eq 1 ]; then
> - ARG_NEWLIB="$1"
> - fi
> -
> - # Try to find newlib relative to our source tree.
> - if [ -z "${ARG_NEWLIB}" ]; then
> - if [ -z "${ARG_SRCROOT}" ]; then
> - ARG_SRCROOT="$(dirname "$0")/../.."
> - fi
> - if [ -d "${ARG_SRCROOT}/newlib" ]; then
> - # If newlib is manually in the same source tree, use it.
> - ARG_NEWLIB="${ARG_SRCROOT}/newlib"
> - elif [ -d "${ARG_SRCROOT}/../newlib" ]; then
> - # Or see if it's alongside the gdb/binutils repo.
> - ARG_NEWLIB="${ARG_SRCROOT}/../newlib"
> - else
> - error "unable to find newlib"
> - fi
> - fi
> -}
> -
> -main() {
> - # The error checking isn't perfect, but should be good enough for this script.
> - set -e
> -
> - parse_opts "$@"
> -
> - if [ -n "${ARG_OUTPUT}" ]; then
> - exec >"${ARG_OUTPUT}" || exit 1
> - fi
> -
> - gen_header
> - gen_common
> - gen_arches
> -}
> -main "$@"
> diff --git a/sim/common/nltvals.def b/sim/common/nltvals.def
> index a196be2420e9..4ab05642d126 100644
> --- a/sim/common/nltvals.def
> +++ b/sim/common/nltvals.def
> @@ -1,5 +1,5 @@
> /* Newlib/libgloss macro values needed by remote target support. */
> -/* This file is machine generated by gennltvals.sh. */
> +/* This file is machine generated by gennltvals.py. */
> #ifdef errno_defs
> /* from errno.h */
> /* from sys/errno.h */
> @@ -604,6 +604,7 @@
> { "SYS_rename", 134 },
> { "SYS_stat", 38 },
> { "SYS_time", 23 },
> + { "SYS_times", 43 },
> { "SYS_unlink", 10 },
> { "SYS_utime", 201 },
> { "SYS_wait", 202 },
> --
> 2.28.0
>
--
Lancelot SIX
More information about the Gdb-patches
mailing list