dejagnu
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

PATCH: add dejagnu(1) multi-launcher [revised]


From: Jacob Bachmeyer
Subject: PATCH: add dejagnu(1) multi-launcher [revised]
Date: Thu, 20 Dec 2018 01:05:45 -0600
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1.22) Gecko/20090807 MultiZilla/1.8.3.4e SeaMonkey/1.1.17 Mnenhy/0.7.6.0

This patch is the long-promised dejagnu(1) multi-launcher, revised to include also its first command "dejagnu help" in this patch to ensure that it works properly.

I had previously mentioned some files that were part of this work that have been renamed between then and now. Specifically, "testsuite/lib/dejagnu.exp" is now "testsuite/lib/launcher.exp" and the entire "testsuite/dejagnu.launcher/" directory has been renamed to "testsuite/launcher.all/" after I decided that, since the launcher is run using a LAUNCHER variable rather than a DEJAGNU variable (obvious potential for confusion with that bad choice that was avoided from the start), using "--tool launcher" to test the launcher is more appropriate than using "--tool dejagnu" even though the launcher is installed under the "dejagnu" name.

Notable differences from the previous version of this patch include a small change to dejagnu(1) to prevent shellcheck from complaining. There are also some insignificant changes to doc/dejagnu.1. The new "dejagnu help" command is included in this patch, complete with documentation and tests. This patch also includes the update to Makefile.am that was missing previously.

----
NEWS item:
X. A shell command "dejagnu" is added as a place to hang various auxiliary
  commands not directly involved with running tests.  The "runtest"
  command will remain for that purpose for the forseeable future.

ChangeLog entries:
        * Makefile.am (EXTRA_DIST): Add "dejagnu" launcher script and
        contents of $(commands_DATA).
        (bin_SCRIPTS): Add "dejagnu" launcher script.
        (commandsdir): Installation directory for "dejagnu" subcommands is
        $(pkgdatadir)/commands.
        (commands_DATA): New, contains "commands/help.sh" as initial item.
        (TESTSUITE_FILES): Add testsuite for same.
        (DEJATOOL): Add "launcher" to list of tools to test.
        (dist_man_MANS): Add man pages for "dejagnu" and "dejagnu help".

        * doc/dejagnu.texi (Running other DejaGnu commands): New chapter.
        (Invoking dejagnu): New node for dejagnu(1) launcher script.
        (Invoking dejagnu help): New node.

        * doc/dejagnu.1: New man page.
        * doc/dejagnu-help.1: New man page.

        * dejagnu: New script.

        * commands/help.sh: New dejagnu subcommand for reading manpages.

        * testsuite/launcher.all/command.exp: New file.
        * testsuite/launcher.all/command/commands/bar-baz.awk: New file.
        * testsuite/launcher.all/command/commands/bar.awk: New file.
        * testsuite/launcher.all/command/commands/bar.sh: New file.
        * testsuite/launcher.all/command/commands/baz-quux.gawk: New file.
        * testsuite/launcher.all/command/commands/foo.sh: New file.
        * testsuite/launcher.all/command/commands/foo.tcl: New file.
        * testsuite/launcher.all/help.exp: New file.
        * testsuite/launcher.all/interp.exp: New file.
        * testsuite/launcher.all/verbose.exp: New file.
        * testsuite/lib/launcher.exp: New file.
----
patch:
----
diff --git a/Makefile.am b/Makefile.am
index 1740d1a..1f19846 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 1992-2016 Free Software Foundation, Inc.
+# Copyright (C) 1992-2016, 2018 Free Software Foundation, Inc.
#
# This file is part of DejaGnu.
#
@@ -21,9 +21,10 @@
AUTOMAKE_OPTIONS = dejagnu
export DEJAGNU

-EXTRA_DIST = ChangeLog-1992 MAINTAINERS runtest \
+EXTRA_DIST = ChangeLog-1992 MAINTAINERS dejagnu runtest \
        $(pkgdata_DATA) $(config_DATA) $(baseboard_DATA) \
-       $(TESTSUITE_FILES) $(XML) $(CONTRIB) $(TEXINFO_TEX)
+       $(commands_DATA) $(TESTSUITE_FILES) $(TEXINFO_TEX)\
+       $(XML) $(CONTRIB)

DISTCLEANFILES = options-init.exp stats-init.exp

@@ -31,7 +32,7 @@ DISTCLEANFILES = options-init.exp stats-init.exp
all-local:
        @echo "Done. Now run 'make install'."

-bin_SCRIPTS = runtest
+bin_SCRIPTS = dejagnu runtest
include_HEADERS = dejagnu.h

pkgdata_DATA = \
@@ -57,6 +58,10 @@ pkgdata_DATA = \
  lib/tip.exp \
  lib/utils.exp

+commandsdir = $(pkgdatadir)/commands
+commands_DATA = \
+       commands/help.sh
+
configdir = $(pkgdatadir)/config
config_DATA = \
        config/README \
@@ -142,6 +147,16 @@ CONTRIB = contrib/compare_tests contrib/sum2junit.sh \
# Testsuite.

TESTSUITE_FILES = \
+       testsuite/launcher.all/command.exp \
+       testsuite/launcher.all/command/commands/bar-baz.awk \
+       testsuite/launcher.all/command/commands/bar.awk \
+       testsuite/launcher.all/command/commands/bar.sh \
+       testsuite/launcher.all/command/commands/baz-quux.gawk \
+       testsuite/launcher.all/command/commands/foo.sh \
+       testsuite/launcher.all/command/commands/foo.tcl \
+       testsuite/launcher.all/help.exp \
+       testsuite/launcher.all/interp.exp \
+       testsuite/launcher.all/verbose.exp \
        testsuite/runtest.libs/topdir/subdir1/subsubdir1/subsubfile1 \
        testsuite/runtest.libs/topdir/subdir1/subfile1 \
        testsuite/runtest.libs/topdir/subdir1/subfile2 \
@@ -158,13 +173,14 @@ TESTSUITE_FILES = \
        testsuite/runtest.main/options/testsuite/null.test/null.exp \
        testsuite/runtest.main/stats.exp \
        testsuite/runtest.main/stats/testsuite/stat.test/stats-sub.exp \
+       testsuite/lib/launcher.exp \
        testsuite/lib/libdejagnu.exp \
        testsuite/lib/libsup.exp \
        testsuite/lib/runtest.exp \
        testsuite/lib/util-defs.exp \
        testsuite/libdejagnu/tunit.exp

-DEJATOOL = libdejagnu runtest
+DEJATOOL = launcher libdejagnu runtest

RUNTEST = ${top_srcdir}/runtest

@@ -175,5 +191,5 @@ unit_SOURCES = testsuite/libdejagnu/unit.cc
# Documentation.

