From 9a7ba4aa0ed5bd60fd01bf0817692212a854bf78 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 18 Jan 2021 22:59:19 -0500 Subject: [PATCH] sim: common: change gennltvals helper to Python This tool is only run by developers and not in a release build, so rewrite it in Python to make it more maintainable. --- sim/ChangeLog | 4 + sim/Makefile.in | 2 +- sim/common/ChangeLog | 6 + sim/common/gennltvals.py | 230 +++++++++++++++++++++++++++++++++++++ sim/common/gennltvals.sh | 238 --------------------------------------- sim/common/nltvals.def | 3 +- 6 files changed, 243 insertions(+), 240 deletions(-) create mode 100755 sim/common/gennltvals.py delete mode 100755 sim/common/gennltvals.sh diff --git a/sim/ChangeLog b/sim/ChangeLog index 5e1ebca21ee..47aae1aaf5b 100644 --- a/sim/ChangeLog +++ b/sim/ChangeLog @@ -1,3 +1,7 @@ +2021-01-30 Mike Frysinger + + * Makefile.in (nltvals): Change to gennltvals.py. + 2021-01-30 Mike Frysinger * README-HACKING: Delete reference to sizeof_pc. diff --git a/sim/Makefile.in b/sim/Makefile.in index a35f807d6f0..1a2dbb145e6 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/ChangeLog b/sim/common/ChangeLog index c7d64392882..a00866dcd46 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,9 @@ +2021-01-30 Mike Frysinger + + * gennltvals.sh: Replace shell script with ... + * gennltvals.py: ... this Python script. + * nltvals.def: Regenerate. + 2021-01-30 Mike Frysinger * sim-watch.c (schedule_watchpoint): Change sizeof_pc to sizeof diff --git a/sim/common/gennltvals.py b/sim/common/gennltvals.py new file mode 100755 index 00000000000..3ca510d0388 --- /dev/null +++ b/sim/common/gennltvals.py @@ -0,0 +1,230 @@ +#!/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 . + +"""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: str, + 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() + define_pattern = re.compile(r'^#\s*define\s+(' + pattern + ')') + for header in headers: + with open(srcdir / header, 'r', encoding='utf-8') as fp: + data = fp.read() + for line in data.splitlines(): + m = define_pattern.match(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 869cba273cc..00000000000 --- 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 . - -# Display the tool usage and exit. -usage() { - cat < Write to the specified file instead of stdout. - --cpp The preprocessor to use. - --srcroot 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 <\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 a196be2420e..4ab05642d12 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.30.2