git: 5c7b986c21ed - main - lorder: Clean up and improve robustness.

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Wed, 28 Feb 2024 15:44:33 UTC
The branch main has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=5c7b986c21ed47545203e8f630fe2281b83112d2

commit 5c7b986c21ed47545203e8f630fe2281b83112d2
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2024-02-28 15:37:36 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2024-02-28 15:37:36 +0000

    lorder: Clean up and improve robustness.
    
    * Properly parse (no) command-line options.
    
    * Ensure that errors go to stderr and result in a non-zero exit.
    
    * Drop the special-case code for a single argument, as it will produce
      the wrong outcome if the file does not exist or is corrupted.
    
    * Don't print anything until after we've collected all the data.
    
    * Always create all temporary files before setting the trap.  This
      ensures that the trap can safely fire at any moment, regardless of any
      previous definition of `T`.
    
    * Use a temporary file rather than a pipe between `nm` and `sed` to
      ensure proper termination if `nm` fails due to a missing or invalid
      input.
    
    * The check for self-referential entries was conditional on testing our
      argument list against a regex looking for archives.  This was a
      needless and unreliable optimization; make the check unconditional.
    
    * Document that lorder will not work properly if any of its inputs have
      spaces in their name.
    
    MFC after:      1 week
    Sponsored by:   Klara, Inc.
    Reviewed by:    allanjude
    Differential Revision:  https://reviews.freebsd.org/D44133
---
 usr.bin/lorder/lorder.1  | 22 ++++++------
 usr.bin/lorder/lorder.sh | 92 ++++++++++++++++++++++++++++++------------------
 2 files changed, 69 insertions(+), 45 deletions(-)

diff --git a/usr.bin/lorder/lorder.1 b/usr.bin/lorder/lorder.1
index b71756b03b49..4c70cd2f4729 100644
--- a/usr.bin/lorder/lorder.1
+++ b/usr.bin/lorder/lorder.1
@@ -25,7 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd March 21, 2023
+.Dd February 27, 2024
 .Dt LORDER 1
 .Os
 .Sh NAME
@@ -44,13 +44,10 @@ The
 .Nm
 utility uses
 .Xr nm 1
-to determine interdependencies in the list of object files
-and library archives
-specified on the command line.
-The
-.Nm
-utility outputs a list of file names where the first file contains a symbol
-which is defined by the second file.
+to determine interdependencies between object files and library
+archives listed on its command line.
+It then outputs a list of pairs of file names such that the first file
+in each pair references at least one symbol defined by the second.
 .Pp
 The output is normally used with
 .Xr tsort 1
@@ -58,11 +55,11 @@ when a library is created to determine the optimum ordering of the
 object modules so that all references may be resolved in a single
 pass of the loader.
 .Pp
-When linking static binaries,
+Similarly, when linking static binaries,
 .Nm
 and
 .Xr tsort 1
-can be used to properly order library archives automatically.
+can be used to sort libraries in order of dependency.
 .Pp
 The use of
 .Nm
@@ -97,3 +94,8 @@ A
 .Nm
 utility appeared in
 .At v7 .
+.Sh CAVEATS
+The
+.Nm
+utility will not work properly if given file names with spaces or
+newlines in them.
diff --git a/usr.bin/lorder/lorder.sh b/usr.bin/lorder/lorder.sh
index a24f844e5790..be28eec8b9bc 100644
--- a/usr.bin/lorder/lorder.sh
+++ b/usr.bin/lorder/lorder.sh
@@ -29,35 +29,50 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 
-# only one argument is a special case, just output the name twice
-case $# in
-	0)
-		echo "usage: lorder file ...";
-		exit ;;
-	1)
-		echo $1 $1;
-		exit ;;
-esac
+export LC_CTYPE=C
+export LC_COLLATE=C
+set -e
 
-# temporary files
+usage() {
+	echo "usage: lorder file ..." >&2
+	exit 1
+}
+
+while getopts "" opt ; do
+	case $opt in
+	*)
+		usage
+		;;
+	esac
+done
+shift $(($OPTIND - 1))
+if [ $# -eq 0 ] ; then
+	usage
+fi
+
+#
+# Create temporary files.
+#
+N=$(mktemp -t _nm_)
 R=$(mktemp -t _reference_)
 S=$(mktemp -t _symbol_)
+T=$(mktemp -t _temp_)
 NM=${NM:-nm}
 
-# remove temporary files on HUP, INT, QUIT, PIPE, TERM
-trap "rm -f $R $S $T; exit 1" 1 2 3 13 15
-
-# make sure all the files get into the output
-for i in $*; do
-	echo $i $i
-done
+#
+# Remove temporary files on termination.
+#
+trap "rm -f $N $R $S $T" EXIT 1 2 3 13 15
 
-# if the line has " [RTDW] " it's a globally defined symbol, put it
-# into the symbol file.
 #
-# if the line has " U " it's a globally undefined symbol, put it into
-# the reference file.
-${NM} ${NMFLAGS} -go $* | sed "
+# A line matching " [RTDW] " indicates that the input defines a symbol
+# with external linkage; put it in the symbol file.
+#
+# A line matching " U " indicates that the input references an
+# undefined symbol; put it in the reference file.
+#
+${NM} ${NMFLAGS} -go "$@" >$N
+sed -e "
 	/ [RTDW] / {
 		s/:.* [RTDW] / /
 		w $S
@@ -68,21 +83,28 @@ ${NM} ${NMFLAGS} -go $* | sed "
 		w $R
 	}
 	d
-"
+" <$N
 
-export LC_ALL=C
-# eliminate references that can be resolved by the same library.
-if [ $(expr "$*" : '.*\.a[[:>:]]') -ne 0 ]; then
-	sort -u -o $S $S
-	sort -u -o $R $R
-	T=$(mktemp -t _temp_)
-	comm -23 $R $S >$T
-	mv $T $R
-fi
+#
+# Elide entries representing a reference to a symbol from within the
+# library that defines it.
+#
+sort -u -o $S $S
+sort -u -o $R $R
+comm -23 $R $S >$T
+mv $T $R
+
+#
+# Make sure that all inputs get into the output.
+#
+for i ; do
+	echo "$i" "$i"
+done
 
-# sort references and symbols on the second field (the symbol),
-# join on that field, and print out the file names.
+#
+# Sort references and symbols on the second field (the symbol), join
+# on that field, and print out the file names.
+#
 sort -k 2 -o $R $R
 sort -k 2 -o $S $S
 join -j 2 -o 1.1 2.1 $R $S
-rm -f $R $S