TEXINFO_TEX = doc/texinfo.tex
-dist_man_MANS = doc/runtest.1
+dist_man_MANS = doc/dejagnu.1 doc/dejagnu-help.1 doc/runtest.1
info_TEXINFOS = doc/dejagnu.texi
diff --git a/commands/help.sh b/commands/help.sh
new file mode 100644
index 0000000..7da4d5f
--- /dev/null
+++ b/commands/help.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+# help.sh -- "dejagnu help" command
+#
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of DejaGnu.
+#
+# DejaGnu 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.
+#
+# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+# ##help
+# #Usage: dejagnu help [options...] <command>
+# #    --verbose, -v           Emit additional messages
+# #    --path, -w              Passed to man(1)
+# #    -W                      Passed to man(1)
+# ##end
+
+# This script was written by Jacob Bachmeyer.
+
+args=
+command=dejagnu
+verbose=0
+for a in "$@"; do
+    case $a in
+       -v|--v|-verb*|--verb*)  verbose=$((verbose + 1)) ;;
+       -w|-W|--path)           args="${args} ${a}" ;;
+       -*)                     echo Unrecognized option "\"$a\"" ;;
+       *)                      command="${command}-${a}" ;;
+    esac
+done
+
+if expr "$verbose" \> 0 > /dev/null ; then
+    echo Verbose level is $verbose
+fi
+
+## Get the location of this script and check for nearby "doc" dir.
+commdir="$(echo "$0" | sed -e 's@/[^/]*$@@')"
+docdir="$(echo "$commdir" | sed -e 's@/[^/]*$@@')/doc"
+
+if expr "$verbose" \> 0 > /dev/null ; then
+    echo Running from "$commdir"
+    if expr "$verbose" \> 1 > /dev/null ; then
+       echo Probing "$docdir"
+    fi
+fi
+
+if test -d "$docdir"; then
+    if expr "$verbose" \> 1 > /dev/null ; then
+       echo Probing "${docdir}/${command}.1"
+    fi
+    if test -r "${docdir}/${command}.1" ; then
+       command="${docdir}/${command}.1"
+    fi
+fi
+
+# Word splitting on the "args" variable is intended.
+# Globbing is not, but ensure that verbose output will show the problem.
+
+if expr "$verbose" \> 0 > /dev/null ; then
+    #shellcheck disable=SC2086
+    echo Forwarding to man $args "\"$command\""
+fi
+
+#shellcheck disable=SC2086
+exec man $args "$command"
+
+#EOF
diff --git a/dejagnu b/dejagnu
new file mode 100755
index 0000000..4b174db
--- /dev/null
+++ b/dejagnu
@@ -0,0 +1,453 @@
+#!/bin/sh
+#
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of DejaGnu.
+#
+# DejaGnu 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.
+#
+# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Portions from runtest Copyright (C) 1992-2016 Free Software Foundation, Inc.
+
+# This script was written by Jacob Bachmeyer.  Portions of this script are
+# adapted from the existing runtest script originally written by Rob Savoye.
+
+# This script finds an implementation for the command given, finds the
+# proper interpreter, and then dispatches the command.  This script can
+# either be run with a command name as the first (few) argument(s), via a
+# link from the command name, or some combination of those.
+
+# shellcheck disable=SC2209
+# The shellcheck tool complains about assigning certain constant strings to
+# variables.  In this script, the intended meaning is obvious in context.
+
+# ##help
+# #Usage: dejagnu <command> [--help|options...]
+# #Usage: dejagnu --help
+# #Usage: dejagnu --version
+# #    --help                  Print help text
+# #    --version               Print DejaGnu version
+# ##end
+
+# list of extensions supported for commands in priority order
+readonly Variants="gawk awk tcl exp bash sh"
+
+## Recognize options
+
+# For testing and development
+override_ext=
+if test x"$1" = x--DGTimpl ; then
+    override_ext=$2
+    shift 2
+fi
+
+want_help=false
+want_version=false
+verbose=0
+for a in "$@"; do
+    case $a in
+       --help)                         want_help=true ;;
+       -v|--v|-verbose|--verbose)      verbose=$((verbose + 1)) ;;
+       -V|--V|-version|--version)      want_version=true ;;
+    esac
+done
+
+if expr "$verbose" \> 0 > /dev/null ; then
+    echo Verbose level is $verbose
+fi
+
+## Get the file name of this script and deduce @address@hidden
+
+bindir="$(echo "$0" | sed -e 's@/[^/]*$@@')"
+if expr "$verbose" \> 0 > /dev/null ; then
+    echo Running launcher from "$bindir"
+fi
+
+## Find the commands.
+
+# If running from source tree, they are in ./commands/ relative to this script.
+# If installed, they are in @datadir@/dejagnu/commands/ on the system.
+
+# This makes the same assumption as in runtest that one of these holds:
+#
+#   @datadir@ == @bindir@/../share
+#   @datadir@ == @bindir@/../../share
+#   @datadir@ == /usr/share
+#   @datadir@ == /usr/local/share
+
+if test -n "$DEJAGNULIBS" ; then
+    commdir="${DEJAGNULIBS}/commands"
+    datadir="${DEJAGNULIBS}"
+elif test -d "${bindir}/commands" && test -f "${bindir}/runtest.exp" ; then
+    if expr "$verbose" \> 1 > /dev/null ; then
+       echo Running from source directory
+    fi
+    commdir="${bindir}/commands"
+    datadir="${bindir}"
+else
+    commdir=
+    for i in \
+       "$(echo "$bindir" | sed -e 's@/[^/]*$@/share/dejagnu@')" \
+       "$(echo "$bindir" | sed -e 's@/[^/]*/[^/]*$@/share/dejagnu@')" \
+       /usr/share/dejagnu /usr/local/share/dejagnu
+    do
+       if expr "$verbose" \> 1 > /dev/null ; then
+           echo Probing directory "$i"/commands
+       fi
+       if test -d "$i"/commands ; then
+           commdir="$i"/commands
+           datadir="$i"
+           break
+       fi
+    done
+fi
+
+if test -z "${commdir}" ; then
+    echo ERROR: could not find command directory.
+    exit 2
+fi
+
+if expr "$verbose" \> 0 > /dev/null ; then
+    echo Looking for commands in "$commdir"
+fi
+
+## Get the name of the requested command.
+
+# Are we just looking for version information?
+if $want_version ; then
+    frame_version=$(grep '^set frame_version' "${datadir}/runtest.exp" \
+       | sed 's/^[^0-9]*//')
+    echo 'dejagnu auxiliary launcher (DejaGnu)' "$frame_version"
+    exit 0
+fi
+
+# Remove any leading autoconf platform prefix and the "dejagnu" prefix.
+command="$(basename "$0" | sed -e 's/^.*-\?dejagnu-\?//')"
+commext=
+
+while true
+do
+    if test -z "${command}" ; then
+       if expr "$1" : - > /dev/null ; then
+           break
+       fi
+       command="$1"
+       shift
+    fi
+    if expr "$verbose" \> 2 > /dev/null ; then
+       echo Looking for "${commdir}/${command}.*"
+    fi
+    for ext in ${Variants}
+    do
+       if test -f "${commdir}/${command}.$ext" ; then
+           commext="$commext $ext"
+       fi
+    done
+    if expr "$1" : - > /dev/null ; then
+       break
+    fi
+    if test -n "$commext" ; then
+       break
+    fi
+    if test -n "$1" ; then
+       command="${command}-$1"
+       shift
+    else
+       break
+    fi
+done
+
+if test -z "$commext" && test -n "$command" ; then
+    echo ERROR: could not resolve command "$command"
+    exit 2
+fi
+
+if expr "$verbose" \> 0 > /dev/null ; then
+    if test -n "$command"; then
+       if expr "$verbose" \> 1 > /dev/null ; then
+           echo Found subcommand "$command" with variants: "$commext"
+       else
+           echo Found subcommand "$command"
+       fi
+    else
+       echo Running nothing.
+    fi
+fi
+
+## Find interpreters.
+
+# Awk and GNU awk
+if test -n "$AWK" ; then
+    awkbin="$AWK"
+elif test -x "${bindir}/awk" ; then
+    awkbin="${bindir}/awk"
+else
+    awkbin=awk
+fi
+if test -n "$GAWK" ; then
+    gawkbin="$GAWK"
+elif test -x "${bindir}/gawk" ; then
+    gawkbin="${bindir}/gawk"
+else
+    gawkbin=gawk
+fi
+if command -v "$awkbin" > /dev/null 2>&1 ; then
+    have_awk=true
+else
+    have_awk=false
+fi
+if command -v "$gawkbin" > /dev/null 2>&1 ; then
+    have_gawk=true
+else
+    have_gawk=false
+fi
+# substitute GNU awk for awk if needed
+if $have_gawk ; then
+    if $have_awk ; then : ; else
+       have_awk=$have_gawk
+       awkbin=$gawkbin
+    fi
+fi
+# is "awk" actually GNU Awk?
+if $have_awk ; then
+    if "$awkbin" --version | sed 1q | grep -qi 'GNU Awk' ; then
+       have_gawk_as_awk=true
+    else
+       have_gawk_as_awk=false
+    fi
+fi
+if expr "$verbose" \> 2 > /dev/null ; then
+    if $have_awk ; then
+       echo Awk interpreter is "$awkbin"
+    else
+       echo Awk interpreter was not found
+    fi
+    if $have_gawk ; then
+       echo GNU Awk interpreter is "$gawkbin"
+    else
+       echo GNU Awk interpreter was not found
+    fi
+fi
+
+
+# Bash
+if test -n "$BASH" ; then
+    bashbin="$BASH"
+elif test -x "${bindir}/bash" ; then
+    bashbin="${bindir}/bash"
+elif test -x /bin/bash ; then
+    bashbin=/bin/bash
+else
+    bashbin=bash
+fi
+if command -v "$bashbin" > /dev/null 2>&1 ; then
+    have_bash=true
+else
+    have_bash=false
+fi
+if expr "$verbose" \> 2 > /dev/null ; then
+    if $have_bash ; then
+       echo Bash interpreter is "$bashbin"
+    else
+       echo Bash interpreter was not found
+    fi
+fi
+
+# Bourne shell
+#  This script is running, therefore we have a Bourne shell.
+have_sh=true
+
+# Expect
+#  DejaGnu configure bails out if Expect is not available, but this script
+#  can be run from the source directory without first running configure.
+if test -n "$EXPECT" ; then
+    expectbin="$EXPECT"
+elif test -x "${bindir}/expect" ; then
+    expectbin="${bindir}/expect"
+else
+    expectbin=expect
+fi
+if command -v "$expectbin" > /dev/null 2>&1 ; then
+    have_expect=true
+else
+    have_expect=false
+fi
+if expr "$verbose" \> 2 > /dev/null ; then
+    if $have_expect ; then
+       echo Expect interpreter is "$expectbin"
+    else
+       echo Expect interpreter was not found
+    fi
+fi
+
+# Tcl
+if test -n "$TCLSH" ; then
+    tclbin="$TCLSH"
+elif test -x "${bindir}/tclsh" ; then
+    tclbin="${bindir}/tclsh"
+else
+    tclbin=tclsh
+fi
+# substitute expect if needed
+if command -v "$tclbin" > /dev/null 2>&1 ; then :
+elif command -v "$expectbin" > /dev/null 2>&1 ; then tclbin="$expectbin"
+fi
+if command -v "$tclbin" > /dev/null 2>&1 ; then
+    have_tcl=true
+else
+    have_tcl=false
+fi
+if expr "$verbose" \> 2 > /dev/null ; then
+    if $have_tcl ; then
+       echo Tcl interpreter is "$tclbin"
+    else
+       echo Tcl interpreter was not found
+    fi
+fi
+
+## Select a variant.
+
+if test -n "$override_ext" ; then
+    selected_ext="$override_ext"
+else
+    selected_ext=
+    for v in $commext
+    do
+       case $v in
+           awk)
+               if $have_awk ; then
+                   selected_ext=awk
+                   break
+               fi
+               ;;
+           bash)
+               if $have_bash ; then
+                   selected_ext=bash
+                   break
+               fi
+               ;;
+           exp)
+               if $have_expect ; then
+                   selected_ext=exp
+                   break
+               fi
+               ;;
+           gawk)
+               if $have_gawk ; then
+                   selected_ext=gawk
+                   break
+               fi
+               ;;
+           tcl)
+               if $have_tcl ; then
+                   selected_ext=tcl
+                   break
+               fi
+               ;;
+           sh)
+               selected_ext=sh
+               break
+               ;;
+           *)
+               echo ERROR: '(select-variant)' unrecognized variant "$v"
+               ;;
+       esac
+    done
+    if test -z "$selected_ext" && test -n "$command" ; then
+       echo ERROR: no variant of "$command" was selected
+       exit 2
+    fi
+fi
+
+if test -n "$command" && expr "$verbose" \> 0 > /dev/null ; then
+    if test -n "$override_ext" ; then
+       echo Selected variant "$selected_ext" by override
+    else
+       echo Selected variant "$selected_ext"
+    fi
+fi
+
+## Dispatch to the selected command.
+
+# Are we just looking for a usage message?
+if $want_help ; then
+    if test -z "$command" ; then
+       # want help on the launcher itself
+       help_file=$0
+    else
+       help_file="${commdir}/${command}.${selected_ext}"
+    fi
+    if test ! -r "$help_file" ; then
+       echo ERROR: file "'$help_file'" is not readable
+       exit 2
+    fi
+    if grep -q '#help' "$help_file" \
+       && grep -q '#end' "$help_file"; then : ; else
+       echo ERROR: file "'$help_file'" does not contain a help message
+       exit 2
+    fi
+    help_prefix_pat=$(grep '#help' "$help_file" \
+       | sed 's/#help.*$//;1q' | tr '[:print:][:blank:]' .)
+    if expr "$verbose" \> 1 > /dev/null ; then
+       echo Extracting help from "'$help_file'" with prefix 
"'$help_prefix_pat'"
+    fi
+    sed -n < "$help_file" \
+       -e '1,/#help/d' \
+       -e '/^'"$help_prefix_pat"'#end/q' \
+       -e 's/^'"$help_prefix_pat"'//;p'
+    exit 0
+fi
+
+if test -z "$command" ; then
+    if test -n "$override_ext" ; then
+       case $selected_ext in
+           awk)        $have_awk;      exit $? ;;
+           bash)       $have_bash;     exit $? ;;
+           exp)        $have_expect;   exit $? ;;
+           gawk)       $have_gawk;     exit $? ;;
+           tcl)        $have_tcl;      exit $? ;;
+           sh)         $have_sh;       exit $? ;;
+           *)                          exit  2 ;;
+       esac
+    else
+       echo ERROR: no command given
+       exit 2
+    fi
+fi
+
+case $selected_ext in
+    awk)
+       if $have_gawk_as_awk ; then
+           exec "$awkbin" --posix -f "${commdir}/${command}.awk" -- ${1+"$@"}
+       else
+           exec "$awkbin" -f "${commdir}/${command}.awk" -- ${1+"$@"}
+       fi
+       ;;
+    bash)   exec "$bashbin" -- "${commdir}/${command}.bash" ${1+"$@"} ;;
+    exp)    exec "$expectbin" -- "${commdir}/${command}.exp" ${1+"$@"} ;;
+    gawk)   exec "$gawkbin" -f "${commdir}/${command}.gawk" -- ${1+"$@"} ;;
+    tcl)    exec "$tclbin" "${commdir}/${command}.tcl" ${1+"$@"} ;;
+    sh)     exec /bin/sh "${commdir}/${command}.sh" ${1+"$@"} ;;
+    echo)
+       echo command: "${command}"
+       echo args: ${1+"$@"}
+       exit 0
+       ;;
+    *)
+       echo ERROR: '(run-variant)' unrecognized variant "$selected_ext"
+       exit 2
+       ;;
+esac
+
+#EOF
diff --git a/doc/dejagnu-help.1 b/doc/dejagnu-help.1
new file mode 100644
index 0000000..110da92
--- /dev/null
+++ b/doc/dejagnu-help.1
@@ -0,0 +1,50 @@
+.\" Copyright (C), 2018  Free Software Foundation, Inc.
+.\" You may distribute this file under the terms of the GNU Free
+.\" Documentation License.
+.Dd December 19, 2018
+.Os GNU
+.Dt DEJAGNU-HELP 1 URM
+.Sh NAME
+.Nm dejagnu\ help
+.Nd display manual pages for DejaGnu auxiliary commands
+.Sh SYNOPSIS
+.Nm dejagnu\ help
+.Op Ar options...
+.Ao Ar command Ac
+.Sh DESCRIPTION
+The
+.Nm
+command displays long-form documentation for DejaGnu auxiliary commands.
+.Sh OPTIONS
+.Bl -tag -width ".Fl v , -verbose"
+.It Fl v , -verbose
+Emit additional output describing the operation of
+.Nm
+itself.
+.It Fl w , -path
+This option is simply passed on to
+.Nm man .
+.It Fl W
+This option is simply passed on to
+.Nm man .
+.El
+.Sh FILES
+The
+.Nm
+command checks for man pages in a
+.Pa doc/
+directory next to the
+.Pa commands/
+directory where this script is located.
+If the page is found there, a full file name is given to
+.Nm man .
+Otherwise, only the command name is given and the search described in
+.Xr man 1
+is performed.
+.Sh SEE ALSO
+.Xr man 1
+.Sh AUTHORS
+Jacob Bachmeyer
+.Sh BUGS
+Currently only supports man pages.
+.\"  LocalWords:  Dt URM Nm DejaGnu Ao Xr
diff --git a/doc/dejagnu.1 b/doc/dejagnu.1
new file mode 100644
index 0000000..5ece6c1
--- /dev/null
+++ b/doc/dejagnu.1
@@ -0,0 +1,141 @@
+.\" Copyright (C) 2018  Free Software Foundation, Inc.
+.\" You may distribute this file under the terms of the GNU Free
+.\" Documentation License.
+.Dd December 17, 2018
+.Os GNU
+.Dt DEJAGNU 1 URM
+.Sh NAME
+.Nm dejagnu
+.Nd DejaGnu auxiliary command launcher
+.Sh SYNOPSIS
+.Nm dejagnu
+.Ao Ar command Ac
+.Op Fl -help \*(Ba Ar options...
+.Nm
+.Fl -help
+.Nm
+.Fl -version
+.Sh DESCRIPTION
+The
+.Nm
+command finds a script that implements the requested
+.Ar command ,
+selects from multiple implementations if available
+according to a fixed internal list, and executes the command.
+.Sh OPTIONS
+.Bl -tag -width ".Fl -version"
+.It Fl -help
+Print a help message instead of running a command.
+If no command is given, prints brief usage for
+.Nm
+itself.
+.It Fl V , -version
+Print a version banner for the launcher itself including the version of 
DejaGnu.
+Any command given is ignored.
+.It Fl v , -verbose
+Emit additional output describing the operation of the
+.Nm
+launcher itself.
+This option is also passed on to the invoked command.
+.El
+.Pp
+All arguments after the command name are passed to the invoked command.
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev DEJAGNULIBS"
+.It Ev DEJAGNULIBS
+If set, the location of DejaGnu's library in the filesystem.
+The search described in
+.Sx FILES
+does not happen if
+.Ev DEJAGNULIBS
+is set.
+.It Ev AWK
+Full file name for an Awk interpreter that may or may not actually be GNU Awk.
+If not set,
+.Ev PATH
+will be searched for an
+.Nm awk
+program.
+If the Awk interpreter is actually GNU Awk, the
+.Fl -posix
+option will be given if an Awk implementation is used.
+.It Ev GAWK
+Full file name for GNU Awk.  If not set,
+.Ev PATH
+will be searched for a
+.Nm gawk
+program.
+.It Ev BASH
+Full file name for GNU Bash.  If not set,
+.Ev PATH
+will be searched for a
+.Nm bash
+program.
+Note that Bash itself sets this variable, even when run as
+.Nm sh ,
+even when running a script.
+.It Ev EXPECT
+Full file name for Expect, which is a Tcl interpreter with the Expect
+extension already loaded.  If not set,
+.Ev PATH
+will be searched for an
+.Nm expect
+program.  Note that the DejaGnu core is written in Expect, so this
+interpreter should always be available.
+.It Ev TCLSH
+Full file name for a Tcl interpreter.  If not set,
+.Ev PATH
+will be searched for a
+.Nm tclsh
+program.
+.El
+.Pp
+Note that GNU Awk is considered a superset of Awk and that Expect is
+considered a superset of Tcl, allowing the former to be used to run scripts
+written for the latter.
+This means that, while Awk programs will generally be run with GNU
+extensions disabled using the
+.Fl -posix
+option to GNU Awk, Tcl programs may be run with either
+.Nm tclsh
+or
+.Nm expect
+and should be written accordingly.
+.Sh FILES
+.Bl -tag -width ".Pa $DEJAGNULIBS/commands"
+.It Pa $DEJAGNULIBS/commands
+If
+.Ev DEJAGNULIBS
+is set, all command scripts are expected to be in this directory.
+.El
+Otherwise, the first directory that actually exists in the following list
+is used, where
+.Pa @bindir@
+represents the directory containing
+.Nm
+itself.
+.Bl -item -offset indent
+.It
+.Pa @bindir@/../share/dejagnu/commands
+.It
+.Pa @bindir@/../../share/dejagnu/commands
+.It
+.Pa /usr/share/dejagnu/commands
+.It
+.Pa /usr/local/share/dejagnu/commands
+.El
+.\" .Sh EXAMPLES
+.Sh SEE ALSO
+The full documentation for DejaGnu is maintained as a Texinfo manual.
+If the
+.Nm info
+program is properly installed at your site, the command
+.Li info dejagnu
+should give you access to the complete manual.
+.Sh AUTHORS
+.An "Jacob Bachmeyer"
+.Sh BUGS
+The command name must precede all other arguments due to limitations of the
+shell.
+.\"  LocalWords:  Dt URM Nm DejaGnu Ao DEJAGNULIBS DejaGnu's Sx awk posix tclsh
+.\"  LocalWords:  tcl superset bindir usr Texinfo
diff --git a/doc/dejagnu.texi b/doc/dejagnu.texi
index 7058320..e72f38f 100644
--- a/doc/dejagnu.texi
+++ b/doc/dejagnu.texi
@@ -50,6 +50,7 @@ Free Documentation License''.
@menu
* Introduction::
* Running tests::
+* Running other DejaGnu commands::
* Customizing DejaGnu::
* Extending DejaGnu::
* Unit testing::
@@ -75,6 +76,11 @@ Running tests
* Running runtest: Runtest.
* Output files: Output Files.

+Running other DejaGnu commands
+
+* Invoking dejagnu::            Command line options for the launcher itself.
+* Invoking dejagnu help::      Reading man pages for dejagnu subcommands.
+
Customizing DejaGnu

* Global config file::
@@ -421,7 +427,7 @@ tools you want to test; then, in each test directory, run 
@emph{make
check} to build auxiliary programs required by some of the tests, and
run the test suites.

address@hidden Running tests, Customizing DejaGnu, Introduction, Top
address@hidden Running tests, Running other DejaGnu commands, Introduction, Top
@chapter Running tests

There are two ways to execute a testsuite. The most common way is when
@@ -1008,7 +1014,109 @@ make the actions for fail-safe patterns produce 
messages starting with

@end itemize

address@hidden Customizing DejaGnu, Extending DejaGnu, Running tests, Top
address@hidden Running other DejaGnu commands, Customizing DejaGnu, Running 
tests, Top
address@hidden Running other DejaGnu commands
+
+DejaGnu now features auxiliary commands not directly related to
+running tests, but somehow related to the broader purpose of testing.
+
+These commands are run via the @command{dejagnu} multiplex launcher,
+which locates an appropriate script and the required interpreter and
+then runs the requested command.
+
address@hidden
+* Invoking dejagnu::            Command line options for the launcher itself.
+* Invoking dejagnu help::      Reading man pages for dejagnu subcommands.
address@hidden menu
+
address@hidden Invoking dejagnu, Invoking dejagnu help, Running other DejaGnu 
commands, Running other DejaGnu commands
address@hidden Invoking @command{dejagnu}
address@hidden dejagnu, invoking
+
+The @command{dejagnu} launcher is primarily designed to pass most
+options on to the scripts that it runs, but does process the
address@hidden and @option{--version} options entirely internally,
+while also recognizing the @option{--verbose} option.
+
address@hidden
address@hidden <command> [options...]
address@hidden --help
address@hidden --version
address@hidden example
+
+Note that the command names may contain multiple words.  In this case,
+the command can be given as separate arguments to @command{dejagnu} or
+combined with dashes (@samp{-}); both forms are equivalent.
+
+All words of the command name must appear before any options.  The
+search for a command terminates when an option is found.
+
+Note that the first valid command found is used.  A longer command
+name can be shadowed by a shorter command name that happens to be a
+prefix of the longer name, if the command name is given as multiple
+arguments.  The equivalent form with the longer command name combined
+using dashes into a single argument will correctly refer to the
+otherwise shadowed command.
+
+The @command{dejagnu} launcher can also be run using symbolic links,
+provided that the shell places the name under which @command{dejagnu}
+was invoked in @code{$0}.  Any dash-separated words after ``dejagnu''
+in the name of such a link are taken to be the leading words of a
+command name.
+
+The @command{dejagnu} launcher supports alternate implementations
+depending upon available interpreters.
+
+Options for the @command{dejagnu} launcher itself cannot be
+abbreviated, since the launcher has no way to know which abbreviations
+are unique and which would be ambiguous to the invoked command.
+
address@hidden @asis
+
address@hidden @code{--help}
+Print a help message instead of running a command.
+
address@hidden @code{-V}, @code{--version}
+Print a version banner for the launcher itself including the
+version of DejaGnu.  Any command given is ignored.
+
address@hidden @code{-v}, @code{--verbose}
+Emit additional output describing the inner workings of the
address@hidden launcher.  This option is also passed on to the
+invoked command.
+
address@hidden table
+
+All arguments after the command name are passed to the invoked command.
+
address@hidden Invoking dejagnu help,  , Invoking dejagnu, Running other 
DejaGnu commands
address@hidden Invoking @command{dejagnu help}
address@hidden dejagnu help, invoking
+
+The @command{dejagnu help} tool displays long-form documentation for
+DejaGnu auxiliary commands that are invoked using the
address@hidden launcher.
+
address@hidden
address@hidden help} [options...] <command>
address@hidden example
+
+Again, command names may contain multiple words.  This command forms
+an operand by joining all words in the command name using dashes
+(@samp{-}) and prepending @samp{dejagnu-}.  This is then used as the
+name of a manual page and passed to the @command{man} command.
+
+If the manual page is in a particular directory relative to the script
+implementing this command, a full file name is produced, otherwise,
address@hidden performs its normal search.
+
+The @option{--verbose} option causes additional output describing the
+inner workings of the @command{dejagnu help} command to be produced.
+
+The @option{--path}, @option{-w}, and @option{-W} options are passed
+to @command{man}.
+
address@hidden Customizing DejaGnu, Extending DejaGnu, Running other DejaGnu 
commands, Top
@chapter Customizing DejaGnu
@cindex customization

