#! /bin/sh
-# Generate nltvals.def, a file that describes various newlib/libgloss
-# target values used by the host/target interface.
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
#
-# Syntax: /bin/sh gennltvals.sh shell srcroot cpp
-
-shell=$1
-srcroot=$2
-cpp=$3
-
-srccom=$srcroot/sim/common
-if [ -d "${srcroot}/newlib" ]; then
- # If newlib is manually in the same source tree, use it.
- newlibroot=${srcroot}
-else
- # Else assume it's alongside the gdb/binutils repo.
- newlibroot=${srcroot}/../newlib
-fi
-
-echo '/* Newlib/libgloss macro values needed by remote target support. */'
-echo '/* This file is machine generated by gennltvals.sh. */'
-
-$shell ${srccom}/gentvals.sh "" errno ${newlibroot}/newlib/libc/include \
- "errno.h sys/errno.h" 'E[[:upper:][:digit:]]*' "${cpp}"
-
-$shell ${srccom}/gentvals.sh "" signal ${newlibroot}/newlib/libc/include \
- "signal.h sys/signal.h" 'SIG[[:upper:][:digit:]]*' "${cpp}"
-
-$shell ${srccom}/gentvals.sh "" open ${newlibroot}/newlib/libc/include \
- "fcntl.h sys/fcntl.h sys/_default_fcntl.h" 'O_[[:upper:][:digit:]]*' "${cpp}"
+# 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.
# 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.
-
-dir=libgloss target=bfin
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=newlib/libc/sys/d10v/sys target=d10v
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-# OBSOLETE dir=libgloss target=d30v
-# OBSOLETE $shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
-# OBSOLETE "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss/cr16/sys target=cr16
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss target=fr30
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss target=frv
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss/i960 target=i960
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss target=m32r
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss/mcore target=mcore
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss target=mn10200
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss target=mn10300
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss target=msp430
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss target=sparc
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss/v850/sys target=v850
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss target=lm32
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
-
-dir=libgloss target=pru
-$shell ${srccom}/gentvals.sh $target sys ${newlibroot}/$dir \
- "syscall.h" 'SYS_[_[:alnum:]]*' "${cpp}"
+#
+# 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 d10v newlib/libc/sys/d10v/sys
+ gen_arch cr16 libgloss/cr16/sys
+ gen_arch fr30
+ gen_arch frv
+ gen_arch i960 libgloss/i960
+ gen_arch m32r
+ gen_arch mcore libgloss/mcore
+ gen_arch mn10200
+ gen_arch mn10300
+ gen_arch msp430
+ gen_arch sparc
+ gen_arch v850 libgloss/v850/sys
+ gen_arch lm32
+ gen_arch pru
+}
+
+# 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 "$@"