@@ -5502,4 +5610,4 @@ This makes @code{runtest} exit. Abbreviation: @kbd{q}.
@bye

@c  LocalWords:  subdirectory prepend prepended testsuite filename Expect's svn
address@hidden  LocalWords:  DejaGnu CVS RCS SCCS
address@hidden  LocalWords:  DejaGnu CVS RCS SCCS prepending subcommands
diff --git a/testsuite/launcher.all/command.exp 
b/testsuite/launcher.all/command.exp
new file mode 100644
index 0000000..eb7b219
--- /dev/null
+++ b/testsuite/launcher.all/command.exp
@@ -0,0 +1,210 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of DejaGnu.
+#
+# DejaGnu 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.
+#
+# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+# This file was written by Jacob Bachmeyer.
+
+# each element:  { launcher_alias
+#                      { name args envars exit_code output_re... }... }
+set tests {
+    { dejagnu
+       { "#" direct calls }
+
+       { "dejagnu foo as Tcl"
+           {foo -v -v} {EXPECT=true  TCLSH=true } 0
+           "Found subcommand foo with variants:  tcl sh\n"
+           "Selected variant tcl" }
+       { "dejagnu foo as Tcl via Expect"
+           {foo -v -v} {EXPECT=true  TCLSH=bogus} 0
+           "Found subcommand foo with variants:  tcl sh\n"
+           "Selected variant tcl" }
+       { "dejagnu foo as shell"
+           {foo -v -v} {EXPECT=bogus TCLSH=bogus} 0
+           "Found subcommand foo with variants:  tcl sh\n"
+           "Selected variant sh" }
+
+       { "dejagnu bar as Awk"
+           {bar -v -v} {AWK=true  GAWK=true } 0
+           "Found subcommand bar with variants:  awk sh\n"
+           "Selected variant awk" }
+       { "dejagnu bar as Awk via GNU Awk"
+           {bar -v -v} {AWK=bogus GAWK=true } 0
+           "Found subcommand bar with variants:  awk sh\n"
+           "Selected variant awk" }
+       { "dejagnu bar as shell"
+           {bar -v -v} {AWK=bogus GAWK=bogus} 0
+           "Found subcommand bar with variants:  awk sh\n"
+           "Selected variant sh" }
+
+       { "dejagnu bar shadows bar-baz"
+           {bar baz -v -v} {AWK=true} 0
+           "Found subcommand bar with variants:  awk sh" }
+       { "dejagnu bar-baz works"
+           {bar-baz -v -v} {AWK=true} 0
+           "Found subcommand bar-baz with variants:  awk" }
+       { "dejagnu bar-baz fails without Awk"
+           {bar-baz -v -v} {AWK=bogus GAWK=bogus} 2
+           "Found subcommand bar-baz with variants:  awk\n"
+           "ERROR: no variant of bar-baz was selected" }
+
+       { "dejagnu baz-quux works"
+           {baz-quux -v -v} {GAWK=true} 0
+           "Found subcommand baz-quux with variants:  gawk\n"
+           "Selected variant gawk" }
+       { "dejagnu baz quux works"
+           {baz quux -v -v} {GAWK=true} 0
+           "Found subcommand baz-quux with variants:  gawk\n"
+           "Selected variant gawk" }
+
+       { "#" invalid direct calls }
+
+       { "dejagnu -v bar fails"      {-v bar} {} 2
+           "Running nothing.\nERROR: no command given" }
+
+       { "dejagnu \"\" bar fails"  {"" bar} {} 2 "ERROR: " }
+       { "dejagnu \"\" \"\" bar fails"   {"" "" bar} {} 2 "ERROR: " }
+
+       { "dejagnu baz \"\" quux fails"     {baz "" quux} {GAWK=true} 2 "ERROR: 
" }
+
+       { "dejagnu bar \"\" baz finds bar subcommand"
+           {--DGTimpl echo bar "" baz} {} 0
+           "command: bar\nargs:  baz" }
+
+       { "#" help system }
+
+       { "dejagnu --help works"      {--help} {} 0 "Usage: dejagnu" }
+
+       { "dejagnu foo --help works if shell variant selected"
+           {foo --help} {EXPECT=bogus TCLSH=bogus} 0
+           "foo.sh help message" }
+       { "dejagnu foo --help fails if Tcl variant selected"
+           {foo --help} {EXPECT=true  TCLSH=true } 2
+           "does not contain a help message" }
+    }
+
+    { dejagnu-foo
+       { "#" calls via dejagnu-foo link }
+       { "dejagnu-foo as Tcl"
+           {-v -v} {EXPECT=true  TCLSH=true } 0
+           "Found subcommand foo with variants:  tcl sh\n"
+           "Selected variant tcl" }
+       { "dejagnu-foo as Tcl via Expect"
+           {-v -v} {EXPECT=true  TCLSH=bogus} 0
+           "Found subcommand foo with variants:  tcl sh\n"
+           "Selected variant tcl" }
+       { "dejagnu-foo as shell"
+           {-v -v} {EXPECT=bogus TCLSH=bogus} 0
+           "Found subcommand foo with variants:  tcl sh\n"
+           "Selected variant sh" }
+    }
+
+    { dejagnu-bar
+       { "#" calls via dejagnu-bar link }
+       { "dejagnu-bar as Awk"
+           {-v -v} {AWK=true  GAWK=true } 0
+           "Found subcommand bar with variants:  awk sh\n"
+           "Selected variant awk" }
+       { "dejagnu-bar as Awk via GNU Awk"
+           {-v -v} {AWK=bogus GAWK=true } 0
+           "Found subcommand bar with variants:  awk sh\n"
+           "Selected variant awk" }
+       { "dejagnu-bar as shell"
+           {-v -v} {AWK=bogus GAWK=bogus} 0
+           "Found subcommand bar with variants:  awk sh\n"
+           "Selected variant sh" }
+
+       { "#" false hybrid:  bar shadows bar-baz }
+       { "dejagnu-bar as Awk shadows bar-baz"
+           {baz -v -v} {AWK=true} 0
+           "Found subcommand bar with variants:  awk sh\n"
+           "Selected variant awk" }
+    }
+
+    { dejagnu-bar-baz
+       { "#" calls via dejagnu-bar-baz link }
+       { "dejagnu-bar-baz as Awk"
+           {-v -v} {AWK=true  GAWK=true } 0
+           "Found subcommand bar-baz with variants:  awk\n"
+           "Selected variant awk" }
+       { "dejagnu-bar-baz as Awk via GNU Awk"
+           {-v -v} {AWK=bogus GAWK=true } 0
+           "Found subcommand bar-baz with variants:  awk\n"
+           "Selected variant awk" }
+       { "dejagnu-bar-baz fails without Awk"
+           {-v -v} {AWK=bogus GAWK=bogus} 2
+           "Found subcommand bar-baz with variants:  awk\n"
+           "ERROR: no variant of bar-baz was selected" }
+    }
+
+    { dejagnu-baz
+       { "#" hybrid:  link as prefix }
+       { "dejagnu-baz quux as GNU Awk"
+           {quux -v -v} {GAWK=true} 0
+           "Found subcommand baz-quux with variants:  gawk\n"
+           "Selected variant gawk" }
+       { "dejagnu-baz quux fails without GNU Awk"
+           {quux -v -v} {GAWK=bogus AWK=true} 2
+           "Found subcommand baz-quux with variants:  gawk\n"
+           "ERROR: no variant of baz-quux was selected" }
+    }
+
+}
+
+# Build the test environment.
+
+# This must be done at run-time in the build directory because symbolic
+# links are not allowed in GNU source tarballs.
+
+catch {
+    file link -symbolic \
+       [testsuite file -object -test command share dejagnu commands] \
+       [testsuite file -source -test command commands]
+}
+foreach alias_item $tests {
+    catch {
+       file link -symbolic \
+           [testsuite file -object -test command bin [lindex $alias_item 0]] \
+           $LAUNCHER
+    }
+}
+if { ![file exists \
+          [testsuite file -object -test command share dejagnu commands]] } {
+    foreach alias_set $tests {
+       skip_dejagnu_launcher_tests \
+           "Could not set up test environment." \
+           unsupported [lrange $alias_set 1 end]
+    }
+    return
+}
+
+# Run the tests.
+
+if { [which true] == 0 || [which bogus] != 0 } {
+    foreach alias_set $tests {
+       skip_dejagnu_launcher_tests \
+           "Either 'true' is not on PATH or 'bogus' is." \
+           unresolved [lrange $alias_set 1 end]
+    }
+} else {
+    foreach alias_set $tests {
+       run_dejagnu_launcher_tests \
+           [testsuite file -object -test command bin [lindex $alias_set 0]] \
+           [lrange $alias_set 1 end]
+    }
+}
+
+#EOF
diff --git a/testsuite/launcher.all/command/commands/bar-baz.awk 
b/testsuite/launcher.all/command/commands/bar-baz.awk
new file mode 100644
index 0000000..28753c8
--- /dev/null
+++ b/testsuite/launcher.all/command/commands/bar-baz.awk
@@ -0,0 +1 @@
+# empty "hidden" command
diff --git a/testsuite/launcher.all/command/commands/bar.awk 
b/testsuite/launcher.all/command/commands/bar.awk
new file mode 100644
index 0000000..1bb8bf6
--- /dev/null
+++ b/testsuite/launcher.all/command/commands/bar.awk
@@ -0,0 +1 @@
+# empty
diff --git a/testsuite/launcher.all/command/commands/bar.sh 
b/testsuite/launcher.all/command/commands/bar.sh
new file mode 100755
index 0000000..c52d3c2
--- /dev/null
+++ b/testsuite/launcher.all/command/commands/bar.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exit 0
diff --git a/testsuite/launcher.all/command/commands/baz-quux.gawk 
b/testsuite/launcher.all/command/commands/baz-quux.gawk
new file mode 100644
index 0000000..9c4ff45
--- /dev/null
+++ b/testsuite/launcher.all/command/commands/baz-quux.gawk
@@ -0,0 +1 @@
+# empty -*- Awk -*- file
diff --git a/testsuite/launcher.all/command/commands/foo.sh 
b/testsuite/launcher.all/command/commands/foo.sh
new file mode 100755
index 0000000..154687f
--- /dev/null
+++ b/testsuite/launcher.all/command/commands/foo.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# ##help
+# #foo.sh help message
+# ##end
+
+exit 0
diff --git a/testsuite/launcher.all/command/commands/foo.tcl 
b/testsuite/launcher.all/command/commands/foo.tcl
new file mode 100644
index 0000000..1bb8bf6
--- /dev/null
+++ b/testsuite/launcher.all/command/commands/foo.tcl
@@ -0,0 +1 @@
+# empty
diff --git a/testsuite/launcher.all/help.exp b/testsuite/launcher.all/help.exp
new file mode 100644
index 0000000..34eb68d
--- /dev/null
+++ b/testsuite/launcher.all/help.exp
@@ -0,0 +1,39 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of DejaGnu.
+#
+# DejaGnu 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.
+#
+# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+# This file was written by Jacob Bachmeyer.
+
+# each element: { name args envars exit_code output_re... }
+set tests {
+    { "dejagnu help selects dejagnu(1) manpage"
+       {help -v} {MANPAGER=echo} 0
+       "Forwarding to man \".*doc/dejagnu\\.1\"" }
+    { "dejagnu help help selects dejagnu-help(1) manpage"
+       {help -v help} {MANPAGER=echo} 0
+       "Forwarding to man \".*doc/dejagnu-help\\.1\"" }
+}
+
+if { ![file isdirectory [file join [file dirname $LAUNCHER] commands]] } {
+    skip_dejagnu_launcher_tests \
+       "The 'commands' directory is not present in the source tree." \
+       unsupported $tests
+} else {
+    run_dejagnu_launcher_tests $LAUNCHER $tests
+}
+
+#EOF
diff --git a/testsuite/launcher.all/interp.exp 
b/testsuite/launcher.all/interp.exp
new file mode 100644
index 0000000..02e763e
--- /dev/null
+++ b/testsuite/launcher.all/interp.exp
@@ -0,0 +1,57 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of DejaGnu.
+#
+# DejaGnu 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.
+#
+# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+# This file was written by Jacob Bachmeyer.
+
+# each element: { name args envars exit_code output_re... }
+set tests {
+    { "have shell, always" {--DGTimpl sh} {} 0 "" }
+    { "report error probing 'echo'" {--DGTimpl echo} {} 2 "" }
+
+    { "have no Awk"  {--DGTimpl awk}  {AWK=bogus GAWK=bogus} 1 "" }
+    { "have Awk"     {--DGTimpl awk}  {AWK=true  GAWK=bogus} 0 "" }
+
+    { "have no GNU Awk"      {--DGTimpl gawk} {GAWK=bogus} 1 "" }
+    { "have GNU Awk" {--DGTimpl gawk} {GAWK=true }  0 "" }
+
+    { "GNU Awk substitutes for Awk"
+                       {--DGTimpl awk}  {AWK=bogus GAWK=true} 0 "" }
+
+    { "have no Tcl"  {--DGTimpl tcl}  {TCLSH=bogus EXPECT=bogus} 1 "" }
+    { "have Tcl"     {--DGTimpl tcl}  {TCLSH=true  EXPECT=bogus} 0 "" }
+
+    { "have no Expect"       {--DGTimpl exp}  {EXPECT=bogus} 1 "" }
+    { "have Expect"  {--DGTimpl exp}  {EXPECT=true }  0 "" }
+
+    { "Expect substitutes for Tcl"
+                       {--DGTimpl tcl}  {TCLSH=bogus EXPECT=true} 0 "" }
+}
+
+if { [which true] == 0 || [which bogus] != 0 } {
+    skip_dejagnu_launcher_tests \
+       "Either 'true' is not on PATH or 'bogus' is." \
+       unresolved $tests
+} elseif { ![file isdirectory [file join [file dirname $LAUNCHER] commands]] } 
{
+    skip_dejagnu_launcher_tests \
+       "The 'commands' directory is not present in the source tree." \
+       unsupported $tests
+} else {
+    run_dejagnu_launcher_tests $LAUNCHER $tests
+}
+
+#EOF
diff --git a/testsuite/launcher.all/verbose.exp 
b/testsuite/launcher.all/verbose.exp
new file mode 100644
index 0000000..a45ca2d
--- /dev/null
+++ b/testsuite/launcher.all/verbose.exp
@@ -0,0 +1,55 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of DejaGnu.
+#
+# DejaGnu 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.
+#
+# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+# This file was written by Jacob Bachmeyer.
+
+# each element: { name args envars exit_code output_re... }
+set tests {
+    { "empty command" {} {} 2 "ERROR: no command given" }
+    { "empty; verbose 1" {-v} {} 2
+       "Verbose level is 1\nRunning launcher [^\n]*\n"
+       "Looking for commands [^\n]*\nRunning nothing.\n"
+       "ERROR: no command given" }
+    { "empty; verbose 2" {-v -v} {} 2
+       "Verbose level is 2\nRunning launcher [^\n]*\n"
+       "Running from source directory\n"
+       "Looking for commands [^\n]*\nRunning nothing.\n"
+       "ERROR: no command given" }
+    { "empty; verbose 3" {-v -v -v} {} 2
+       "Verbose level is 3\nRunning launcher [^\n]*\n"
+       "Running from source directory\n"
+       "Looking for commands [^\n]*\nRunning nothing.\n"
+       "Awk interpreter [^\n]*\nGNU Awk interpreter [^\n]*\n"
+       "Bash interpreter [^\n]*\n"
+       "Expect interpreter [^\n]*\nTcl interpreter [^\n]*\n"
+       "ERROR: no command given" }
+}
+
+lappend tests [list "check version" {--version} {} 0 \
+                  [format "dejagnu auxiliary launcher \\(DejaGnu\\) %s" \
+                       $frame_version]]
+
+if { ![file isdirectory [file join [file dirname $LAUNCHER] commands]] } {
+    skip_dejagnu_launcher_tests \
+       "The 'commands' directory is not present in the source tree." \
+       unsupported $tests
+} else {
+    run_dejagnu_launcher_tests $LAUNCHER $tests
+}
+
+#EOF
diff --git a/testsuite/lib/launcher.exp b/testsuite/lib/launcher.exp
new file mode 100644
index 0000000..906f722
--- /dev/null
+++ b/testsuite/lib/launcher.exp
@@ -0,0 +1,110 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of DejaGnu.
+#
+# DejaGnu 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.
+#
+# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+# This file was written by Jacob Bachmeyer.
+
+if { ![info exists LAUNCHER] } {
+    set LAUNCHER \
+       [file join [file dirname [testsuite file -source -top]] dejagnu]
+}
+verbose "Using LAUNCHER $LAUNCHER" 2
+
+if { [which $LAUNCHER] == 0 } {
+    perror "Can't find LAUNCHER = $LAUNCHER"
+    exit 2
+}
+
+# run dejagnu(1) LAUNCHER with ARGLIST, returning { output exit_code }
+proc dejagnu_run { launcher arglist envlist } {
+    global errorCode
+
+    set exec_cmd [list exec]
+    if { [llength $envlist] > 0 } {
+       lappend exec_cmd env
+       foreach var $envlist { lappend exec_cmd $var }
+    }
+    lappend exec_cmd $launcher
+
+    # reset errorCode
+    catch { error }
+
+    catch { eval $exec_cmd $arglist } output
+
+    if { [lindex $errorCode 0] eq "CHILDSTATUS" } {
+       return [list $output [lindex $errorCode 2]]
+    } else {
+       return [list $output 0]
+    }
+}
+
+# evaluate a test against LAUNCHER, returning true if it passes
+# TEST is a list:  { name arglist envlist exit_code output_re... }
+proc try_dejagnu_launcher { launcher test } {
+    foreach part [lrange $test 4 end] { append re $part }
+
+    if { [llength [lindex $test 2]] > 0 } {
+       verbose "Spawning \"env [lindex $test 2] $launcher [lindex $test 1]\" 
..."
+    } else {
+       verbose "Spawning \"$launcher [lindex $test 1]\" ..."
+    }
+    verbose "Expecting to match {$re} ..." 2
+    set result [dejagnu_run $launcher [lindex $test 1] [lindex $test 2]]
+    verbose "Exit code [lindex $result 1]; output {[lindex $result 0]}" 2
+
+    if { [regexp $re [lindex $result 0]]
+        && [lindex $test 3] == [lindex $result 1] } {
+       return 1
+    } else {
+       return 0
+    }
+}
+
+proc run_dejagnu_launcher_tests { launcher tests } {
+    foreach test $tests {
+       if { [lindex $test 0] == "#" } {
+           # ignore comments in test list
+       } elseif { [llength $test] == 1 } {
+           # name only is a stub
+           untested [lindex $test 0]
+       } elseif { [try_dejagnu_launcher $launcher $test] } {
+           pass [lindex $test 0]
+       } else {
+           fail [lindex $test 0]
+       }
+    }
+}
+
+proc skip_dejagnu_launcher_tests { why result tests } {
+    perror $why 0
+    foreach test $tests {
+       if { [lindex $test 0] == "#" } {
+           # ignore comments in test list
+       } else {
+           $result [lindex $test 0]
+       }
+    }
+}
+
+# stub: dejagnu(1) itself is non-interactive
+proc dejagnu_exit {} {}
+
+# stub: dejagnu(1) does not have a separate version number
+proc dejagnu_version {} {
+}
+
+#EOF
----


-- Jacob



reply via email to

[Prev in Thread] Current Thread [Next in Thread]