sg_inq+sg_vpd: more JSON work (tpc)

git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@964 6180dd3e-e324-4e3e-922d-17de1ae2f315
diff --git a/ChangeLog b/ChangeLog
index 9e98139..2682ce0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@
 some description at the top of its ".c" file. All utilities in the main
 directory have their own "man" pages. There is also a sg3_utils man page.
 
-Changelog for pre-release sg3_utils-1.48 [20220728] [svn: r963]
+Changelog for pre-release sg3_utils-1.48 [20220805] [svn: r964]
   - some utilities: add experimental --json[=JO] option
   - sg_z_act_query: new utility for sending either a
     Zone activate or Zone query command
@@ -77,7 +77,7 @@
     .tar.gz ; fix build issue with Fedora 36
   - round of coverity identified issue fixes (and non-issues)
   - autoconf: upgrade version 2.70 to 2.71; automake upgrade
-    to version 1.16.5
+    to version 1.16.5 (from Fedora 36)
   - codespell fixes
 
 Changelog for released sg3_utils-1.47 [20211110] [svn: r919]
diff --git a/Makefile.in b/Makefile.in
index 09ecc74..73aba95 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -229,6 +229,7 @@
 ETAGS = @ETAGS@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+FILECMD = @FILECMD@
 GETOPT_O_FILES = @GETOPT_O_FILES@
 GREP = @GREP@
 INSTALL = @INSTALL@
diff --git a/aclocal.m4 b/aclocal.m4
index cf53b9c..c9ab270 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -22,7 +22,8 @@
 
 # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
 #
-#   Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc.
+#   Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software
+#   Foundation, Inc.
 #   Written by Gordon Matzigkeit, 1996
 #
 # This file is free software; the Free Software Foundation gives
@@ -53,7 +54,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ])
 
-# serial 58 LT_INIT
+# serial 59 LT_INIT
 
 
 # LT_PREREQ(VERSION)
@@ -203,6 +204,7 @@
 m4_require([_LT_CHECK_SHELL_FEATURES])dnl
 m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
 m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_DECL_FILECMD])dnl
 m4_require([_LT_CHECK_MAGIC_METHOD])dnl
 m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
 m4_require([_LT_CMD_OLD_ARCHIVE])dnl
@@ -241,8 +243,8 @@
 ofile=libtool
 can_build_shared=yes
 
-# All known linkers require a '.a' archive for static linking (except MSVC,
-# which needs '.lib').
+# All known linkers require a '.a' archive for static linking (except MSVC and
+# ICC, which need '.lib').
 libext=a
 
 with_gnu_ld=$lt_cv_prog_gnu_ld
@@ -744,6 +746,7 @@
     cat <<_LT_EOF >> "$cfgfile"
 #! $SHELL
 # Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
 # NOTE: Changes made to this file will be lost: look at ltmain.sh.
 
 # Provide generalized library-building support services.
@@ -793,7 +796,7 @@
   # if finds mixed CR/LF and LF-only lines.  Since sed operates in
   # text mode, it properly converts lines to CR/LF.  This bash problem
   # is reportedly fixed, but why not run on old versions too?
-  sed '$q' "$ltmain" >> "$cfgfile" \
+  $SED '$q' "$ltmain" >> "$cfgfile" \
      || (rm -f "$cfgfile"; exit 1)
 
    mv -f "$cfgfile" "$ofile" ||
@@ -1055,8 +1058,8 @@
 _LT_EOF
       echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
       $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
-      echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
-      $AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+      echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+      $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
       echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
       $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
       cat > conftest.c << _LT_EOF
@@ -1080,17 +1083,12 @@
       _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
     darwin1.*)
       _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
-    darwin*) # darwin 5.x on
-      # if running on 10.5 or later, the deployment target defaults
-      # to the OS version, if on x86, and 10.4, the deployment
-      # target defaults to 10.4. Don't you love it?
-      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
-	10.0,*86*-darwin8*|10.0,*-darwin[[912]]*)
-	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
-	10.[[012]][[,.]]*)
-	  _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
-	10.*|11.*)
-	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+    darwin*)
+      case $MACOSX_DEPLOYMENT_TARGET,$host in
+        10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
+          _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+        *)
+          _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
       esac
     ;;
   esac
@@ -1139,12 +1137,12 @@
     output_verbose_link_cmd=func_echo_all
     _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
     _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
-    _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
-    _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+    _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+    _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
     m4_if([$1], [CXX],
 [   if test yes != "$lt_cv_apple_cc_single_mod"; then
       _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
-      _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
+      _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
     fi
 ],[])
   else
@@ -1258,7 +1256,8 @@
 # _LT_WITH_SYSROOT
 # ----------------
 AC_DEFUN([_LT_WITH_SYSROOT],
-[AC_MSG_CHECKING([for sysroot])
+[m4_require([_LT_DECL_SED])dnl
+AC_MSG_CHECKING([for sysroot])
 AC_ARG_WITH([sysroot],
 [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
   [Search for dependent libraries within DIR (or the compiler's sysroot
@@ -1275,7 +1274,7 @@
    fi
    ;; #(
  /*)
-   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
    ;; #(
  no|'')
    ;; #(
@@ -1305,7 +1304,7 @@
   # options accordingly.
   echo 'int i;' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *ELF-32*)
 	HPUX_IA64_MODE=32
 	;;
@@ -1322,7 +1321,7 @@
   echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
     if test yes = "$lt_cv_prog_gnu_ld"; then
-      case `/usr/bin/file conftest.$ac_objext` in
+      case `$FILECMD conftest.$ac_objext` in
 	*32-bit*)
 	  LD="${LD-ld} -melf32bsmip"
 	  ;;
@@ -1334,7 +1333,7 @@
 	;;
       esac
     else
-      case `/usr/bin/file conftest.$ac_objext` in
+      case `$FILECMD conftest.$ac_objext` in
 	*32-bit*)
 	  LD="${LD-ld} -32"
 	  ;;
@@ -1356,7 +1355,7 @@
   echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
     emul=elf
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *32-bit*)
 	emul="${emul}32"
 	;;
@@ -1364,7 +1363,7 @@
 	emul="${emul}64"
 	;;
     esac
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *MSB*)
 	emul="${emul}btsmip"
 	;;
@@ -1372,7 +1371,7 @@
 	emul="${emul}ltsmip"
 	;;
     esac
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *N32*)
 	emul="${emul}n32"
 	;;
@@ -1392,14 +1391,14 @@
   # not appear in the list.
   echo 'int i;' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
-    case `/usr/bin/file conftest.o` in
+    case `$FILECMD conftest.o` in
       *32-bit*)
 	case $host in
 	  x86_64-*kfreebsd*-gnu)
 	    LD="${LD-ld} -m elf_i386_fbsd"
 	    ;;
 	  x86_64-*linux*)
-	    case `/usr/bin/file conftest.o` in
+	    case `$FILECMD conftest.o` in
 	      *x86-64*)
 		LD="${LD-ld} -m elf32_x86_64"
 		;;
@@ -1467,7 +1466,7 @@
   # options accordingly.
   echo 'int i;' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
-    case `/usr/bin/file conftest.o` in
+    case `$FILECMD conftest.o` in
     *64-bit*)
       case $lt_cv_prog_gnu_ld in
       yes*)
@@ -1506,9 +1505,22 @@
 m4_defun([_LT_PROG_AR],
 [AC_CHECK_TOOLS(AR, [ar], false)
 : ${AR=ar}
-: ${AR_FLAGS=cr}
 _LT_DECL([], [AR], [1], [The archiver])
-_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
+
+# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+# Automake.  If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+# higher priority because thats what people were doing historically (setting
+# ARFLAGS for automake and AR_FLAGS for libtool).  FIXME: Make the AR_FLAGS
+# variable obsoleted/removed.
+
+test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+lt_ar_flags=$AR_FLAGS
+_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)])
+
+# Make AR_FLAGS overridable by 'make ARFLAGS='.  Don't try to run-time override
+# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
+         [Flags to create an archive])
 
 AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
   [lt_cv_ar_at_file=no
@@ -1727,7 +1739,7 @@
     lt_cv_sys_max_cmd_len=8192;
     ;;
 
-  bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
+  bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
     # This has been around since 386BSD, at least.  Likely further.
     if test -x /sbin/sysctl; then
       lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
@@ -1770,7 +1782,7 @@
   sysv5* | sco5v6* | sysv4.2uw2*)
     kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
     if test -n "$kargmax"; then
-      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[	 ]]//'`
+      lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[	 ]]//'`
     else
       lt_cv_sys_max_cmd_len=32768
     fi
@@ -2220,26 +2232,35 @@
 striplib=
 old_striplib=
 AC_MSG_CHECKING([whether stripping libraries is possible])
-if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
-  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
-  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
-  AC_MSG_RESULT([yes])
+if test -z "$STRIP"; then
+  AC_MSG_RESULT([no])
 else
-# FIXME - insert some real tests, host_os isn't really good enough
-  case $host_os in
-  darwin*)
-    if test -n "$STRIP"; then
+  if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+    old_striplib="$STRIP --strip-debug"
+    striplib="$STRIP --strip-unneeded"
+    AC_MSG_RESULT([yes])
+  else
+    case $host_os in
+    darwin*)
+      # FIXME - insert some real tests, host_os isn't really good enough
       striplib="$STRIP -x"
       old_striplib="$STRIP -S"
       AC_MSG_RESULT([yes])
-    else
+      ;;
+    freebsd*)
+      if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+        old_striplib="$STRIP --strip-debug"
+        striplib="$STRIP --strip-unneeded"
+        AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+      fi
+      ;;
+    *)
       AC_MSG_RESULT([no])
-    fi
-    ;;
-  *)
-    AC_MSG_RESULT([no])
-    ;;
-  esac
+      ;;
+    esac
+  fi
 fi
 _LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
 _LT_DECL([], [striplib], [1])
@@ -2562,7 +2583,7 @@
     case $host_os in
     cygwin*)
       # Cygwin DLLs use 'cyg' prefix rather than 'lib'
-      soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
 m4_if([$1], [],[
       sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
       ;;
@@ -2572,14 +2593,14 @@
       ;;
     pw32*)
       # pw32 DLLs use 'pw' prefix rather than 'lib'
-      library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
       ;;
     esac
     dynamic_linker='Win32 ld.exe'
     ;;
 
-  *,cl*)
-    # Native MSVC
+  *,cl* | *,icl*)
+    # Native MSVC or ICC
     libname_spec='$name'
     soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
     library_names_spec='$libname.dll.lib'
@@ -2598,7 +2619,7 @@
       done
       IFS=$lt_save_ifs
       # Convert to MSYS style.
-      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
       ;;
     cygwin*)
       # Convert to unix form, then to dos form, then back to unix form
@@ -2635,7 +2656,7 @@
     ;;
 
   *)
-    # Assume MSVC wrapper
+    # Assume MSVC and ICC wrapper
     library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
     dynamic_linker='Win32 ld.exe'
     ;;
@@ -2668,7 +2689,7 @@
   shlibpath_var=LD_LIBRARY_PATH
   ;;
 
-freebsd* | dragonfly*)
+freebsd* | dragonfly* | midnightbsd*)
   # DragonFly does not have aout.  When/if they implement a new
   # versioning mechanism, adjust this.
   if test -x /usr/bin/objformat; then
@@ -2880,6 +2901,9 @@
   # before this can be enabled.
   hardcode_into_libs=yes
 
+  # Add ABI-specific directories to the system library path.
+  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
   # Ideally, we could use ldconfig to report *all* directores which are
   # searched for libraries, however this is still not possible.  Aside from not
   # being certain /sbin/ldconfig is available, command
@@ -2888,7 +2912,7 @@
   # appending ld.so.conf contents (and includes) to the search path.
   if test -f /etc/ld.so.conf; then
     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -2900,18 +2924,6 @@
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -3479,7 +3491,7 @@
 
 bsdi[[45]]*)
   lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
-  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_cmd='$FILECMD -L'
   lt_cv_file_magic_test_file=/shlib/libc.so
   ;;
 
@@ -3513,14 +3525,14 @@
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-freebsd* | dragonfly*)
+freebsd* | dragonfly* | midnightbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     case $host_cpu in
     i*86 )
       # Not sure whether the presence of OpenBSD here was a mistake.
       # Let's accept both of them until this is cleared up.
       lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
-      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_cmd=$FILECMD
       lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
       ;;
     esac
@@ -3534,7 +3546,7 @@
   ;;
 
 hpux10.20* | hpux11*)
-  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_cmd=$FILECMD
   case $host_cpu in
   ia64*)
     lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
@@ -3571,7 +3583,7 @@
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd* | netbsdelf*-gnu)
+netbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
   else
@@ -3581,7 +3593,7 @@
 
 newos6*)
   lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
-  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_cmd=$FILECMD
   lt_cv_file_magic_test_file=/usr/lib/libnls.so
   ;;
 
@@ -3708,13 +3720,13 @@
 	mingw*) lt_bad_file=conftest.nm/nofile ;;
 	*) lt_bad_file=/dev/null ;;
 	esac
-	case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
+	case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
 	*$lt_bad_file* | *'Invalid file or object type'*)
 	  lt_cv_path_NM="$tmp_nm -B"
 	  break 2
 	  ;;
 	*)
-	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
 	  */dev/null*)
 	    lt_cv_path_NM="$tmp_nm -p"
 	    break 2
@@ -3740,7 +3752,7 @@
     # Let the user override the test.
   else
     AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
-    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
+    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
     *COFF*)
       DUMPBIN="$DUMPBIN -symbols -headers"
       ;;
@@ -3980,7 +3992,7 @@
 
 if test "$lt_cv_nm_interface" = "MS dumpbin"; then
   # Gets list of data symbols to import.
-  lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
+  lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
   # Adjust the below global symbol transforms to fixup imported variables.
   lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
   lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
@@ -3998,20 +4010,20 @@
 # Transform an extracted symbol line into a proper C declaration.
 # Some systems (esp. on ia64) link data and code symbols differently,
 # so use this general approach.
-lt_cv_sys_global_symbol_to_cdecl="sed -n"\
+lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
 $lt_cdecl_hook\
 " -e 's/^T .* \(.*\)$/extern int \1();/p'"\
 " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
 
 # Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
+lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
 $lt_c_name_hook\
 " -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
 " -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
 
 # Transform an extracted symbol line into symbol name with lib prefix and
 # symbol address.
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
 $lt_c_name_lib_hook\
 " -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
 " -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
@@ -4035,7 +4047,7 @@
   if test "$lt_cv_nm_interface" = "MS dumpbin"; then
     # Fake it for dumpbin and say T for any non-static function,
     # D for any global variable and I for any imported variable.
-    # Also find C++ and __fastcall symbols from MSVC++,
+    # Also find C++ and __fastcall symbols from MSVC++ or ICC,
     # which start with @ or ?.
     lt_cv_sys_global_symbol_pipe="$AWK ['"\
 "     {last_section=section; section=\$ 3};"\
@@ -4053,9 +4065,9 @@
 "     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
 "     ' prfx=^$ac_symprfx]"
   else
-    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+    lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
   fi
-  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
 
   # Check to see that the pipe works correctly.
   pipe_works=no
@@ -4077,8 +4089,7 @@
   if AC_TRY_EVAL(ac_compile); then
     # Now try to grab the symbols.
     nlist=conftest.nm
-    $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD
-    if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
       # Try sorting and uniquifying the output.
       if sort "$nlist" | uniq > "$nlist"T; then
 	mv -f "$nlist"T "$nlist"
@@ -4343,7 +4354,7 @@
 	    ;;
 	esac
 	;;
-      freebsd* | dragonfly*)
+      freebsd* | dragonfly* | midnightbsd*)
 	# FreeBSD uses GNU C++
 	;;
       hpux9* | hpux10* | hpux11*)
@@ -4426,7 +4437,7 @@
 	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
 	    ;;
 	  *)
-	    case `$CC -V 2>&1 | sed 5q` in
+	    case `$CC -V 2>&1 | $SED 5q` in
 	    *Sun\ C*)
 	      # Sun C++ 5.9
 	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
@@ -4450,7 +4461,7 @@
 	    ;;
 	esac
 	;;
-      netbsd* | netbsdelf*-gnu)
+      netbsd*)
 	;;
       *qnx* | *nto*)
         # QNX uses GNU C++, but need to define -shared option too, otherwise
@@ -4718,12 +4729,6 @@
 	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
 	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
         ;;
-      # flang / f18. f95 an alias for gfortran or flang on Debian
-      flang* | f18* | f95*)
-	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
-        ;;
       # icc used to be incompatible with GCC.
       # ICC 10 doesn't accept -KPIC any more.
       icc* | ifort*)
@@ -4768,7 +4773,7 @@
 	_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
 	;;
       *)
-	case `$CC -V 2>&1 | sed 5q` in
+	case `$CC -V 2>&1 | $SED 5q` in
 	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
 	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
 	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
@@ -4951,7 +4956,7 @@
     if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
       _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
     else
-      _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+      _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
     fi
     ;;
   pw32*)
@@ -4959,7 +4964,7 @@
     ;;
   cygwin* | mingw* | cegcc*)
     case $cc_basename in
-    cl*)
+    cl* | icl*)
       _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
       ;;
     *)
@@ -4968,9 +4973,6 @@
       ;;
     esac
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    _LT_TAGVAR(link_all_deplibs, $1)=no
-    ;;
   *)
     _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
     ;;
@@ -5019,23 +5021,20 @@
 
   case $host_os in
   cygwin* | mingw* | pw32* | cegcc*)
-    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
     # When not using gcc, we currently assume that we are using
-    # Microsoft Visual C++.
+    # Microsoft Visual C++ or Intel C++ Compiler.
     if test yes != "$GCC"; then
       with_gnu_ld=no
     fi
     ;;
   interix*)
-    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
     with_gnu_ld=yes
     ;;
   openbsd* | bitrig*)
     with_gnu_ld=no
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    _LT_TAGVAR(link_all_deplibs, $1)=no
-    ;;
   esac
 
   _LT_TAGVAR(ld_shlibs, $1)=yes
@@ -5082,7 +5081,7 @@
       _LT_TAGVAR(whole_archive_flag_spec, $1)=
     fi
     supports_anon_versioning=no
-    case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
+    case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
       *GNU\ gold*) supports_anon_versioning=yes ;;
       *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
       *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
@@ -5194,6 +5193,7 @@
 	emximp -o $lib $output_objdir/$libname.def'
       _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='@'
       ;;
 
     interix[[3-9]]*)
@@ -5208,7 +5208,7 @@
       # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
       # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
-      _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
       ;;
 
     gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
@@ -5251,7 +5251,7 @@
 	  _LT_TAGVAR(compiler_needs_object, $1)=yes
 	  ;;
 	esac
-	case `$CC -V 2>&1 | sed 5q` in
+	case `$CC -V 2>&1 | $SED 5q` in
 	*Sun\ C*)			# Sun C 5.9
 	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
 	  _LT_TAGVAR(compiler_needs_object, $1)=yes
@@ -5263,7 +5263,7 @@
 
         if test yes = "$supports_anon_versioning"; then
           _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
-            cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+            cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
             echo "local: *; };" >> $output_objdir/$libname.ver~
             $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
         fi
@@ -5279,7 +5279,7 @@
 	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
 	  if test yes = "$supports_anon_versioning"; then
 	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
-              cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+              cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
               echo "local: *; };" >> $output_objdir/$libname.ver~
               $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
 	  fi
@@ -5290,7 +5290,7 @@
       fi
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
 	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
 	wlarc=
@@ -5411,7 +5411,7 @@
 	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
 	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
 	else
-	  _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+	  _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
 	fi
 	aix_use_runtimelinking=no
 
@@ -5594,12 +5594,12 @@
 
     cygwin* | mingw* | pw32* | cegcc*)
       # When not using gcc, we currently assume that we are using
-      # Microsoft Visual C++.
+      # Microsoft Visual C++ or Intel C++ Compiler.
       # hardcode_libdir_flag_spec is actually meaningless, as there is
       # no search path for DLLs.
       case $cc_basename in
-      cl*)
-	# Native MSVC
+      cl* | icl*)
+	# Native MSVC or ICC
 	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
 	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
 	_LT_TAGVAR(always_export_symbols, $1)=yes
@@ -5640,7 +5640,7 @@
           fi'
 	;;
       *)
-	# Assume MSVC wrapper
+	# Assume MSVC and ICC wrapper
 	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
 	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
 	# Tell ltmain to make .lib files, not .a files.
@@ -5688,7 +5688,7 @@
       ;;
 
     # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-    freebsd* | dragonfly*)
+    freebsd* | dragonfly* | midnightbsd*)
       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
       _LT_TAGVAR(hardcode_direct, $1)=yes
@@ -5811,7 +5811,6 @@
 	if test yes = "$lt_cv_irix_exported_symbol"; then
           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
 	fi
-	_LT_TAGVAR(link_all_deplibs, $1)=no
       else
 	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
 	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
@@ -5833,7 +5832,7 @@
       esac
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
 	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
       else
@@ -5900,6 +5899,7 @@
 	emximp -o $lib $output_objdir/$libname.def'
       _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='@'
       ;;
 
     osf3*)
@@ -6455,7 +6455,7 @@
       # Commands to make compiler produce verbose output that lists
       # what "hidden" libraries, object files and flags are used when
       # linking a shared library.
-      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 
     else
       GXX=no
@@ -6666,8 +6666,8 @@
 
       cygwin* | mingw* | pw32* | cegcc*)
 	case $GXX,$cc_basename in
-	,cl* | no,cl*)
-	  # Native MSVC
+	,cl* | no,cl* | ,icl* | no,icl*)
+	  # Native MSVC or ICC
 	  # hardcode_libdir_flag_spec is actually meaningless, as there is
 	  # no search path for DLLs.
 	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
@@ -6765,6 +6765,7 @@
 	  emximp -o $lib $output_objdir/$libname.def'
 	_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
 	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+	_LT_TAGVAR(file_list_spec, $1)='@'
 	;;
 
       dgux*)
@@ -6795,7 +6796,7 @@
         _LT_TAGVAR(archive_cmds_need_lc, $1)=no
         ;;
 
-      freebsd* | dragonfly*)
+      freebsd* | dragonfly* | midnightbsd*)
         # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
         # conventions
         _LT_TAGVAR(ld_shlibs, $1)=yes
@@ -6830,7 +6831,7 @@
             # explicitly linking system object files so we need to strip them
             # from the output so that they don't get included in the library
             # dependencies.
-            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
             ;;
           *)
             if test yes = "$GXX"; then
@@ -6895,7 +6896,7 @@
 	    # explicitly linking system object files so we need to strip them
 	    # from the output so that they don't get included in the library
 	    # dependencies.
-	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
 	    ;;
           *)
 	    if test yes = "$GXX"; then
@@ -6932,7 +6933,7 @@
 	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
 	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
 	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
-	_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
 	;;
       irix5* | irix6*)
         case $cc_basename in
@@ -7072,13 +7073,13 @@
 	    _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
 	    if test yes = "$supports_anon_versioning"; then
 	      _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
-                cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+                cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
                 echo "local: *; };" >> $output_objdir/$libname.ver~
                 $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
 	    fi
 	    ;;
 	  *)
-	    case `$CC -V 2>&1 | sed 5q` in
+	    case `$CC -V 2>&1 | $SED 5q` in
 	    *Sun\ C*)
 	      # Sun C++ 5.9
 	      _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
@@ -7234,7 +7235,7 @@
 	      # Commands to make compiler produce verbose output that lists
 	      # what "hidden" libraries, object files and flags are used when
 	      # linking a shared library.
-	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 
 	    else
 	      # FIXME: insert proper C++ library support
@@ -7318,7 +7319,7 @@
 	        # Commands to make compiler produce verbose output that lists
 	        # what "hidden" libraries, object files and flags are used when
 	        # linking a shared library.
-	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 	      else
 	        # g++ 2.7 appears to require '-G' NOT '-shared' on this
 	        # platform.
@@ -7329,7 +7330,7 @@
 	        # Commands to make compiler produce verbose output that lists
 	        # what "hidden" libraries, object files and flags are used when
 	        # linking a shared library.
-	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 	      fi
 
 	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
@@ -8216,6 +8217,14 @@
 AC_SUBST([DLLTOOL])
 ])
 
+# _LT_DECL_FILECMD
+# ----------------
+# Check for a file(cmd) program that can be used to detect file type and magic
+m4_defun([_LT_DECL_FILECMD],
+[AC_CHECK_TOOL([FILECMD], [file], [:])
+_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
+])# _LD_DECL_FILECMD
+
 # _LT_DECL_SED
 # ------------
 # Check for a fully-functional sed program, that truncates
@@ -8395,8 +8404,8 @@
 
 # Helper functions for option handling.                    -*- Autoconf -*-
 #
-#   Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
-#   Foundation, Inc.
+#   Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free
+#   Software Foundation, Inc.
 #   Written by Gary V. Vaughan, 2004
 #
 # This file is free software; the Free Software Foundation gives
@@ -8827,7 +8836,7 @@
 
 # ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
 #
-# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
+# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software
 # Foundation, Inc.
 # Written by Gary V. Vaughan, 2004
 #
@@ -8952,7 +8961,8 @@
 
 # ltversion.m4 -- version numbers			-*- Autoconf -*-
 #
-#   Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
+#   Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation,
+#   Inc.
 #   Written by Scott James Remnant, 2004
 #
 # This file is free software; the Free Software Foundation gives
@@ -8961,23 +8971,23 @@
 
 # @configure_input@
 
-# serial 4179 ltversion.m4
+# serial 4245 ltversion.m4
 # This file is part of GNU Libtool
 
-m4_define([LT_PACKAGE_VERSION], [2.4.6])
-m4_define([LT_PACKAGE_REVISION], [2.4.6])
+m4_define([LT_PACKAGE_VERSION], [2.4.7])
+m4_define([LT_PACKAGE_REVISION], [2.4.7])
 
 AC_DEFUN([LTVERSION_VERSION],
-[macro_version='2.4.6'
-macro_revision='2.4.6'
+[macro_version='2.4.7'
+macro_revision='2.4.7'
 _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
 _LT_DECL(, macro_revision, 0)
 ])
 
 # lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
 #
-#   Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
-#   Foundation, Inc.
+#   Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free
+#   Software Foundation, Inc.
 #   Written by Scott James Remnant, 2004.
 #
 # This file is free software; the Free Software Foundation gives
diff --git a/config.guess b/config.guess
index 7f76b62..c7f17e8 100755
--- a/config.guess
+++ b/config.guess
@@ -1,10 +1,10 @@
-#! /bin/sh
+#!/usr/bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright 1992-2022 Free Software Foundation, Inc.
 
 # shellcheck disable=SC2006,SC2268 # see below for rationale
 
-timestamp='2022-01-09'
+timestamp='2022-05-25'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -1151,16 +1151,27 @@
 	;;
     x86_64:Linux:*:*)
 	set_cc_for_build
+	CPU=$UNAME_MACHINE
 	LIBCABI=$LIBC
 	if test "$CC_FOR_BUILD" != no_compiler_found; then
-	    if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
-		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-		grep IS_X32 >/dev/null
-	    then
-		LIBCABI=${LIBC}x32
-	    fi
+	    ABI=64
+	    sed 's/^	    //' << EOF > "$dummy.c"
+	    #ifdef __i386__
+	    ABI=x86
+	    #else
+	    #ifdef __ILP32__
+	    ABI=x32
+	    #endif
+	    #endif
+EOF
+	    cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+	    eval "$cc_set_abi"
+	    case $ABI in
+		x86) CPU=i686 ;;
+		x32) LIBCABI=${LIBC}x32 ;;
+	    esac
 	fi
-	GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
+	GUESS=$CPU-pc-linux-$LIBCABI
 	;;
     xtensa*:Linux:*:*)
 	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
@@ -1367,8 +1378,11 @@
     BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
 	GUESS=i586-pc-haiku
 	;;
-    x86_64:Haiku:*:*)
-	GUESS=x86_64-unknown-haiku
+    ppc:Haiku:*:*)	# Haiku running on Apple PowerPC
+	GUESS=powerpc-apple-haiku
+	;;
+    *:Haiku:*:*)	# Haiku modern gcc (not bound by BeOS compat)
+	GUESS=$UNAME_MACHINE-unknown-haiku
 	;;
     SX-4:SUPER-UX:*:*)
 	GUESS=sx4-nec-superux$UNAME_RELEASE
diff --git a/config.sub b/config.sub
index dba16e8..b41da55 100755
--- a/config.sub
+++ b/config.sub
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/usr/bin/sh
 # Configuration validation subroutine script.
 #   Copyright 1992-2022 Free Software Foundation, Inc.
 
diff --git a/configure b/configure
index 7e31157..19592e6 100755
--- a/configure
+++ b/configure
@@ -704,6 +704,7 @@
 RANLIB
 DLLTOOL
 OBJDUMP
+FILECMD
 LN_S
 NM
 ac_ct_DUMPBIN
@@ -4694,8 +4695,8 @@
 
 
 
-macro_version='2.4.6'
-macro_revision='2.4.6'
+macro_version='2.4.7'
+macro_revision='2.4.7'
 
 
 
@@ -5323,13 +5324,13 @@
 	mingw*) lt_bad_file=conftest.nm/nofile ;;
 	*) lt_bad_file=/dev/null ;;
 	esac
-	case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
+	case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
 	*$lt_bad_file* | *'Invalid file or object type'*)
 	  lt_cv_path_NM="$tmp_nm -B"
 	  break 2
 	  ;;
 	*)
-	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
 	  */dev/null*)
 	    lt_cv_path_NM="$tmp_nm -p"
 	    break 2
@@ -5467,7 +5468,7 @@
   fi
 fi
 
-    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
+    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
     *COFF*)
       DUMPBIN="$DUMPBIN -symbols -headers"
       ;;
@@ -5571,7 +5572,7 @@
     lt_cv_sys_max_cmd_len=8192;
     ;;
 
-  bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
+  bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
     # This has been around since 386BSD, at least.  Likely further.
     if test -x /sbin/sysctl; then
       lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
@@ -5614,7 +5615,7 @@
   sysv5* | sco5v6* | sysv4.2uw2*)
     kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
     if test -n "$kargmax"; then
-      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[	 ]//'`
+      lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[	 ]//'`
     else
       lt_cv_sys_max_cmd_len=32768
     fi
@@ -5820,6 +5821,114 @@
 
 
 if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args.
+set dummy ${ac_tool_prefix}file; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_FILECMD+y}
+then :
+  printf %s "(cached) " >&6
+else $as_nop
+  if test -n "$FILECMD"; then
+  ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_FILECMD="${ac_tool_prefix}file"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+FILECMD=$ac_cv_prog_FILECMD
+if test -n "$FILECMD"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5
+printf "%s\n" "$FILECMD" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_FILECMD"; then
+  ac_ct_FILECMD=$FILECMD
+  # Extract the first word of "file", so it can be a program name with args.
+set dummy file; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_FILECMD+y}
+then :
+  printf %s "(cached) " >&6
+else $as_nop
+  if test -n "$ac_ct_FILECMD"; then
+  ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  case $as_dir in #(((
+    '') as_dir=./ ;;
+    */) ;;
+    *) as_dir=$as_dir/ ;;
+  esac
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_FILECMD="file"
+    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD
+if test -n "$ac_ct_FILECMD"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5
+printf "%s\n" "$ac_ct_FILECMD" >&6; }
+else
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+  if test "x$ac_ct_FILECMD" = x; then
+    FILECMD=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    FILECMD=$ac_ct_FILECMD
+  fi
+else
+  FILECMD="$ac_cv_prog_FILECMD"
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
 set dummy ${ac_tool_prefix}objdump; ac_word=$2
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -5962,7 +6071,7 @@
 
 bsdi[45]*)
   lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
-  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_cmd='$FILECMD -L'
   lt_cv_file_magic_test_file=/shlib/libc.so
   ;;
 
@@ -5996,14 +6105,14 @@
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-freebsd* | dragonfly*)
+freebsd* | dragonfly* | midnightbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     case $host_cpu in
     i*86 )
       # Not sure whether the presence of OpenBSD here was a mistake.
       # Let's accept both of them until this is cleared up.
       lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
-      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_cmd=$FILECMD
       lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
       ;;
     esac
@@ -6017,7 +6126,7 @@
   ;;
 
 hpux10.20* | hpux11*)
-  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_cmd=$FILECMD
   case $host_cpu in
   ia64*)
     lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
@@ -6054,7 +6163,7 @@
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd* | netbsdelf*-gnu)
+netbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
   else
@@ -6064,7 +6173,7 @@
 
 newos6*)
   lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
-  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_cmd=$FILECMD
   lt_cv_file_magic_test_file=/usr/lib/libnls.so
   ;;
 
@@ -6437,13 +6546,29 @@
 fi
 
 : ${AR=ar}
-: ${AR_FLAGS=cr}
 
 
 
 
 
 
+# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+# Automake.  If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+# higher priority because thats what people were doing historically (setting
+# ARFLAGS for automake and AR_FLAGS for libtool).  FIXME: Make the AR_FLAGS
+# variable obsoleted/removed.
+
+test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+lt_ar_flags=$AR_FLAGS
+
+
+
+
+
+
+# Make AR_FLAGS overridable by 'make ARFLAGS='.  Don't try to run-time override
+# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+
 
 
 
@@ -6860,7 +6985,7 @@
 
 if test "$lt_cv_nm_interface" = "MS dumpbin"; then
   # Gets list of data symbols to import.
-  lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
+  lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
   # Adjust the below global symbol transforms to fixup imported variables.
   lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
   lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
@@ -6878,20 +7003,20 @@
 # Transform an extracted symbol line into a proper C declaration.
 # Some systems (esp. on ia64) link data and code symbols differently,
 # so use this general approach.
-lt_cv_sys_global_symbol_to_cdecl="sed -n"\
+lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
 $lt_cdecl_hook\
 " -e 's/^T .* \(.*\)$/extern int \1();/p'"\
 " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
 
 # Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
+lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
 $lt_c_name_hook\
 " -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
 " -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
 
 # Transform an extracted symbol line into symbol name with lib prefix and
 # symbol address.
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
 $lt_c_name_lib_hook\
 " -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
 " -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
@@ -6915,7 +7040,7 @@
   if test "$lt_cv_nm_interface" = "MS dumpbin"; then
     # Fake it for dumpbin and say T for any non-static function,
     # D for any global variable and I for any imported variable.
-    # Also find C++ and __fastcall symbols from MSVC++,
+    # Also find C++ and __fastcall symbols from MSVC++ or ICC,
     # which start with @ or ?.
     lt_cv_sys_global_symbol_pipe="$AWK '"\
 "     {last_section=section; section=\$ 3};"\
@@ -6933,9 +7058,9 @@
 "     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
 "     ' prfx=^$ac_symprfx"
   else
-    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+    lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
   fi
-  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
 
   # Check to see that the pipe works correctly.
   pipe_works=no
@@ -6961,8 +7086,11 @@
   test $ac_status = 0; }; then
     # Now try to grab the symbols.
     nlist=conftest.nm
-    $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5
-    if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "$nlist"; then
       # Try sorting and uniquifying the output.
       if sort "$nlist" | uniq > "$nlist"T; then
 	mv -f "$nlist"T "$nlist"
@@ -7135,7 +7263,7 @@
    fi
    ;; #(
  /*)
-   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
    ;; #(
  no|'')
    ;; #(
@@ -7260,7 +7388,7 @@
   ac_status=$?
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *ELF-32*)
 	HPUX_IA64_MODE=32
 	;;
@@ -7281,7 +7409,7 @@
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
     if test yes = "$lt_cv_prog_gnu_ld"; then
-      case `/usr/bin/file conftest.$ac_objext` in
+      case `$FILECMD conftest.$ac_objext` in
 	*32-bit*)
 	  LD="${LD-ld} -melf32bsmip"
 	  ;;
@@ -7293,7 +7421,7 @@
 	;;
       esac
     else
-      case `/usr/bin/file conftest.$ac_objext` in
+      case `$FILECMD conftest.$ac_objext` in
 	*32-bit*)
 	  LD="${LD-ld} -32"
 	  ;;
@@ -7319,7 +7447,7 @@
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
     emul=elf
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *32-bit*)
 	emul="${emul}32"
 	;;
@@ -7327,7 +7455,7 @@
 	emul="${emul}64"
 	;;
     esac
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *MSB*)
 	emul="${emul}btsmip"
 	;;
@@ -7335,7 +7463,7 @@
 	emul="${emul}ltsmip"
 	;;
     esac
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *N32*)
 	emul="${emul}n32"
 	;;
@@ -7359,14 +7487,14 @@
   ac_status=$?
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-    case `/usr/bin/file conftest.o` in
+    case `$FILECMD conftest.o` in
       *32-bit*)
 	case $host in
 	  x86_64-*kfreebsd*-gnu)
 	    LD="${LD-ld} -m elf_i386_fbsd"
 	    ;;
 	  x86_64-*linux*)
-	    case `/usr/bin/file conftest.o` in
+	    case `$FILECMD conftest.o` in
 	      *x86-64*)
 		LD="${LD-ld} -m elf32_x86_64"
 		;;
@@ -7474,7 +7602,7 @@
   ac_status=$?
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-    case `/usr/bin/file conftest.o` in
+    case `$FILECMD conftest.o` in
     *64-bit*)
       case $lt_cv_prog_gnu_ld in
       yes*)
@@ -8257,8 +8385,8 @@
 _LT_EOF
       echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
       $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
-      echo "$AR cr libconftest.a conftest.o" >&5
-      $AR cr libconftest.a conftest.o 2>&5
+      echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5
+      $AR $AR_FLAGS libconftest.a conftest.o 2>&5
       echo "$RANLIB libconftest.a" >&5
       $RANLIB libconftest.a 2>&5
       cat > conftest.c << _LT_EOF
@@ -8285,17 +8413,12 @@
       _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
     darwin1.*)
       _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
-    darwin*) # darwin 5.x on
-      # if running on 10.5 or later, the deployment target defaults
-      # to the OS version, if on x86, and 10.4, the deployment
-      # target defaults to 10.4. Don't you love it?
-      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
-	10.0,*86*-darwin8*|10.0,*-darwin[912]*)
-	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
-	10.[012][,.]*)
-	  _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
-	10.*|11.*)
-	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+    darwin*)
+      case $MACOSX_DEPLOYMENT_TARGET,$host in
+        10.[012],*|,*powerpc*-darwin[5-8]*)
+          _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+        *)
+          _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
       esac
     ;;
   esac
@@ -8683,8 +8806,8 @@
 ofile=libtool
 can_build_shared=yes
 
-# All known linkers require a '.a' archive for static linking (except MSVC,
-# which needs '.lib').
+# All known linkers require a '.a' archive for static linking (except MSVC and
+# ICC, which need '.lib').
 libext=a
 
 with_gnu_ld=$lt_cv_prog_gnu_ld
@@ -9148,12 +9271,6 @@
 	lt_prog_compiler_pic='-KPIC'
 	lt_prog_compiler_static='-static'
         ;;
-      # flang / f18. f95 an alias for gfortran or flang on Debian
-      flang* | f18* | f95*)
-	lt_prog_compiler_wl='-Wl,'
-	lt_prog_compiler_pic='-fPIC'
-	lt_prog_compiler_static='-static'
-        ;;
       # icc used to be incompatible with GCC.
       # ICC 10 doesn't accept -KPIC any more.
       icc* | ifort*)
@@ -9198,7 +9315,7 @@
 	lt_prog_compiler_static='-qstaticlink'
 	;;
       *)
-	case `$CC -V 2>&1 | sed 5q` in
+	case `$CC -V 2>&1 | $SED 5q` in
 	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
 	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
 	  lt_prog_compiler_pic='-KPIC'
@@ -9621,23 +9738,20 @@
 
   case $host_os in
   cygwin* | mingw* | pw32* | cegcc*)
-    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
     # When not using gcc, we currently assume that we are using
-    # Microsoft Visual C++.
+    # Microsoft Visual C++ or Intel C++ Compiler.
     if test yes != "$GCC"; then
       with_gnu_ld=no
     fi
     ;;
   interix*)
-    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
     with_gnu_ld=yes
     ;;
   openbsd* | bitrig*)
     with_gnu_ld=no
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    link_all_deplibs=no
-    ;;
   esac
 
   ld_shlibs=yes
@@ -9684,7 +9798,7 @@
       whole_archive_flag_spec=
     fi
     supports_anon_versioning=no
-    case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in
+    case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
       *GNU\ gold*) supports_anon_versioning=yes ;;
       *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
       *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
@@ -9796,6 +9910,7 @@
 	emximp -o $lib $output_objdir/$libname.def'
       old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
       enable_shared_with_static_runtimes=yes
+      file_list_spec='@'
       ;;
 
     interix[3-9]*)
@@ -9810,7 +9925,7 @@
       # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
       # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
-      archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
       ;;
 
     gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
@@ -9853,7 +9968,7 @@
 	  compiler_needs_object=yes
 	  ;;
 	esac
-	case `$CC -V 2>&1 | sed 5q` in
+	case `$CC -V 2>&1 | $SED 5q` in
 	*Sun\ C*)			# Sun C 5.9
 	  whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
 	  compiler_needs_object=yes
@@ -9865,7 +9980,7 @@
 
         if test yes = "$supports_anon_versioning"; then
           archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
-            cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+            cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
             echo "local: *; };" >> $output_objdir/$libname.ver~
             $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
         fi
@@ -9881,7 +9996,7 @@
 	  archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
 	  if test yes = "$supports_anon_versioning"; then
 	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
-              cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+              cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
               echo "local: *; };" >> $output_objdir/$libname.ver~
               $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
 	  fi
@@ -9892,7 +10007,7 @@
       fi
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
 	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
 	wlarc=
@@ -10013,7 +10128,7 @@
 	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
 	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
 	else
-	  export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+	  export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
 	fi
 	aix_use_runtimelinking=no
 
@@ -10284,12 +10399,12 @@
 
     cygwin* | mingw* | pw32* | cegcc*)
       # When not using gcc, we currently assume that we are using
-      # Microsoft Visual C++.
+      # Microsoft Visual C++ or Intel C++ Compiler.
       # hardcode_libdir_flag_spec is actually meaningless, as there is
       # no search path for DLLs.
       case $cc_basename in
-      cl*)
-	# Native MSVC
+      cl* | icl*)
+	# Native MSVC or ICC
 	hardcode_libdir_flag_spec=' '
 	allow_undefined_flag=unsupported
 	always_export_symbols=yes
@@ -10330,7 +10445,7 @@
           fi'
 	;;
       *)
-	# Assume MSVC wrapper
+	# Assume MSVC and ICC wrapper
 	hardcode_libdir_flag_spec=' '
 	allow_undefined_flag=unsupported
 	# Tell ltmain to make .lib files, not .a files.
@@ -10371,8 +10486,8 @@
     output_verbose_link_cmd=func_echo_all
     archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
     module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
-    archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
-    module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+    archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+    module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
 
   else
   ld_shlibs=no
@@ -10406,7 +10521,7 @@
       ;;
 
     # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-    freebsd* | dragonfly*)
+    freebsd* | dragonfly* | midnightbsd*)
       archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
       hardcode_libdir_flag_spec='-R$libdir'
       hardcode_direct=yes
@@ -10569,7 +10684,6 @@
 	if test yes = "$lt_cv_irix_exported_symbol"; then
           archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
 	fi
-	link_all_deplibs=no
       else
 	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
 	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
@@ -10591,7 +10705,7 @@
       esac
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
 	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
       else
@@ -10658,6 +10772,7 @@
 	emximp -o $lib $output_objdir/$libname.def'
       old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
       enable_shared_with_static_runtimes=yes
+      file_list_spec='@'
       ;;
 
     osf3*)
@@ -11350,7 +11465,7 @@
     case $host_os in
     cygwin*)
       # Cygwin DLLs use 'cyg' prefix rather than 'lib'
-      soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
 
       sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
       ;;
@@ -11360,14 +11475,14 @@
       ;;
     pw32*)
       # pw32 DLLs use 'pw' prefix rather than 'lib'
-      library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
       ;;
     esac
     dynamic_linker='Win32 ld.exe'
     ;;
 
-  *,cl*)
-    # Native MSVC
+  *,cl* | *,icl*)
+    # Native MSVC or ICC
     libname_spec='$name'
     soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
     library_names_spec='$libname.dll.lib'
@@ -11386,7 +11501,7 @@
       done
       IFS=$lt_save_ifs
       # Convert to MSYS style.
-      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
       ;;
     cygwin*)
       # Convert to unix form, then to dos form, then back to unix form
@@ -11423,7 +11538,7 @@
     ;;
 
   *)
-    # Assume MSVC wrapper
+    # Assume MSVC and ICC wrapper
     library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
     dynamic_linker='Win32 ld.exe'
     ;;
@@ -11456,7 +11571,7 @@
   shlibpath_var=LD_LIBRARY_PATH
   ;;
 
-freebsd* | dragonfly*)
+freebsd* | dragonfly* | midnightbsd*)
   # DragonFly does not have aout.  When/if they implement a new
   # versioning mechanism, adjust this.
   if test -x /usr/bin/objformat; then
@@ -11690,6 +11805,9 @@
   # before this can be enabled.
   hardcode_into_libs=yes
 
+  # Add ABI-specific directories to the system library path.
+  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
   # Ideally, we could use ldconfig to report *all* directores which are
   # searched for libraries, however this is still not possible.  Aside from not
   # being certain /sbin/ldconfig is available, command
@@ -11698,7 +11816,7 @@
   # appending ld.so.conf contents (and includes) to the search path.
   if test -f /etc/ld.so.conf; then
     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -11710,18 +11828,6 @@
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -12621,30 +12727,41 @@
 old_striplib=
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
 printf %s "checking whether stripping libraries is possible... " >&6; }
-if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
-  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
-  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-printf "%s\n" "yes" >&6; }
+if test -z "$STRIP"; then
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
 else
-# FIXME - insert some real tests, host_os isn't really good enough
-  case $host_os in
-  darwin*)
-    if test -n "$STRIP"; then
+  if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+    old_striplib="$STRIP --strip-debug"
+    striplib="$STRIP --strip-unneeded"
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+  else
+    case $host_os in
+    darwin*)
+      # FIXME - insert some real tests, host_os isn't really good enough
       striplib="$STRIP -x"
       old_striplib="$STRIP -S"
       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 printf "%s\n" "yes" >&6; }
-    else
+      ;;
+    freebsd*)
+      if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+        old_striplib="$STRIP --strip-debug"
+        striplib="$STRIP --strip-unneeded"
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+      else
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+      fi
+      ;;
+    *)
       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
-    fi
-    ;;
-  *)
-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
-printf "%s\n" "no" >&6; }
-    ;;
-  esac
+      ;;
+    esac
+  fi
 fi
 
 
@@ -14339,6 +14456,7 @@
 lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
 reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
 reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`'
 OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
 deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
 file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
@@ -14347,6 +14465,7 @@
 DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
 sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
 AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`'
 AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
 archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
 STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
@@ -14467,6 +14586,7 @@
 lt_SP2NL \
 lt_NL2SP \
 reload_flag \
+FILECMD \
 OBJDUMP \
 deplibs_check_method \
 file_magic_cmd \
@@ -14475,7 +14595,6 @@
 DLLTOOL \
 sharedlib_from_linklib_cmd \
 AR \
-AR_FLAGS \
 archiver_list_spec \
 STRIP \
 RANLIB \
@@ -15303,6 +15422,7 @@
     cat <<_LT_EOF >> "$cfgfile"
 #! $SHELL
 # Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
 # NOTE: Changes made to this file will be lost: look at ltmain.sh.
 
 # Provide generalized library-building support services.
@@ -15422,6 +15542,9 @@
 # convert \$build files to toolchain format.
 to_tool_file_cmd=$lt_cv_to_tool_file_cmd
 
+# A file(cmd) program that detects file types.
+FILECMD=$lt_FILECMD
+
 # An object symbol dumper.
 OBJDUMP=$lt_OBJDUMP
 
@@ -15446,8 +15569,11 @@
 # The archiver.
 AR=$lt_AR
 
+# Flags to create an archive (by configure).
+lt_ar_flags=$lt_ar_flags
+
 # Flags to create an archive.
-AR_FLAGS=$lt_AR_FLAGS
+AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"}
 
 # How to feed a file listing to the archiver.
 archiver_list_spec=$lt_archiver_list_spec
@@ -15823,7 +15949,7 @@
   # if finds mixed CR/LF and LF-only lines.  Since sed operates in
   # text mode, it properly converts lines to CR/LF.  This bash problem
   # is reportedly fixed, but why not run on old versions too?
-  sed '$q' "$ltmain" >> "$cfgfile" \
+  $SED '$q' "$ltmain" >> "$cfgfile" \
      || (rm -f "$cfgfile"; exit 1)
 
    mv -f "$cfgfile" "$ofile" ||
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 8a09982..81f4f52 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,10 +1,10 @@
 
 man_MANS = \
 	scsi_mandat.8 scsi_readcap.8 scsi_ready.8 scsi_satl.8 scsi_start.8 \
-	scsi_stop.8 scsi_temperature.8 sg3_utils.8 sg_bg_ctl.8 \
-	sg_compare_and_write.8 sg_decode_sense.8 sg_format.8 sg_get_config.8 \
-	sg_get_elem_status.8 sg_get_lba_status.8 sg_ident.8 sg_inq.8 \
-	sg_logs.8 sg_luns.8 sg_modes.8 sg_opcodes.8 sg_persist.8 \
+	scsi_stop.8 scsi_temperature.8 sg3_utils.8 sg3_utils_json.8
+	sg_bg_ctl.8 sg_compare_and_write.8 sg_decode_sense.8 sg_format.8
+	sg_get_config.8 sg_get_elem_status.8 sg_get_lba_status.8 sg_ident.8 \
+	sg_inq.8 sg_logs.8 sg_luns.8 sg_modes.8 sg_opcodes.8 sg_persist.8 \
 	sg_prevent.8 sg_raw.8 sg_rdac.8 sg_read_attr.8 \
 	sg_read_block_limits.8 sg_read_buffer.8 sg_read_long.8 sg_readcap.8 \
 	sg_reassign.8 sg_referrals.8 sg_rep_density.8 sg_rep_pip.8 \
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 8b8e282..8a4ba43 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -188,6 +188,7 @@
 ETAGS = @ETAGS@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+FILECMD = @FILECMD@
 GETOPT_O_FILES = @GETOPT_O_FILES@
 GREP = @GREP@
 INSTALL = @INSTALL@
@@ -287,21 +288,7 @@
 top_srcdir = @top_srcdir@
 man_MANS = scsi_mandat.8 scsi_readcap.8 scsi_ready.8 scsi_satl.8 \
 	scsi_start.8 scsi_stop.8 scsi_temperature.8 sg3_utils.8 \
-	sg_bg_ctl.8 sg_compare_and_write.8 sg_decode_sense.8 \
-	sg_format.8 sg_get_config.8 sg_get_elem_status.8 \
-	sg_get_lba_status.8 sg_ident.8 sg_inq.8 sg_logs.8 sg_luns.8 \
-	sg_modes.8 sg_opcodes.8 sg_persist.8 sg_prevent.8 sg_raw.8 \
-	sg_rdac.8 sg_read_attr.8 sg_read_block_limits.8 \
-	sg_read_buffer.8 sg_read_long.8 sg_readcap.8 sg_reassign.8 \
-	sg_referrals.8 sg_rep_density.8 sg_rep_pip.8 sg_rep_zones.8 \
-	sg_requests.8 sg_reset_wp.8 sg_rmsn.8 sg_rtpg.8 sg_safte.8 \
-	sg_sanitize.8 sg_sat_identify.8 sg_sat_phy_event.8 \
-	sg_sat_read_gplog.8 sg_sat_set_features.8 sg_seek.8 \
-	sg_senddiag.8 sg_ses.8 sg_ses_microcode.8 sg_start.8 sg_stpg.8 \
-	sg_stream_ctl.8 sg_sync.8 sg_timestamp.8 sg_turs.8 sg_unmap.8 \
-	sg_verify.8 sg_vpd.8 sg_wr_mode.8 sg_write_buffer.8 \
-	sg_write_long.8 sg_write_same.8 sg_write_verify.8 sg_write_x.8 \
-	sg_zone.8 sg_z_act_query.8 $(am__append_1) $(am__append_3) \
+	sg3_utils_json.8 $(am__append_1) $(am__append_3) \
 	$(am__append_5)
 CLEANFILES = $(am__append_2) $(am__append_4) $(am__append_6)
 all: all-am
@@ -547,6 +534,19 @@
 
 .PRECIOUS: Makefile
 
+	sg_bg_ctl.8 sg_compare_and_write.8 sg_decode_sense.8 sg_format.8
+	sg_get_config.8 sg_get_elem_status.8 sg_get_lba_status.8 sg_ident.8 \
+	sg_inq.8 sg_logs.8 sg_luns.8 sg_modes.8 sg_opcodes.8 sg_persist.8 \
+	sg_prevent.8 sg_raw.8 sg_rdac.8 sg_read_attr.8 \
+	sg_read_block_limits.8 sg_read_buffer.8 sg_read_long.8 sg_readcap.8 \
+	sg_reassign.8 sg_referrals.8 sg_rep_density.8 sg_rep_pip.8 \
+	sg_rep_zones.8 sg_requests.8 sg_reset_wp.8 sg_rmsn.8 sg_rtpg.8 \
+	sg_safte.8 sg_sanitize.8 sg_sat_identify.8 sg_sat_phy_event.8 \
+	sg_sat_read_gplog.8 sg_sat_set_features.8 sg_seek.8 sg_senddiag.8 \
+	sg_ses.8 sg_ses_microcode.8 sg_start.8 sg_stpg.8 sg_stream_ctl.8 \
+	sg_sync.8 sg_timestamp.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
+	sg_wr_mode.8 sg_write_buffer.8 sg_write_long.8 sg_write_same.8 \
+	sg_write_verify.8 sg_write_x.8 sg_zone.8 sg_z_act_query.8
 @OS_LINUX_TRUE@sg_scan.8: sg_scan.8.linux
 @OS_LINUX_TRUE@	cp -p $< $@
 @OS_WIN32_MINGW_TRUE@sg_scan.8: sg_scan.8.win32
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index ab59236..1eb2f4a 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS "8" "July 2022" "sg3_utils\-1.48" SG3_UTILS
+.TH SG3_UTILS "8" "August 2022" "sg3_utils\-1.48" SG3_UTILS
 .SH NAME
 sg3_utils \- a package of utilities for sending SCSI commands
 .SH SYNOPSIS
diff --git a/doc/sg3_utils_json.8 b/doc/sg3_utils_json.8
index be2983a..788f19c 100644
--- a/doc/sg3_utils_json.8
+++ b/doc/sg3_utils_json.8
@@ -1,6 +1,6 @@
-.TH SG3_UTILS "8" "July 2022" "sg3_utils\-1.48" SG3_UTILS
+.TH SG3_UTILS_JSON "8" "August 2022" "sg3_utils\-1.48" SG3_UTILS
 .SH NAME
-sg3_utils \- JSON output for some utilities
+sg3_utils_json \- JSON output for some sg3_utils utilities
 .SH SYNOPSIS
 .B sg_*
 \fI\-\-json[=JO]\fR [\fIOTHER_OPTIONS\fR] [\fIDEVICE\fR]
diff --git a/doc/sg_decode_sense.8 b/doc/sg_decode_sense.8
index 440cb0b..ea68eb1 100644
--- a/doc/sg_decode_sense.8
+++ b/doc/sg_decode_sense.8
@@ -4,9 +4,10 @@
 .SH SYNOPSIS
 .B sg_decode_sense
 [\fI\-\-binary=BFN\fR] [\fI\-\-cdb\fR] [\fI\-\-err=ES\fR] [\fI\-\-file=HFN\fR]
-[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-inhex=HFN\fR] [\fI\-\-nodecode\fR]
-[\fI\-\-nospace\fR] [\fI\-\-status=SS\fR] [\fI\-\-verbose\fR]
-[\fI\-\-version\fR] [\fI\-\-write=WFN\fR] [H1 H2 H3 ...]
+[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-inhex=HFN\fR]
+[\fI\-\-ignore\-first\fR] [\fI\-\-nodecode\fR] [\fI\-\-nospace\fR]
+[\fI\-\-status=SS\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR]
+[\fI\-\-write=WFN\fR] [H1 H2 H3 ...]
 .SH DESCRIPTION
 .\" Add any additional description here
 This utility takes SCSI sense data in binary or as a sequence of ASCII
@@ -97,6 +98,14 @@
 same action as \fI\-\-file=HFN\fR. This option was added for compatibility
 with other utilities in this package that have a \fI\-\-inhex=\fR option.
 .TP
+\fB\-I\fR, \fB\-\-ignore\-first\fR
+many programs that output hex bytes (e.g. 'hexdump \-C') have a running
+count (or index) in the first column of each line. This option ignores the
+first hexadecimal value on each line. This option has no effect if
+\fI\-\-binary=BFN\fR or \fI\-\-nospace\fR are given. Blank lines and any
+character from and after "#" on a line are ignored. Useful with the
+\fI\-\-file=HFN\fR and \fI\-\-nodecode\fR options.
+.TP
 \fB\-N\fR, \fB\-\-nodecode\fR
 Do not decode the given data as sense or a cdb. Useful when arbitrary data
 is given (e.g. when converting hex to binary or vice versa).
diff --git a/doc/sg_inq.8 b/doc/sg_inq.8
index 0f02d2a..76a5d97 100644
--- a/doc/sg_inq.8
+++ b/doc/sg_inq.8
@@ -25,7 +25,9 @@
 then outputs the response. All SCSI devices are meant to respond to
 a "standard" INQUIRY command with at least a 36 byte response (in SCSI 2 and
 higher). An INQUIRY is termed as "standard" when both the EVPD and CmdDt (now
-obsolete) bits are clear.
+obsolete) bits are clear. Formally (i.e. as per SPC stardards) the name of
+a standard INQUIRY response is the "standard INQUIRY data format" but here
+the "standard INQUIRY response" is used as it is shorter and more descriptive.
 .PP
 Alternatively the \fI\-\-inhex=FN\fR option can be given. In this case
 \fIFN\fR is assumed to be a file name ('\-' for stdin) containing ASCII
@@ -125,7 +127,8 @@
 useful for tools like udev(7) in Linux.
 .TP
 \fB\-E\fR, \fB\-x\fR, \fB\-\-extended\fR
-prints the extended INQUIRY VPD page [0x86].
+prints the extended INQUIRY VPD page [0x86]. It has the same effect
+as giving the \fI\-\-page=ei\fR option.
 .TP
 \fB\-h\fR, \fB\-\-help\fR
 print out the usage message then exit. When used twice, after the
@@ -148,7 +151,8 @@
 option (e.g. 'sg_inq \-p di \-HHHH /dev/sg3 > dev_id.hex').
 .TP
 \fB\-i\fR, \fB\-\-id\fR
-prints the device identification VPD page [0x83].
+prints the device identification VPD page [0x83]. It has the same effect
+as giving the \fI\-\-page=di\fR option.
 .TP
 \fB\-I\fR, \fB\-\-inhex\fR=\fIFN\fR
 \fIFN\fR is expected to be a file name (or '\-' for stdin) which contains
@@ -338,6 +342,20 @@
 It is possible that even though the \fIDEVICE\fR presents as a NVMe device,
 it has a SNTL and accepts SCSI commands. In this case to send a SCSI INQUIRY
 command (and fetch its VPD pages) use the sg_vpd(8) utility.
+.SH SG_INQ and SG_VPD
+Both these utilities have much in common since VPD pages are fetched with the
+SCSI INQUIRY command. As more VPD pages have been added (and existing pages
+expanded) the newer ones were only decoded with sg_vpd. Recently with the
+optional JSON output work, it was decided to place all VPD page decoding in
+a source file called sg_vpd_common.c that is linked in by both sg_inq and
+sg_vpd.
+.PP
+This means that the VPD page decoding capabilities of both sg_inq and sg_vpd
+will be the same. Their default actions remain as they were, namely when
+sg_inq is used without command line options, it decodes the "standard INQUIRY
+data format" (usually called the "standard INQUIRY response") response while
+when sg_vpd is used without options, it decodes the "Supported VPD pages" VPD
+page.
 .SH EXIT STATUS
 The exit status of sg_inq is 0 when it is successful. Otherwise see
 the sg3_utils(8) man page.
diff --git a/doc/sg_vpd.8 b/doc/sg_vpd.8
index 7f68160..45f496c 100644
--- a/doc/sg_vpd.8
+++ b/doc/sg_vpd.8
@@ -1,4 +1,4 @@
-.TH SG_VPD "8" "July 2022" "sg3_utils\-1.48" SG3_UTILS
+.TH SG_VPD "8" "August 2022" "sg3_utils\-1.48" SG3_UTILS
 .SH NAME
 sg_vpd \- fetch SCSI VPD page and/or decode its response
 .SH SYNOPSIS
diff --git a/include/Makefile.in b/include/Makefile.in
index 6f2fa87..6067757 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -206,6 +206,7 @@
 ETAGS = @ETAGS@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+FILECMD = @FILECMD@
 GETOPT_O_FILES = @GETOPT_O_FILES@
 GREP = @GREP@
 INSTALL = @INSTALL@
diff --git a/include/sg_lib.h b/include/sg_lib.h
index 0e2d842..1fc46d1 100644
--- a/include/sg_lib.h
+++ b/include/sg_lib.h
@@ -661,14 +661,19 @@
 
 /* Read ASCII hex bytes or binary from fname (a file named '-' taken as
  * stdin). If reading ASCII hex then there should be either one entry per
- * line or a comma, space, hyphen or tab separated list of bytes. If
- * no_space is * set then a string of ACSII hex digits is expected, 2 per
- * byte. Everything from and including a '#' on a line is ignored. Returns
- * 0 if ok, or an error code. If the error code is
- * SG_LIB_LBA_OUT_OF_RANGE then mp_arr would be exceeded and both mp_arr
- * and mp_arr_len are written to. */
+ * line or a comma, space, hyphen or tab separated list of bytes. If no_space
+ * is set then a string of ACSII hex digits is expected, 2 per byte.
+ * Everything from and including a '#' on a line is ignored. Returns 0 if ok,
+ * or an error code. If the error code is SG_LIB_LBA_OUT_OF_RANGE then mp_arr
+ * would be exceeded and both mp_arr and mp_arr_len are written to.
+ * The max_arr_len_and argument may carry extra information: when it is
+ * negative its absolute value is used for the maximum number of bytes to
+ * write to mp_arr _and_ the first hexadecimal value on each line is skipped.
+ * Many hexadecimal output programs place a running address (index) as the
+ * first field on each line. When as_binary and/or no_space are true, the
+ * absolute value of max_arr_len_and is used. */
 int sg_f2hex_arr(const char * fname, bool as_binary, bool no_space,
-                 uint8_t * mp_arr, int * mp_arr_len, int max_arr_len);
+                 uint8_t * mp_arr, int * mp_arr_len, int max_arr_len_and);
 
 /* Returns true when executed on big endian machine; else returns false.
  * Useful for displaying ATA identify words (which need swapping on a
diff --git a/inhex/vpd_tpc.hex b/inhex/vpd_tpc.hex
new file mode 100644
index 0000000..e3e9f38
--- /dev/null
+++ b/inhex/vpd_tpc.hex
@@ -0,0 +1,43 @@
+#
+# An example invocation:
+#    sg_vpd --inhex=vpd_tpc.hex
+
+00 8f 00 8c
+
+00 00 00 20
+00 00 00 00 00 00 01 23  00 00 00 3c
+00 00 00 1e 00 00 00 99  88 77 66 55 00 00 00 44
+55 66 77 88
+
+00 01 00 10
+0d
+00 00
+03 00
+12 00
+83 02 10 11
+84 01 07
+00 00 	# pad
+
+00 04 00 1c
+00 00 00 00 00 1c 00 40  00 01 22 33
+00 99 88 77 00 00 00 00  00 00 00 00 00 00 00 00
+
+00 08 00 04
+02
+02 e9
+00	# pad
+
+00 0c 00 0c
+00 08
+00 00
+00 01
+c0 00
+ff ff
+00 00	# pad
+
+00 0d 00 14
+12
+# UUID
+10 00 11 22 33 44 55 66  77 88 99 aa bb cc dd ee
+fe dc
+00   # pad
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 45b464f..406cc02 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -280,6 +280,7 @@
 ETAGS = @ETAGS@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+FILECMD = @FILECMD@
 GETOPT_O_FILES = @GETOPT_O_FILES@
 GREP = @GREP@
 INSTALL = @INSTALL@
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index 7256c43..b1c9792 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -3559,18 +3559,23 @@
 
 /* Read ASCII hex bytes or binary from fname (a file named '-' taken as
  * stdin). If reading ASCII hex then there should be either one entry per
- * line or a comma, space, hyphen or tab separated list of bytes. If
- * no_space is * set then a string of ACSII hex digits is expected, 2 per
- * byte. Everything from and including a '#' on a line is ignored. Returns
- * 0 if ok, or an error code. If the error code is
- * SG_LIB_LBA_OUT_OF_RANGE then mp_arr would be exceeded and both mp_arr
- * and mp_arr_len are written to. */
+ * line or a comma, space, hyphen or tab separated list of bytes. If no_space
+ * is set then a string of ACSII hex digits is expected, 2 perbyte.
+ * Everything from and including a '#' on a line is ignored. Returns 0 if ok,
+ * or an error code. If the error code is SG_LIB_LBA_OUT_OF_RANGE then mp_arr
+ * would be exceeded and both mp_arr and mp_arr_len are written to.
+ * The max_arr_len_and argument may carry extra information: when it
+ * is negative its absolute value is used for the maximum number of bytes to
+ * write to mp_arr _and_ the first hexadecimal value on each line is skipped.
+ * Many hexadecimal output programs place a running address (index) as the
+ * first field on each line. When as_binary and/or no_space are true, the
+ * absolute value of max_arr_len_and is used. */
 int
 sg_f2hex_arr(const char * fname, bool as_binary, bool no_space,
-             uint8_t * mp_arr, int * mp_arr_len, int max_arr_len)
+             uint8_t * mp_arr, int * mp_arr_len, int max_arr_len_and)
 {
-    bool has_stdin, split_line;
-    int fn_len, in_len, k, j, m, fd, err;
+    bool has_stdin, split_line, skip_first, redo_first;
+    int fn_len, in_len, k, j, m, fd, err, max_arr_len;
     int off = 0;
     int ret = 0;
     unsigned int h;
@@ -3584,6 +3589,13 @@
         pr2ws("%s: bad arguments\n", __func__);
         return SG_LIB_LOGIC_ERROR;
     }
+    if (max_arr_len_and < 0) {
+        skip_first = true;
+        max_arr_len = -max_arr_len_and;
+    } else {
+        skip_first = false;
+        max_arr_len = max_arr_len_and;
+    }
     fn_len = strlen(fname);
     if (0 == fn_len)
         return SG_LIB_SYNTAX_ERROR;
@@ -3727,8 +3739,9 @@
             if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1))))
                 carry_over[0] = *lcp;
             off += k;
-        } else {
-            for (k = 0; k < 1024; ++k) {
+        } else {        /* (white)space separated ASCII hexadecimal bytes */
+            for (redo_first = false, k = 0; k < 1024;
+                 k = (redo_first ? k : k + 1)) {
                 if (1 == sscanf(lcp, "%10x", &h)) {
                     if (h > 0xff) {
                         pr2ws("%s: hex number larger than 0xff in line "
@@ -3746,8 +3759,12 @@
                         ret = SG_LIB_LBA_OUT_OF_RANGE;
                         *mp_arr_len = max_arr_len;
                         goto fini;
-                    } else
+                    } else if ((0 == k) && skip_first && (! redo_first))
+                        redo_first = true;
+                    else {
+                        redo_first = false;
                         mp_arr[off + k] = h;
+                    }
                     lcp = strpbrk(lcp, " ,-\t");
                     if (NULL == lcp)
                         break;
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index 3e291eb..4906bb6 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -19,8 +19,8 @@
 #include "sg_lib_data.h"
 
 
-const char * sg_lib_version_str = "2.90 20220622";
-/* spc6r06, sbc5r01, zbc2r13 */
+const char * sg_lib_version_str = "2.91 20220730";
+/* spc6r06, sbc5r03, zbc2r13 */
 
 
 /* indexed by pdt; those that map to own index do not decay */
@@ -434,7 +434,7 @@
  * as there is no need to differentiate. */
 struct sg_lib_value_name_t sg_lib_xcopy_sa_arr[] = {    /* originating */
     {0x0, PDT_ALL, "Extended copy(LID1)"},
-    {0x1, PDT_ALL, "Extended copy"},          /* was 'Extended copy(LID4)' */
+    {0x1, PDT_ALL, "Extended copy"}, /* 'Extended copy(LID4)' until spc5r01 */
     {0x10, PDT_ALL, "Populate token"},
     {0x11, PDT_ALL, "Write using token"},
     {0x16, PDT_TAPE, "Set tape stream mirroring"},     /* ADC-4 and SSC-5 */
diff --git a/ltmain.sh b/ltmain.sh
index 540a92a..49fcad1 100755
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -1,12 +1,12 @@
-#! /bin/sh
+#! /usr/bin/env sh
 ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
-##               by inline-source v2014-01-03.01
+##               by inline-source v2019-02-19.15
 
-# libtool (GNU libtool) 2.4.6
+# libtool (GNU libtool) 2.4.7
 # Provide generalized library-building support services.
 # Written by Gordon Matzigkeit <[email protected]>, 1996
 
-# Copyright (C) 1996-2015 Free Software Foundation, Inc.
+# Copyright (C) 1996-2019, 2021-2022 Free Software Foundation, Inc.
 # This is free software; see the source for copying conditions.  There is NO
 # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
@@ -31,8 +31,8 @@
 
 PROGRAM=libtool
 PACKAGE=libtool
-VERSION="2.4.6 Debian-2.4.6-15build2"
-package_revision=2.4.6
+VERSION=2.4.7
+package_revision=2.4.7
 
 
 ## ------ ##
@@ -64,34 +64,25 @@
 # libraries, which are installed to $pkgauxdir.
 
 # Set a version string for this script.
-scriptversion=2015-01-20.17; # UTC
+scriptversion=2019-02-19.15; # UTC
 
 # General shell script boiler plate, and helper functions.
 # Written by Gary V. Vaughan, 2004
 
-# Copyright (C) 2004-2015 Free Software Foundation, Inc.
-# This is free software; see the source for copying conditions.  There is NO
-# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# This is free software.  There is NO warranty; not even for
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Copyright (C) 2004-2019, 2021 Bootstrap Authors
+#
+# This file is dual licensed under the terms of the MIT license
+# <https://opensource.org/license/MIT>, and GPL version 2 or later
+# <http://www.gnu.org/licenses/gpl-2.0.html>.  You must apply one of
+# these licenses when using or redistributing this software or any of
+# the files within it.  See the URLs above, or the file `LICENSE`
+# included in the Bootstrap distribution for the full license texts.
 
-# 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.
-
-# As a special exception to the GNU General Public License, if you distribute
-# this file as part of a program or library that is built using GNU Libtool,
-# you may include this file under the same distribution terms that you use
-# for the rest of that program.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNES 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/>.
-
-# Please report bugs or propose patches to [email protected].
+# Please report bugs or propose patches to:
+# <https://github.com/gnulib-modules/bootstrap/issues>
 
 
 ## ------ ##
@@ -139,9 +130,12 @@
 	  _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\"
 	fi"
 done
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+# These NLS vars are set unconditionally (bootstrap issue #24).  Unset those
+# in case the environment reset is needed later and the $save_* variant is not
+# defined (see the code above).
+LC_ALL=C
+LANGUAGE=C
+export LANGUAGE LC_ALL
 
 # Make sure IFS has a sensible default
 sp=' '
@@ -159,6 +153,26 @@
 fi
 
 
+# func_unset VAR
+# --------------
+# Portably unset VAR.
+# In some shells, an 'unset VAR' statement leaves a non-zero return
+# status if VAR is already unset, which might be problematic if the
+# statement is used at the end of a function (thus poisoning its return
+# value) or when 'set -e' is active (causing even a spurious abort of
+# the script in this case).
+func_unset ()
+{
+    { eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; }
+}
+
+
+# Make sure CDPATH doesn't cause `cd` commands to output the target dir.
+func_unset CDPATH
+
+# Make sure ${,E,F}GREP behave sanely.
+func_unset GREP_OPTIONS
+
 
 ## ------------------------- ##
 ## Locate command utilities. ##
@@ -259,7 +273,7 @@
     rm -f conftest.in conftest.tmp conftest.nl conftest.out
   }
 
-  func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin
+  func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin"
   rm -f conftest.sed
   SED=$func_path_progs_result
 }
@@ -295,7 +309,7 @@
     rm -f conftest.in conftest.tmp conftest.nl conftest.out
   }
 
-  func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin
+  func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin"
   GREP=$func_path_progs_result
 }
 
@@ -360,6 +374,35 @@
   s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g
   s/\n//g"
 
+# require_check_ifs_backslash
+# ---------------------------
+# Check if we can use backslash as IFS='\' separator, and set
+# $check_ifs_backshlash_broken to ':' or 'false'.
+require_check_ifs_backslash=func_require_check_ifs_backslash
+func_require_check_ifs_backslash ()
+{
+  _G_save_IFS=$IFS
+  IFS='\'
+  _G_check_ifs_backshlash='a\\b'
+  for _G_i in $_G_check_ifs_backshlash
+  do
+  case $_G_i in
+  a)
+    check_ifs_backshlash_broken=false
+    ;;
+  '')
+    break
+    ;;
+  *)
+    check_ifs_backshlash_broken=:
+    break
+    ;;
+  esac
+  done
+  IFS=$_G_save_IFS
+  require_check_ifs_backslash=:
+}
+
 
 ## ----------------- ##
 ## Global variables. ##
@@ -387,7 +430,7 @@
 # putting '$debug_cmd' at the start of all your functions, you can get
 # bash to show function call trace with:
 #
-#    debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
+#    debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
 debug_cmd=${debug_cmd-":"}
 exit_cmd=:
 
@@ -580,16 +623,16 @@
   {
     $debug_cmd
 
-    func_quote_for_eval "$2"
-    eval "$1+=\\ \$func_quote_for_eval_result"
+    func_quote_arg pretty "$2"
+    eval "$1+=\\ \$func_quote_arg_result"
   }'
 else
   func_append_quoted ()
   {
     $debug_cmd
 
-    func_quote_for_eval "$2"
-    eval "$1=\$$1\\ \$func_quote_for_eval_result"
+    func_quote_arg pretty "$2"
+    eval "$1=\$$1\\ \$func_quote_arg_result"
   }
 fi
 
@@ -1091,85 +1134,203 @@
 }
 
 
-# func_quote_for_eval ARG...
-# --------------------------
-# Aesthetically quote ARGs to be evaled later.
-# This function returns two values:
-#   i) func_quote_for_eval_result
-#      double-quoted, suitable for a subsequent eval
-#  ii) func_quote_for_eval_unquoted_result
-#      has all characters that are still active within double
-#      quotes backslashified.
-func_quote_for_eval ()
+# func_quote_portable EVAL ARG
+# ----------------------------
+# Internal function to portably implement func_quote_arg.  Note that we still
+# keep attention to performance here so we as much as possible try to avoid
+# calling sed binary (so far O(N) complexity as long as func_append is O(1)).
+func_quote_portable ()
 {
     $debug_cmd
 
-    func_quote_for_eval_unquoted_result=
-    func_quote_for_eval_result=
-    while test 0 -lt $#; do
-      case $1 in
+    $require_check_ifs_backslash
+
+    func_quote_portable_result=$2
+
+    # one-time-loop (easy break)
+    while true
+    do
+      if $1; then
+        func_quote_portable_result=`$ECHO "$2" | $SED \
+          -e "$sed_double_quote_subst" -e "$sed_double_backslash"`
+        break
+      fi
+
+      # Quote for eval.
+      case $func_quote_portable_result in
         *[\\\`\"\$]*)
-	  _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;;
-        *)
-          _G_unquoted_arg=$1 ;;
-      esac
-      if test -n "$func_quote_for_eval_unquoted_result"; then
-	func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg"
-      else
-        func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg"
-      fi
+          # Fallback to sed for $func_check_bs_ifs_broken=:, or when the string
+          # contains the shell wildcard characters.
+          case $check_ifs_backshlash_broken$func_quote_portable_result in
+            :*|*[\[\*\?]*)
+              func_quote_portable_result=`$ECHO "$func_quote_portable_result" \
+                  | $SED "$sed_quote_subst"`
+              break
+              ;;
+          esac
 
-      case $_G_unquoted_arg in
-        # Double-quote args containing shell metacharacters to delay
-        # word splitting, command substitution and variable expansion
-        # for a subsequent eval.
-        # Many Bourne shells cannot handle close brackets correctly
-        # in scan sets, so we specify it separately.
-        *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-          _G_quoted_arg=\"$_G_unquoted_arg\"
+          func_quote_portable_old_IFS=$IFS
+          for _G_char in '\' '`' '"' '$'
+          do
+            # STATE($1) PREV($2) SEPARATOR($3)
+            set start "" ""
+            func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy
+            IFS=$_G_char
+            for _G_part in $func_quote_portable_result
+            do
+              case $1 in
+              quote)
+                func_append func_quote_portable_result "$3$2"
+                set quote "$_G_part" "\\$_G_char"
+                ;;
+              start)
+                set first "" ""
+                func_quote_portable_result=
+                ;;
+              first)
+                set quote "$_G_part" ""
+                ;;
+              esac
+            done
+          done
+          IFS=$func_quote_portable_old_IFS
           ;;
-        *)
-          _G_quoted_arg=$_G_unquoted_arg
-	  ;;
+        *) ;;
       esac
-
-      if test -n "$func_quote_for_eval_result"; then
-	func_append func_quote_for_eval_result " $_G_quoted_arg"
-      else
-        func_append func_quote_for_eval_result "$_G_quoted_arg"
-      fi
-      shift
+      break
     done
+
+    func_quote_portable_unquoted_result=$func_quote_portable_result
+    case $func_quote_portable_result in
+      # double-quote args containing shell metacharacters to delay
+      # word splitting, command substitution and variable expansion
+      # for a subsequent eval.
+      # many bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        func_quote_portable_result=\"$func_quote_portable_result\"
+        ;;
+    esac
 }
 
 
-# func_quote_for_expand ARG
-# -------------------------
-# Aesthetically quote ARG to be evaled later; same as above,
-# but do not quote variable references.
-func_quote_for_expand ()
+# func_quotefast_eval ARG
+# -----------------------
+# Quote one ARG (internal).  This is equivalent to 'func_quote_arg eval ARG',
+# but optimized for speed.  Result is stored in $func_quotefast_eval.
+if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then
+  printf -v _GL_test_printf_tilde %q '~'
+  if test '\~' = "$_GL_test_printf_tilde"; then
+    func_quotefast_eval ()
+    {
+      printf -v func_quotefast_eval_result %q "$1"
+    }
+  else
+    # Broken older Bash implementations.  Make those faster too if possible.
+    func_quotefast_eval ()
+    {
+      case $1 in
+        '~'*)
+          func_quote_portable false "$1"
+          func_quotefast_eval_result=$func_quote_portable_result
+          ;;
+        *)
+          printf -v func_quotefast_eval_result %q "$1"
+          ;;
+      esac
+    }
+  fi
+else
+  func_quotefast_eval ()
+  {
+    func_quote_portable false "$1"
+    func_quotefast_eval_result=$func_quote_portable_result
+  }
+fi
+
+
+# func_quote_arg MODEs ARG
+# ------------------------
+# Quote one ARG to be evaled later.  MODEs argument may contain zero or more
+# specifiers listed below separated by ',' character.  This function returns two
+# values:
+#   i) func_quote_arg_result
+#      double-quoted (when needed), suitable for a subsequent eval
+#  ii) func_quote_arg_unquoted_result
+#      has all characters that are still active within double
+#      quotes backslashified.  Available only if 'unquoted' is specified.
+#
+# Available modes:
+# ----------------
+# 'eval' (default)
+#       - escape shell special characters
+# 'expand'
+#       - the same as 'eval';  but do not quote variable references
+# 'pretty'
+#       - request aesthetic output, i.e. '"a b"' instead of 'a\ b'.  This might
+#         be used later in func_quote to get output like: 'echo "a b"' instead
+#         of 'echo a\ b'.  This is slower than default on some shells.
+# 'unquoted'
+#       - produce also $func_quote_arg_unquoted_result which does not contain
+#         wrapping double-quotes.
+#
+# Examples for 'func_quote_arg pretty,unquoted string':
+#
+#   string      | *_result              | *_unquoted_result
+#   ------------+-----------------------+-------------------
+#   "           | \"                    | \"
+#   a b         | "a b"                 | a b
+#   "a b"       | "\"a b\""             | \"a b\"
+#   *           | "*"                   | *
+#   z="${x-$y}" | "z=\"\${x-\$y}\""     | z=\"\${x-\$y}\"
+#
+# Examples for 'func_quote_arg pretty,unquoted,expand string':
+#
+#   string        |   *_result          |  *_unquoted_result
+#   --------------+---------------------+--------------------
+#   z="${x-$y}"   | "z=\"${x-$y}\""     | z=\"${x-$y}\"
+func_quote_arg ()
 {
-    $debug_cmd
-
-    case $1 in
-      *[\\\`\"]*)
-	_G_arg=`$ECHO "$1" | $SED \
-	    -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;;
-      *)
-        _G_arg=$1 ;;
-    esac
-
-    case $_G_arg in
-      # Double-quote args containing shell metacharacters to delay
-      # word splitting and command substitution for a subsequent eval.
-      # Many Bourne shells cannot handle close brackets correctly
-      # in scan sets, so we specify it separately.
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-        _G_arg=\"$_G_arg\"
+    _G_quote_expand=false
+    case ,$1, in
+      *,expand,*)
+        _G_quote_expand=:
         ;;
     esac
 
-    func_quote_for_expand_result=$_G_arg
+    case ,$1, in
+      *,pretty,*|*,expand,*|*,unquoted,*)
+        func_quote_portable $_G_quote_expand "$2"
+        func_quote_arg_result=$func_quote_portable_result
+        func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result
+        ;;
+      *)
+        # Faster quote-for-eval for some shells.
+        func_quotefast_eval "$2"
+        func_quote_arg_result=$func_quotefast_eval_result
+        ;;
+    esac
+}
+
+
+# func_quote MODEs ARGs...
+# ------------------------
+# Quote all ARGs to be evaled later and join them into single command.  See
+# func_quote_arg's description for more info.
+func_quote ()
+{
+    $debug_cmd
+    _G_func_quote_mode=$1 ; shift
+    func_quote_result=
+    while test 0 -lt $#; do
+      func_quote_arg "$_G_func_quote_mode" "$1"
+      if test -n "$func_quote_result"; then
+        func_append func_quote_result " $func_quote_arg_result"
+      else
+        func_append func_quote_result "$func_quote_arg_result"
+      fi
+      shift
+    done
 }
 
 
@@ -1215,8 +1376,8 @@
     _G_cmd=$1
     _G_fail_exp=${2-':'}
 
-    func_quote_for_expand "$_G_cmd"
-    eval "func_notquiet $func_quote_for_expand_result"
+    func_quote_arg pretty,expand "$_G_cmd"
+    eval "func_notquiet $func_quote_arg_result"
 
     $opt_dry_run || {
       eval "$_G_cmd"
@@ -1241,8 +1402,8 @@
     _G_fail_exp=${2-':'}
 
     $opt_quiet || {
-      func_quote_for_expand "$_G_cmd"
-      eval "func_echo $func_quote_for_expand_result"
+      func_quote_arg expand,pretty "$_G_cmd"
+      eval "func_echo $func_quote_arg_result"
     }
 
     $opt_dry_run || {
@@ -1369,30 +1530,26 @@
 # End:
 #! /bin/sh
 
-# Set a version string for this script.
-scriptversion=2015-10-07.11; # UTC
-
 # A portable, pluggable option parser for Bourne shell.
 # Written by Gary V. Vaughan, 2010
 
-# Copyright (C) 2010-2015 Free Software Foundation, Inc.
-# This is free software; see the source for copying conditions.  There is NO
-# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# This is free software.  There is NO warranty; not even for
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Copyright (C) 2010-2019, 2021 Bootstrap Authors
+#
+# This file is dual licensed under the terms of the MIT license
+# <https://opensource.org/license/MIT>, and GPL version 2 or later
+# <http://www.gnu.org/licenses/gpl-2.0.html>.  You must apply one of
+# these licenses when using or redistributing this software or any of
+# the files within it.  See the URLs above, or the file `LICENSE`
+# included in the Bootstrap distribution for the full license texts.
 
-# 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.
+# Please report bugs or propose patches to:
+# <https://github.com/gnulib-modules/bootstrap/issues>
 
-# 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/>.
-
-# Please report bugs or propose patches to [email protected].
+# Set a version string for this script.
+scriptversion=2019-02-19.15; # UTC
 
 
 ## ------ ##
@@ -1415,7 +1572,7 @@
 #
 # In order for the '--version' option to work, you will need to have a
 # suitably formatted comment like the one at the top of this file
-# starting with '# Written by ' and ending with '# warranty; '.
+# starting with '# Written by ' and ending with '# Copyright'.
 #
 # For '-h' and '--help' to work, you will also need a one line
 # description of your script's purpose in a comment directly above the
@@ -1427,7 +1584,7 @@
 # to display verbose messages only when your user has specified
 # '--verbose'.
 #
-# After sourcing this file, you can plug processing for additional
+# After sourcing this file, you can plug in processing for additional
 # options by amending the variables from the 'Configuration' section
 # below, and following the instructions in the 'Option parsing'
 # section further down.
@@ -1476,8 +1633,8 @@
 ## ------------------------- ##
 
 # This section contains functions for adding, removing, and running hooks
-# to the main code.  A hook is just a named list of of function, that can
-# be run in order later on.
+# in the main code.  A hook is just a list of function names that can be
+# run in order later on.
 
 # func_hookable FUNC_NAME
 # -----------------------
@@ -1510,7 +1667,8 @@
 
 # func_remove_hook FUNC_NAME HOOK_FUNC
 # ------------------------------------
-# Remove HOOK_FUNC from the list of functions called by FUNC_NAME.
+# Remove HOOK_FUNC from the list of hook functions to be called by
+# FUNC_NAME.
 func_remove_hook ()
 {
     $debug_cmd
@@ -1519,10 +1677,28 @@
 }
 
 
+# func_propagate_result FUNC_NAME_A FUNC_NAME_B
+# ---------------------------------------------
+# If the *_result variable of FUNC_NAME_A _is set_, assign its value to
+# *_result variable of FUNC_NAME_B.
+func_propagate_result ()
+{
+    $debug_cmd
+
+    func_propagate_result_result=:
+    if eval "test \"\${${1}_result+set}\" = set"
+    then
+      eval "${2}_result=\$${1}_result"
+    else
+      func_propagate_result_result=false
+    fi
+}
+
+
 # func_run_hooks FUNC_NAME [ARG]...
 # ---------------------------------
 # Run all hook functions registered to FUNC_NAME.
-# It is assumed that the list of hook functions contains nothing more
+# It's assumed that the list of hook functions contains nothing more
 # than a whitespace-delimited list of legal shell function names, and
 # no effort is wasted trying to catch shell meta-characters or preserve
 # whitespace.
@@ -1530,26 +1706,21 @@
 {
     $debug_cmd
 
-    _G_rc_run_hooks=false
-
     case " $hookable_fns " in
       *" $1 "*) ;;
-      *) func_fatal_error "'$1' does not support hook funcions.n" ;;
+      *) func_fatal_error "'$1' does not support hook functions." ;;
     esac
 
     eval _G_hook_fns=\$$1_hooks; shift
 
     for _G_hook in $_G_hook_fns; do
-      if eval $_G_hook '"$@"'; then
-        # store returned options list back into positional
-        # parameters for next 'cmd' execution.
-        eval _G_hook_result=\$${_G_hook}_result
-        eval set dummy "$_G_hook_result"; shift
-        _G_rc_run_hooks=:
+      func_unset "${_G_hook}_result"
+      eval $_G_hook '${1+"$@"}'
+      func_propagate_result $_G_hook func_run_hooks
+      if $func_propagate_result_result; then
+        eval set dummy "$func_run_hooks_result"; shift
       fi
     done
-
-    $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result
 }
 
 
@@ -1559,14 +1730,16 @@
 ## --------------- ##
 
 # In order to add your own option parsing hooks, you must accept the
-# full positional parameter list in your hook function, you may remove/edit
-# any options that you action, and then pass back the remaining unprocessed
-# options in '<hooked_function_name>_result', escaped suitably for
-# 'eval'.  In this case you also must return $EXIT_SUCCESS to let the
-# hook's caller know that it should pay attention to
-# '<hooked_function_name>_result'.  Returning $EXIT_FAILURE signalizes that
-# arguments are left untouched by the hook and therefore caller will ignore the
-# result variable.
+# full positional parameter list from your hook function.  You may remove
+# or edit any options that you action, and then pass back the remaining
+# unprocessed options in '<hooked_function_name>_result', escaped
+# suitably for 'eval'.
+#
+# The '<hooked_function_name>_result' variable is automatically unset
+# before your hook gets called; for best performance, only set the
+# *_result variable when necessary (i.e. don't call the 'func_quote'
+# function unnecessarily because it can be an expensive operation on some
+# machines).
 #
 # Like this:
 #
@@ -1578,11 +1751,8 @@
 #        usage_message=$usage_message'
 #      -s, --silent       don'\''t print informational messages
 #    '
-#        # No change in '$@' (ignored completely by this hook).  There is
-#        # no need to do the equivalent (but slower) action:
-#        # func_quote_for_eval ${1+"$@"}
-#        # my_options_prep_result=$func_quote_for_eval_result
-#        false
+#        # No change in '$@' (ignored completely by this hook).  Leave
+#        # my_options_prep_result variable intact.
 #    }
 #    func_add_hook func_options_prep my_options_prep
 #
@@ -1593,7 +1763,7 @@
 #
 #        args_changed=false
 #
-#        # Note that for efficiency, we parse as many options as we can
+#        # Note that, for efficiency, we parse as many options as we can
 #        # recognise in a loop before passing the remainder back to the
 #        # caller on the first unrecognised argument we encounter.
 #        while test $# -gt 0; do
@@ -1610,18 +1780,17 @@
 #                         args_changed=:
 #                         ;;
 #            *)           # Make sure the first unrecognised option "$_G_opt"
-#                         # is added back to "$@", we could need that later
-#                         # if $args_changed is true.
+#                         # is added back to "$@" in case we need it later,
+#                         # if $args_changed was set to 'true'.
 #                         set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
 #          esac
 #        done
 #
+#        # Only call 'func_quote' here if we processed at least one argument.
 #        if $args_changed; then
-#          func_quote_for_eval ${1+"$@"}
-#          my_silent_option_result=$func_quote_for_eval_result
+#          func_quote eval ${1+"$@"}
+#          my_silent_option_result=$func_quote_result
 #        fi
-#
-#        $args_changed
 #    }
 #    func_add_hook func_parse_options my_silent_option
 #
@@ -1632,8 +1801,6 @@
 #
 #        $opt_silent && $opt_verbose && func_fatal_help "\
 #    '--silent' and '--verbose' options are mutually exclusive."
-#
-#        false
 #    }
 #    func_add_hook func_validate_options my_option_validation
 #
@@ -1649,13 +1816,8 @@
 {
     $debug_cmd
 
-    _G_func_options_finish_exit=false
-    if func_run_hooks func_options ${1+"$@"}; then
-      func_options_finish_result=$func_run_hooks_result
-      _G_func_options_finish_exit=:
-    fi
-
-    $_G_func_options_finish_exit
+    func_run_hooks func_options ${1+"$@"}
+    func_propagate_result func_run_hooks func_options_finish
 }
 
 
@@ -1668,28 +1830,27 @@
 {
     $debug_cmd
 
-    _G_rc_options=false
+    _G_options_quoted=false
 
     for my_func in options_prep parse_options validate_options options_finish
     do
-      if eval func_$my_func '${1+"$@"}'; then
-        eval _G_res_var='$'"func_${my_func}_result"
-        eval set dummy "$_G_res_var" ; shift
-        _G_rc_options=:
+      func_unset func_${my_func}_result
+      func_unset func_run_hooks_result
+      eval func_$my_func '${1+"$@"}'
+      func_propagate_result func_$my_func func_options
+      if $func_propagate_result_result; then
+        eval set dummy "$func_options_result"; shift
+        _G_options_quoted=:
       fi
     done
 
-    # Save modified positional parameters for caller.  As a top-level
-    # options-parser function we always need to set the 'func_options_result'
-    # variable (regardless the $_G_rc_options value).
-    if $_G_rc_options; then
-      func_options_result=$_G_res_var
-    else
-      func_quote_for_eval ${1+"$@"}
-      func_options_result=$func_quote_for_eval_result
-    fi
-
-    $_G_rc_options
+    $_G_options_quoted || {
+      # As we (func_options) are top-level options-parser function and
+      # nobody quoted "$@" for us yet, we need to do it explicitly for
+      # caller.
+      func_quote eval ${1+"$@"}
+      func_options_result=$func_quote_result
+    }
 }
 
 
@@ -1699,8 +1860,7 @@
 # Note that when calling hook functions, we pass through the list of
 # positional parameters.  If a hook function modifies that list, and
 # needs to propagate that back to rest of this script, then the complete
-# modified list must be put in 'func_run_hooks_result' before
-# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned).
+# modified list must be put in 'func_run_hooks_result' before returning.
 func_hookable func_options_prep
 func_options_prep ()
 {
@@ -1710,14 +1870,8 @@
     opt_verbose=false
     opt_warning_types=
 
-    _G_rc_options_prep=false
-    if func_run_hooks func_options_prep ${1+"$@"}; then
-      _G_rc_options_prep=:
-      # save modified positional parameters for caller
-      func_options_prep_result=$func_run_hooks_result
-    fi
-
-    $_G_rc_options_prep
+    func_run_hooks func_options_prep ${1+"$@"}
+    func_propagate_result func_run_hooks func_options_prep
 }
 
 
@@ -1729,27 +1883,32 @@
 {
     $debug_cmd
 
-    func_parse_options_result=
-
-    _G_rc_parse_options=false
+    _G_parse_options_requote=false
     # this just eases exit handling
     while test $# -gt 0; do
       # Defer to hook functions for initial option parsing, so they
       # get priority in the event of reusing an option name.
-      if func_run_hooks func_parse_options ${1+"$@"}; then
-        eval set dummy "$func_run_hooks_result"; shift
-        _G_rc_parse_options=:
+      func_run_hooks func_parse_options ${1+"$@"}
+      func_propagate_result func_run_hooks func_parse_options
+      if $func_propagate_result_result; then
+        eval set dummy "$func_parse_options_result"; shift
+        # Even though we may have changed "$@", we passed the "$@" array
+        # down into the hook and it quoted it for us (because we are in
+        # this if-branch).  No need to quote it again.
+        _G_parse_options_requote=false
       fi
 
       # Break out of the loop if we already parsed every option.
       test $# -gt 0 || break
 
+      # We expect that one of the options parsed in this function matches
+      # and thus we remove _G_opt from "$@" and need to re-quote.
       _G_match_parse_options=:
       _G_opt=$1
       shift
       case $_G_opt in
         --debug|-x)   debug_cmd='set -x'
-                      func_echo "enabling shell trace mode"
+                      func_echo "enabling shell trace mode" >&2
                       $debug_cmd
                       ;;
 
@@ -1760,7 +1919,7 @@
 
         --warnings|--warning|-W)
                       if test $# = 0 && func_missing_arg $_G_opt; then
-                        _G_rc_parse_options=:
+                        _G_parse_options_requote=:
                         break
                       fi
                       case " $warning_categories $1" in
@@ -1815,7 +1974,7 @@
                       shift
                       ;;
 
-        --)           _G_rc_parse_options=: ; break ;;
+        --)           _G_parse_options_requote=: ; break ;;
         -*)           func_fatal_help "unrecognised option: '$_G_opt'" ;;
         *)            set dummy "$_G_opt" ${1+"$@"}; shift
                       _G_match_parse_options=false
@@ -1823,17 +1982,16 @@
                       ;;
       esac
 
-      $_G_match_parse_options && _G_rc_parse_options=:
+      if $_G_match_parse_options; then
+        _G_parse_options_requote=:
+      fi
     done
 
-
-    if $_G_rc_parse_options; then
+    if $_G_parse_options_requote; then
       # save modified positional parameters for caller
-      func_quote_for_eval ${1+"$@"}
-      func_parse_options_result=$func_quote_for_eval_result
+      func_quote eval ${1+"$@"}
+      func_parse_options_result=$func_quote_result
     fi
-
-    $_G_rc_parse_options
 }
 
 
@@ -1846,21 +2004,14 @@
 {
     $debug_cmd
 
-    _G_rc_validate_options=false
-
     # Display all warnings if -W was not given.
     test -n "$opt_warning_types" || opt_warning_types=" $warning_categories"
 
-    if func_run_hooks func_validate_options ${1+"$@"}; then
-      # save modified positional parameters for caller
-      func_validate_options_result=$func_run_hooks_result
-      _G_rc_validate_options=:
-    fi
+    func_run_hooks func_validate_options ${1+"$@"}
+    func_propagate_result func_run_hooks func_validate_options
 
     # Bail if the options were screwed!
     $exit_cmd $EXIT_FAILURE
-
-    $_G_rc_validate_options
 }
 
 
@@ -1916,8 +2067,8 @@
 
 # func_split_equals STRING
 # ------------------------
-# Set func_split_equals_lhs and func_split_equals_rhs shell variables after
-# splitting STRING at the '=' sign.
+# Set func_split_equals_lhs and func_split_equals_rhs shell variables
+# after splitting STRING at the '=' sign.
 test -z "$_G_HAVE_XSI_OPS" \
     && (eval 'x=a/b/c;
       test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
@@ -1932,8 +2083,9 @@
 
       func_split_equals_lhs=${1%%=*}
       func_split_equals_rhs=${1#*=}
-      test "x$func_split_equals_lhs" = "x$1" \
-        && func_split_equals_rhs=
+      if test "x$func_split_equals_lhs" = "x$1"; then
+        func_split_equals_rhs=
+      fi
   }'
 else
   # ...otherwise fall back to using expr, which is often a shell builtin.
@@ -1943,7 +2095,7 @@
 
       func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'`
       func_split_equals_rhs=
-      test "x$func_split_equals_lhs" = "x$1" \
+      test "x$func_split_equals_lhs=" = "x$1" \
         || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'`
   }
 fi #func_split_equals
@@ -1969,7 +2121,7 @@
   {
       $debug_cmd
 
-      func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'`
+      func_split_short_opt_name=`expr "x$1" : 'x\(-.\)'`
       func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'`
   }
 fi #func_split_short_opt
@@ -2011,31 +2163,44 @@
 # func_version
 # ------------
 # Echo version message to standard output and exit.
+# The version message is extracted from the calling file's header
+# comments, with leading '# ' stripped:
+#   1. First display the progname and version
+#   2. Followed by the header comment line matching  /^# Written by /
+#   3. Then a blank line followed by the first following line matching
+#      /^# Copyright /
+#   4. Immediately followed by any lines between the previous matches,
+#      except lines preceding the intervening completely blank line.
+# For example, see the header comments of this file.
 func_version ()
 {
     $debug_cmd
 
     printf '%s\n' "$progname $scriptversion"
     $SED -n '
-        /(C)/!b go
-        :more
-        /\./!{
-          N
-          s|\n# | |
-          b more
+        /^# Written by /!b
+        s|^# ||; p; n
+
+        :fwd2blnk
+        /./ {
+          n
+          b fwd2blnk
         }
-        :go
-        /^# Written by /,/# warranty; / {
-          s|^# ||
-          s|^# *$||
-          s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2|
-          p
+        p; n
+
+        :holdwrnt
+        s|^# ||
+        s|^# *$||
+        /^Copyright /!{
+          /./H
+          n
+          b holdwrnt
         }
-        /^# Written by / {
-          s|^# ||
-          p
-        }
-        /^warranty; /q' < "$progpath"
+
+        s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2|
+        G
+        s|\(\n\)\n*|\1|g
+        p; q' < "$progpath"
 
     exit $?
 }
@@ -2045,12 +2210,12 @@
 # mode: shell-script
 # sh-indentation: 2
 # eval: (add-hook 'before-save-hook 'time-stamp)
-# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC"
 # time-stamp-time-zone: "UTC"
 # End:
 
 # Set a version string.
-scriptversion='(GNU libtool) 2.4.6'
+scriptversion='(GNU libtool) 2.4.7'
 
 
 # func_echo ARG...
@@ -2141,12 +2306,12 @@
        compiler:       $LTCC
        compiler flags: $LTCFLAGS
        linker:         $LD (gnu? $with_gnu_ld)
-       version:        $progname $scriptversion Debian-2.4.6-15build2
+       version:        $progname (GNU libtool) 2.4.7
        automake:       `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
        autoconf:       `($AUTOCONF --version) 2>/dev/null |$SED 1q`
 
 Report bugs to <[email protected]>.
-GNU libtool home page: <http://www.gnu.org/s/libtool/>.
+GNU libtool home page: <http://www.gnu.org/software/libtool/>.
 General help using GNU software: <http://www.gnu.org/gethelp/>."
     exit 0
 }
@@ -2197,7 +2362,7 @@
 # a configuration failure hint, and exit.
 func_fatal_configuration ()
 {
-    func__fatal_error ${1+"$@"} \
+    func_fatal_error ${1+"$@"} \
       "See the $PACKAGE documentation for more information." \
       "Fatal configuration error."
 }
@@ -2375,11 +2540,9 @@
 
     if $_G_rc_lt_options_prep; then
       # Pass back the list of options.
-      func_quote_for_eval ${1+"$@"}
-      libtool_options_prep_result=$func_quote_for_eval_result
+      func_quote eval ${1+"$@"}
+      libtool_options_prep_result=$func_quote_result
     fi
-
-    $_G_rc_lt_options_prep
 }
 func_add_hook func_options_prep libtool_options_prep
 
@@ -2482,11 +2645,9 @@
 
     if $_G_rc_lt_parse_options; then
       # save modified positional parameters for caller
-      func_quote_for_eval ${1+"$@"}
-      libtool_parse_options_result=$func_quote_for_eval_result
+      func_quote eval ${1+"$@"}
+      libtool_parse_options_result=$func_quote_result
     fi
-
-    $_G_rc_lt_parse_options
 }
 func_add_hook func_parse_options libtool_parse_options
 
@@ -2507,17 +2668,10 @@
     # preserve --debug
     test : = "$debug_cmd" || func_append preserve_args " --debug"
 
-    case $host in
-      # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452
-      # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788
-      *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*)
-        # don't eliminate duplications in $postdeps and $predeps
-        opt_duplicate_compiler_generated_deps=:
-        ;;
-      *)
-        opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
-        ;;
-    esac
+    # Keeping compiler generated duplicates in $postdeps and $predeps is not
+    # harmful, and is necessary in a majority of systems that use it to satisfy
+    # symbol dependencies.
+    opt_duplicate_compiler_generated_deps=:
 
     $opt_help || {
       # Sanity checks first:
@@ -2543,8 +2697,8 @@
     }
 
     # Pass back the unparsed argument list
-    func_quote_for_eval ${1+"$@"}
-    libtool_validate_options_result=$func_quote_for_eval_result
+    func_quote eval ${1+"$@"}
+    libtool_validate_options_result=$func_quote_result
 }
 func_add_hook func_validate_options libtool_validate_options
 
@@ -3510,8 +3664,8 @@
       esac
     done
 
-    func_quote_for_eval "$libobj"
-    test "X$libobj" != "X$func_quote_for_eval_result" \
+    func_quote_arg pretty "$libobj"
+    test "X$libobj" != "X$func_quote_arg_result" \
       && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
       && func_warning "libobj name '$libobj' may not contain shell special characters."
     func_dirname_and_basename "$obj" "/" ""
@@ -3584,8 +3738,8 @@
 
     func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
     srcfile=$func_to_tool_file_result
-    func_quote_for_eval "$srcfile"
-    qsrcfile=$func_quote_for_eval_result
+    func_quote_arg pretty "$srcfile"
+    qsrcfile=$func_quote_arg_result
 
     # Only build a PIC object if we are building libtool libraries.
     if test yes = "$build_libtool_libs"; then
@@ -3740,7 +3894,8 @@
   -prefer-non-pic   try to build non-PIC objects only
   -shared           do not build a '.o' file suitable for static linking
   -static           only build a '.o' file suitable for static linking
-  -Wc,FLAG          pass FLAG directly to the compiler
+  -Wc,FLAG
+  -Xcompiler FLAG   pass FLAG directly to the compiler
 
 COMPILE-COMMAND is a command to be used in creating a 'standard' object file
 from the given SOURCEFILE.
@@ -3846,6 +4001,8 @@
   -weak LIBNAME     declare that the target provides the LIBNAME interface
   -Wc,FLAG
   -Xcompiler FLAG   pass linker-specific FLAG directly to the compiler
+  -Wa,FLAG
+  -Xassembler FLAG  pass linker-specific FLAG directly to the assembler
   -Wl,FLAG
   -Xlinker FLAG     pass linker-specific FLAG directly to the linker
   -XCClinker FLAG   pass link-specific FLAG to the compiler driver (CC)
@@ -4188,8 +4345,8 @@
        case $nonopt in *shtool*) :;; *) false;; esac
     then
       # Aesthetically quote it.
-      func_quote_for_eval "$nonopt"
-      install_prog="$func_quote_for_eval_result "
+      func_quote_arg pretty "$nonopt"
+      install_prog="$func_quote_arg_result "
       arg=$1
       shift
     else
@@ -4199,8 +4356,8 @@
 
     # The real first argument should be the name of the installation program.
     # Aesthetically quote it.
-    func_quote_for_eval "$arg"
-    func_append install_prog "$func_quote_for_eval_result"
+    func_quote_arg pretty "$arg"
+    func_append install_prog "$func_quote_arg_result"
     install_shared_prog=$install_prog
     case " $install_prog " in
       *[\\\ /]cp\ *) install_cp=: ;;
@@ -4257,12 +4414,12 @@
       esac
 
       # Aesthetically quote the argument.
-      func_quote_for_eval "$arg"
-      func_append install_prog " $func_quote_for_eval_result"
+      func_quote_arg pretty "$arg"
+      func_append install_prog " $func_quote_arg_result"
       if test -n "$arg2"; then
-	func_quote_for_eval "$arg2"
+	func_quote_arg pretty "$arg2"
       fi
-      func_append install_shared_prog " $func_quote_for_eval_result"
+      func_append install_shared_prog " $func_quote_arg_result"
     done
 
     test -z "$install_prog" && \
@@ -4273,8 +4430,8 @@
 
     if test -n "$install_override_mode" && $no_mode; then
       if $install_cp; then :; else
-	func_quote_for_eval "$install_override_mode"
-	func_append install_shared_prog " -m $func_quote_for_eval_result"
+	func_quote_arg pretty "$install_override_mode"
+	func_append install_shared_prog " -m $func_quote_arg_result"
       fi
     fi
 
@@ -4570,8 +4727,8 @@
 	        relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
 
 	        $opt_quiet || {
-	          func_quote_for_expand "$relink_command"
-		  eval "func_echo $func_quote_for_expand_result"
+	          func_quote_arg expand,pretty "$relink_command"
+		  eval "func_echo $func_quote_arg_result"
 	        }
 	        if eval "$relink_command"; then :
 	          else
@@ -5350,7 +5507,8 @@
   if test \"\$libtool_execute_magic\" != \"$magic\"; then
     file=\"\$0\""
 
-    qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
+    func_quote_arg pretty "$ECHO"
+    qECHO=$func_quote_arg_result
     $ECHO "\
 
 # A function that is used when there is no print builtin or printf.
@@ -5360,7 +5518,7 @@
 \$1
 _LTECHO_EOF'
 }
-    ECHO=\"$qECHO\"
+    ECHO=$qECHO
   fi
 
 # Very basic option parsing. These options are (a) specific to
@@ -6703,9 +6861,9 @@
     while test "$#" -gt 0; do
       arg=$1
       shift
-      func_quote_for_eval "$arg"
-      qarg=$func_quote_for_eval_unquoted_result
-      func_append libtool_args " $func_quote_for_eval_result"
+      func_quote_arg pretty,unquoted "$arg"
+      qarg=$func_quote_arg_unquoted_result
+      func_append libtool_args " $func_quote_arg_result"
 
       # If the previous option needs an argument, assign it.
       if test -n "$prev"; then
@@ -6941,6 +7099,13 @@
 	  prev=
 	  continue
 	  ;;
+	xassembler)
+	  func_append compiler_flags " -Xassembler $qarg"
+	  prev=
+	  func_append compile_command " -Xassembler $qarg"
+	  func_append finalize_command " -Xassembler $qarg"
+	  continue
+	  ;;
 	xcclinker)
 	  func_append linker_flags " $qarg"
 	  func_append compiler_flags " $qarg"
@@ -7111,7 +7276,7 @@
 	    # These systems don't actually have a C library (as such)
 	    test X-lc = "X$arg" && continue
 	    ;;
-	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*)
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*)
 	    # Do not include libc due to us having libc/libc_r.
 	    test X-lc = "X$arg" && continue
 	    ;;
@@ -7131,7 +7296,7 @@
 	  esac
 	elif test X-lc_r = "X$arg"; then
 	 case $host in
-	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*)
+	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*)
 	   # Do not include libc_r directly, use -pthread flag.
 	   continue
 	   ;;
@@ -7161,8 +7326,20 @@
 	prev=xcompiler
 	continue
 	;;
-
-      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+     # Solaris ld rejects as of 11.4. Refer to Oracle bug 22985199.
+     -pthread)
+	case $host in
+	  *solaris2*) ;;
+	  *)
+	    case "$new_inherited_linker_flags " in
+	        *" $arg "*) ;;
+	        * ) func_append new_inherited_linker_flags " $arg" ;;
+	    esac
+	  ;;
+	esac
+	continue
+	;;
+      -mt|-mthreads|-kthread|-Kthread|-pthreads|--thread-safe \
       |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
 	func_append compiler_flags " $arg"
 	func_append compile_command " $arg"
@@ -7303,9 +7480,9 @@
 	save_ifs=$IFS; IFS=,
 	for flag in $args; do
 	  IFS=$save_ifs
-          func_quote_for_eval "$flag"
-	  func_append arg " $func_quote_for_eval_result"
-	  func_append compiler_flags " $func_quote_for_eval_result"
+          func_quote_arg pretty "$flag"
+	  func_append arg " $func_quote_arg_result"
+	  func_append compiler_flags " $func_quote_arg_result"
 	done
 	IFS=$save_ifs
 	func_stripname ' ' '' "$arg"
@@ -7319,16 +7496,21 @@
 	save_ifs=$IFS; IFS=,
 	for flag in $args; do
 	  IFS=$save_ifs
-          func_quote_for_eval "$flag"
-	  func_append arg " $wl$func_quote_for_eval_result"
-	  func_append compiler_flags " $wl$func_quote_for_eval_result"
-	  func_append linker_flags " $func_quote_for_eval_result"
+          func_quote_arg pretty "$flag"
+	  func_append arg " $wl$func_quote_arg_result"
+	  func_append compiler_flags " $wl$func_quote_arg_result"
+	  func_append linker_flags " $func_quote_arg_result"
 	done
 	IFS=$save_ifs
 	func_stripname ' ' '' "$arg"
 	arg=$func_stripname_result
 	;;
 
+      -Xassembler)
+        prev=xassembler
+        continue
+        ;;
+
       -Xcompiler)
 	prev=xcompiler
 	continue
@@ -7346,8 +7528,8 @@
 
       # -msg_* for osf cc
       -msg_*)
-	func_quote_for_eval "$arg"
-	arg=$func_quote_for_eval_result
+	func_quote_arg pretty "$arg"
+	arg=$func_quote_arg_result
 	;;
 
       # Flags to be passed through unchanged, with rationale:
@@ -7368,14 +7550,13 @@
       # -stdlib=*            select c++ std lib with clang
       # -fsanitize=*         Clang/GCC memory and address sanitizer
       # -fuse-ld=*           Linker select flags for GCC
-      # -static-*            direct GCC to link specific libraries statically
-      # -fcilkplus           Cilk Plus language extension features for C/C++
+      # -Wa,*                Pass flags directly to the assembler
       -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
       -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
       -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
-      -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus)
-        func_quote_for_eval "$arg"
-	arg=$func_quote_for_eval_result
+      -specs=*|-fsanitize=*|-fuse-ld=*|-Wa,*)
+        func_quote_arg pretty "$arg"
+	arg=$func_quote_arg_result
         func_append compile_command " $arg"
         func_append finalize_command " $arg"
         func_append compiler_flags " $arg"
@@ -7396,15 +7577,15 @@
 	  continue
         else
 	  # Otherwise treat like 'Some other compiler flag' below
-	  func_quote_for_eval "$arg"
-	  arg=$func_quote_for_eval_result
+	  func_quote_arg pretty "$arg"
+	  arg=$func_quote_arg_result
         fi
 	;;
 
       # Some other compiler flag.
       -* | +*)
-        func_quote_for_eval "$arg"
-	arg=$func_quote_for_eval_result
+        func_quote_arg pretty "$arg"
+	arg=$func_quote_arg_result
 	;;
 
       *.$objext)
@@ -7524,8 +7705,8 @@
       *)
 	# Unknown arguments in both finalize_command and compile_command need
 	# to be aesthetically quoted because they are evaled later.
-	func_quote_for_eval "$arg"
-	arg=$func_quote_for_eval_result
+	func_quote_arg pretty "$arg"
+	arg=$func_quote_arg_result
 	;;
       esac # arg
 
@@ -7666,10 +7847,7 @@
 	case $pass in
 	dlopen) libs=$dlfiles ;;
 	dlpreopen) libs=$dlprefiles ;;
-	link)
-	  libs="$deplibs %DEPLIBS%"
-	  test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
-	  ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
 	esac
       fi
       if test lib,dlpreopen = "$linkmode,$pass"; then
@@ -7988,19 +8166,19 @@
 	    # It is a libtool convenience library, so add in its objects.
 	    func_append convenience " $ladir/$objdir/$old_library"
 	    func_append old_convenience " $ladir/$objdir/$old_library"
-	    tmp_libs=
-	    for deplib in $dependency_libs; do
-	      deplibs="$deplib $deplibs"
-	      if $opt_preserve_dup_deps; then
-		case "$tmp_libs " in
-		*" $deplib "*) func_append specialdeplibs " $deplib" ;;
-		esac
-	      fi
-	      func_append tmp_libs " $deplib"
-	    done
 	  elif test prog != "$linkmode" && test lib != "$linkmode"; then
 	    func_fatal_error "'$lib' is not a convenience library"
 	  fi
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    deplibs="$deplib $deplibs"
+	    if $opt_preserve_dup_deps; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+	      esac
+	    fi
+	    func_append tmp_libs " $deplib"
+	  done
 	  continue
 	fi # $pass = conv
 
@@ -8733,7 +8911,7 @@
       test CXX = "$tagname" && {
         case $host_os in
         linux*)
-          case `$CC -V 2>&1 | sed 5q` in
+          case `$CC -V 2>&1 | $SED 5q` in
           *Sun\ C*) # Sun C++ 5.9
             func_suncc_cstd_abi
 
@@ -8906,7 +9084,7 @@
 	  #
 	  case $version_type in
 	  # correct linux to gnu/linux during the next big refactor
-	  darwin|freebsd-elf|linux|osf|windows|none)
+	  darwin|freebsd-elf|linux|midnightbsd-elf|osf|windows|none)
 	    func_arith $number_major + $number_minor
 	    current=$func_arith_result
 	    age=$number_minor
@@ -8924,9 +9102,6 @@
 	    revision=$number_minor
 	    lt_irix_increment=no
 	    ;;
-	  *)
-	    func_fatal_configuration "$modename: unknown library version type '$version_type'"
-	    ;;
 	  esac
 	  ;;
 	no)
@@ -9000,7 +9175,7 @@
 	  versuffix=.$current.$revision
 	  ;;
 
-	freebsd-elf)
+	freebsd-elf | midnightbsd-elf)
 	  func_arith $current - $age
 	  major=.$func_arith_result
 	  versuffix=$major.$age.$revision
@@ -9226,7 +9401,7 @@
 	  *-*-netbsd*)
 	    # Don't link with libc until the a.out ld.so is fixed.
 	    ;;
-	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*)
 	    # Do not include libc due to us having libc/libc_r.
 	    ;;
 	  *-*-sco3.2v5* | *-*-sco5v6*)
@@ -10037,8 +10212,8 @@
 	    for cmd in $concat_cmds; do
 	      IFS=$save_ifs
 	      $opt_quiet || {
-		  func_quote_for_expand "$cmd"
-		  eval "func_echo $func_quote_for_expand_result"
+		  func_quote_arg expand,pretty "$cmd"
+		  eval "func_echo $func_quote_arg_result"
 	      }
 	      $opt_dry_run || eval "$cmd" || {
 		lt_exit=$?
@@ -10131,8 +10306,8 @@
 	  eval cmd=\"$cmd\"
 	  IFS=$save_ifs
 	  $opt_quiet || {
-	    func_quote_for_expand "$cmd"
-	    eval "func_echo $func_quote_for_expand_result"
+	    func_quote_arg expand,pretty "$cmd"
+	    eval "func_echo $func_quote_arg_result"
 	  }
 	  $opt_dry_run || eval "$cmd" || {
 	    lt_exit=$?
@@ -10606,12 +10781,13 @@
 	  elif eval var_value=\$$var; test -z "$var_value"; then
 	    relink_command="$var=; export $var; $relink_command"
 	  else
-	    func_quote_for_eval "$var_value"
-	    relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	    func_quote_arg pretty "$var_value"
+	    relink_command="$var=$func_quote_arg_result; export $var; $relink_command"
 	  fi
 	done
-	relink_command="(cd `pwd`; $relink_command)"
-	relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+	func_quote eval cd "`pwd`"
+	func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)"
+	relink_command=$func_quote_arg_unquoted_result
       fi
 
       # Only actually do things if not in dry run mode.
@@ -10851,13 +11027,15 @@
 	elif eval var_value=\$$var; test -z "$var_value"; then
 	  relink_command="$var=; export $var; $relink_command"
 	else
-	  func_quote_for_eval "$var_value"
-	  relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	  func_quote_arg pretty,unquoted "$var_value"
+	  relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command"
 	fi
       done
       # Quote the link command for shipping.
-      relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
-      relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      func_quote eval cd "`pwd`"
+      relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      func_quote_arg pretty,unquoted "$relink_command"
+      relink_command=$func_quote_arg_unquoted_result
       if test yes = "$hardcode_automatic"; then
 	relink_command=
       fi
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index 65650db..8d2a418 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -177,6 +177,7 @@
 ETAGS = @ETAGS@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+FILECMD = @FILECMD@
 GETOPT_O_FILES = @GETOPT_O_FILES@
 GREP = @GREP@
 INSTALL = @INSTALL@
diff --git a/src/Makefile.in b/src/Makefile.in
index 9fb93bf..c07b012 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -547,6 +547,7 @@
 ETAGS = @ETAGS@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+FILECMD = @FILECMD@
 GETOPT_O_FILES = @GETOPT_O_FILES@
 GREP = @GREP@
 INSTALL = @INSTALL@
diff --git a/src/sg_decode_sense.c b/src/sg_decode_sense.c
index e902d0a..db54e0b 100644
--- a/src/sg_decode_sense.c
+++ b/src/sg_decode_sense.c
@@ -30,11 +30,11 @@
 #include "sg_unaligned.h"
 
 
-static const char * version_str = "1.31 20220729";
+static const char * version_str = "1.32 20220730";
 
 #define MY_NAME "sg_decode_sense"
 
-#define MAX_SENSE_LEN 4096 /* max descriptor format actually: 255+8 */
+#define MAX_SENSE_LEN 8192 /* max descriptor format actually: 255+8 */
 
 static struct option long_options[] = {
     {"binary", required_argument, 0, 'b'},
@@ -46,8 +46,10 @@
     {"help", no_argument, 0, 'h'},
     {"hex", no_argument, 0, 'H'},
     {"in", required_argument, 0, 'i'},          /* don't advertise */
-    {"json", optional_argument, 0, 'j'},
     {"inhex", required_argument, 0, 'i'},       /* same as --file */
+    {"ignore-first", no_argument, 0, 'I'},
+    {"ignore_first", no_argument, 0, 'I'},
+    {"json", optional_argument, 0, 'j'},
     {"nodecode", no_argument, 0, 'N'},
     {"nospace", no_argument, 0, 'n'},
     {"status", required_argument, 0, 's'},
@@ -68,6 +70,7 @@
     bool version_given;
     bool err_given;
     bool file_given;
+    bool ignore_first;
     const char * fname;
     int es_val;
     int hex_count;
@@ -89,10 +92,11 @@
   pr2serr("Usage: sg_decode_sense [--binary=BFN] [--cdb] [--err=ES] "
           "[--file=HFN]\n"
           "                       [--help] [--hex] [--inhex=HFN] "
-          "[--json[=JO]]\n"
-          "                       [--nodecode] [--nospace] [--status=SS] "
-          "[--verbose]\n"
-          "                       [--version] [--write=WFN] H1 H2 H3 ...\n"
+          "[--ignore-first]\n"
+          "                       [--json[=JO]] [--nodecode] [--nospace] "
+          "[--status=SS]\n"
+          "                       [--verbose] [--version] [--write=WFN] "
+          "H1 H2 H3 ...\n"
           "  where:\n"
           "    --binary=BFN|-b BFN    BFN is a file name to read sense "
           "data in\n"
@@ -116,6 +120,10 @@
           "                          hex (used '-HH' or '-HHH' for different "
           "formats)\n"
           "    --inhex=HFN|-i HFN    same as action as --file=HFN\n"
+          "    --ignore-first|-I     when reading hex (e.g. with --file=HFN) "
+          "skip\n"
+          "                          the first hexadecimal value on each "
+          "line\n"
           "    --json[=JO]|-j[JO]    output in JSON instead of human "
           "readable text.\n"
           "                          Use --json=? for JSON help\n"
@@ -149,7 +157,7 @@
     char *endptr;
 
     while (1) {
-        c = getopt_long(argc, argv, "b:ce:f:hHi:j::nNs:vVw:", long_options,
+        c = getopt_long(argc, argv, "b:ce:f:hHi:Ij::nNs:vVw:", long_options,
                         NULL);
         if (c == -1)
             break;
@@ -201,6 +209,9 @@
             op->file_given = true;
             op->fname = optarg;
             break;
+        case 'I':
+            op->ignore_first = true;
+            break;
        case 'j':
             if (! sgj_init_state(&op->json_st, optarg)) {
                 int bad_char = op->json_st.first_bad_char;
@@ -333,12 +344,17 @@
     const char * cp;
     sgj_state * jsp;
     sgj_opaque_p jop = NULL;
+    uint8_t * free_op_buff = NULL;
     char b[2048];
-    struct opts_t opts;
 
-    op = &opts;
+    op = (struct opts_t *)sg_memalign(sizeof(*op), 0 /* page align */,
+				      &free_op_buff, false);
+    if (NULL == op) {
+        pr2serr("Unable to allocate heap for options structure\n");
+        ret = sg_convert_errno(ENOMEM);
+        goto clean_op;
+    }
     blen = sizeof(b);
-    memset(op, 0, sizeof(opts));
     memset(b, 0, blen);
     ret = parse_cmd_line(op, argc, argv);
 
@@ -360,14 +376,14 @@
 #endif
     if (op->version_given) {
         pr2serr("version: %s\n", version_str);
-        return 0;
+        goto clean_op;
     }
     if (ret != 0) {
         usage();
-        return ret;
+        goto clean_op;
     } else if (op->do_help) {
         usage();
-        return 0;
+        goto clean_op;
     }
     as_json = op->json_st.pr_as_json;
     jsp = &op->json_st;
@@ -450,7 +466,9 @@
         op->sense_len = s;
     } else if (op->file_given) {
         ret = sg_f2hex_arr(op->fname, false, op->no_space, op->sense,
-                           &op->sense_len, MAX_SENSE_LEN);
+                           &op->sense_len,
+                           (op->ignore_first ? -MAX_SENSE_LEN :
+                                               MAX_SENSE_LEN));
         if (ret) {
             pr2serr("unable to decode ASCII hex from file: %s\n", op->fname);
             goto fini;
@@ -522,5 +540,8 @@
             sgj_js2file(&op->json_st, NULL, ret, stdout);
         sgj_finish(jsp);
     }
+clean_op:
+    if (free_op_buff)
+        free(free_op_buff);
     return ret;
 }
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 001970f..9745c0e 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -53,7 +53,7 @@
 
 #include "sg_vpd_common.h"  /* for shared VPD page processing with sg_vpd */
 
-static const char * version_str = "2.26 20220729";  /* spc6r06 */
+static const char * version_str = "2.27 20220806";  /* spc6r06, sbc5r03 */
 
 #define MY_NAME "sg_inq"
 
@@ -328,8 +328,7 @@
             "Performs a SCSI INQUIRY command on DEVICE or decodes INQUIRY "
             "response\nheld in file FN. If no options given then does a "
             "'standard' INQUIRY.\nCan list VPD pages with '--vpd' or "
-            "'--page=PG' option. The sg_vpd\nand sdparm utilities decode "
-            "more VPD pages than this utility.\n");
+            "'--page=PG' option.\n");
 }
 
 #ifdef SG_SCSI_STRINGS
@@ -3270,6 +3269,60 @@
             decode_dev_constit_vpd(rp, len, op, jap, recurse_vpd_decode);
         }
         break;
+    case VPD_3PARTY_COPY:       /* 0x8f  ["tpc"] */
+        np = "Third party copy VPD page";
+        if (!op->do_raw && (op->do_hex < 2))
+            sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
+        res = vpd_fetch_page_from_dev(sg_fd, rp, pn, op->maxlen, vb, &len);
+        if (res)
+            break;
+        if (op->do_raw)
+            dStrRaw((const char *)rp, len);
+        else {
+            if (as_json) {
+                jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+                jap = sgj_named_subarray_r(jsp, jo2p,
+                                  "third_party_copy_descriptor_list");
+            }
+            decode_3party_copy_vpd(rp, len, op, jap);
+        }
+        break;
+    case VPD_PROTO_LU:          /* 0x90  ["pslu"] */
+        np = "Protocol specific logical unit information VPD page";
+        if (!op->do_raw && (op->do_hex < 2))
+            sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
+        res = vpd_fetch_page_from_dev(sg_fd, rp, pn, op->maxlen, vb, &len);
+        if (res)
+            break;
+        if (op->do_raw)
+            dStrRaw((const char *)rp, len);
+        else {
+            if (as_json) {
+                jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+                jap = sgj_named_subarray_r(jsp, jo2p,
+                                  "logical_unit_information_descriptor_list");
+            }
+            decode_proto_lu_vpd(rp, len, op, jap);
+        }
+        break;
+    case VPD_PROTO_PORT:        /* 0x91  ["pspo"] */
+        np = "Protocol specific port information VPD page";
+        if (!op->do_raw && (op->do_hex < 2))
+            sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
+        res = vpd_fetch_page_from_dev(sg_fd, rp, pn, op->maxlen, vb, &len);
+        if (res)
+            break;
+        if (op->do_raw)
+            dStrRaw((const char *)rp, len);
+        else {
+            if (as_json) {
+                jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+                jap = sgj_named_subarray_r(jsp, jo2p,
+                                  "port_information_descriptor_list");
+            }
+            decode_proto_port_vpd(rp, len, op, jap);
+        }
+        break;
     case VPD_SCSI_FEATURE_SETS:         /* 0x92  ["sfs"] */
         np = "SCSI Feature sets VPD page";
         if (!op->do_raw && (op->do_hex < 2))
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index a0bf503..50f2c8a 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -42,7 +42,7 @@
 
 */
 
-static const char * version_str = "1.78 20220729";  /* spc6r06 + sbc5r01 */
+static const char * version_str = "1.79 20220806";  /* spc6r06 + sbc5r03 */
 
 #define MY_NAME "sg_vpd"
 
@@ -874,508 +874,6 @@
     return 0;
 }
 
-/* This is xcopy(LID4) related: "ROD" == Representation Of Data
- * Used by VPD_3PARTY_COPY */
-static void
-decode_rod_descriptor(const uint8_t * buff, int len)
-{
-    const uint8_t * bp = buff;
-    int k, bump;
-    uint64_t ul;
-
-    for (k = 0; k < len; k += bump, bp += bump) {
-        bump = sg_get_unaligned_be16(bp + 2) + 4;
-        switch (bp[0]) {
-            case 0:
-                /* Block ROD device type specific descriptor */
-                printf("  Optimal block ROD length granularity: %d\n",
-                       sg_get_unaligned_be16(bp + 6));
-                printf("  Maximum Bytes in block ROD: %" PRIu64 "\n",
-                       sg_get_unaligned_be64(bp + 8));
-                ul = sg_get_unaligned_be64(bp + 16);
-                printf("  Optimal Bytes in block ROD transfer: ");
-                if (SG_LIB_UNBOUNDED_64BIT == ul)
-                    printf("-1 [no limit]\n");
-                else
-                    printf("%" PRIu64 "\n", ul);
-                ul = sg_get_unaligned_be64(bp + 24);
-                printf("  Optimal Bytes to token per segment: ");
-                if (SG_LIB_UNBOUNDED_64BIT == ul)
-                    printf("-1 [no limit]\n");
-                else
-                    printf("%" PRIu64 "\n", ul);
-                ul = sg_get_unaligned_be64(bp + 32);
-                printf("  Optimal Bytes from token per segment: ");
-                if (SG_LIB_UNBOUNDED_64BIT == ul)
-                    printf("-1 [no limit]\n");
-                else
-                    printf("%" PRIu64 "\n", ul);
-                break;
-            case 1:
-                /* Stream ROD device type specific descriptor */
-                printf("  Maximum Bytes in stream ROD: %" PRIu64 "\n",
-                       sg_get_unaligned_be64(bp + 8));
-                ul = sg_get_unaligned_be64(bp + 16);
-                printf("  Optimal Bytes in stream ROD transfer: ");
-                if (SG_LIB_UNBOUNDED_64BIT == ul)
-                    printf("-1 [no limit]\n");
-                else
-                    printf("%" PRIu64 "\n", ul);
-                break;
-            case 3:
-                /* Copy manager ROD device type specific descriptor */
-                printf("  Maximum Bytes in processor ROD: %" PRIu64 "\n",
-                       sg_get_unaligned_be64(bp + 8));
-                ul = sg_get_unaligned_be64(bp + 16);
-                printf("  Optimal Bytes in processor ROD transfer: ");
-                if (SG_LIB_UNBOUNDED_64BIT == ul)
-                    printf("-1 [no limit]\n");
-                else
-                    printf("%" PRIu64 "\n", ul);
-                break;
-            default:
-                printf("  Unhandled descriptor (format %d, device type %d)\n",
-                       bp[0] >> 5, bp[0] & 0x1F);
-                break;
-        }
-    }
-}
-
-struct tpc_desc_type {
-    uint8_t code;
-    const char * name;
-};
-
-static struct tpc_desc_type tpc_desc_arr[] = {
-    {0x0, "block -> stream"},
-    {0x1, "stream -> block"},
-    {0x2, "block -> block"},
-    {0x3, "stream -> stream"},
-    {0x4, "inline -> stream"},
-    {0x5, "embedded -> stream"},
-    {0x6, "stream -> discard"},
-    {0x7, "verify CSCD"},
-    {0x8, "block<o> -> stream"},
-    {0x9, "stream -> block<o>"},
-    {0xa, "block<o> -> block<o>"},
-    {0xb, "block -> stream & application_client"},
-    {0xc, "stream -> block & application_client"},
-    {0xd, "block -> block & application_client"},
-    {0xe, "stream -> stream&application_client"},
-    {0xf, "stream -> discard&application_client"},
-    {0x10, "filemark -> tape"},
-    {0x11, "space -> tape"},            /* obsolete: spc5r02 */
-    {0x12, "locate -> tape"},           /* obsolete: spc5r02 */
-    {0x13, "<i>tape -> <i>tape"},
-    {0x14, "register persistent reservation key"},
-    {0x15, "third party persistent reservation source I_T nexus"},
-    {0x16, "<i>block -> <i>block"},
-    {0x17, "positioning -> tape"},      /* this and next added spc5r02 */
-    {0x18, "<loi>tape -> <loi>tape"},   /* loi: logical object identifier */
-    {0xbe, "ROD <- block range(n)"},
-    {0xbf, "ROD <- block range(1)"},
-    {0xe0, "CSCD: FC N_Port_Name"},
-    {0xe1, "CSCD: FC N_Port_ID"},
-    {0xe2, "CSCD: FC N_Port_ID with N_Port_Name, checking"},
-    {0xe3, "CSCD: Parallel interface: I_T"},
-    {0xe4, "CSCD: Identification Descriptor"},
-    {0xe5, "CSCD: IPv4"},
-    {0xe6, "CSCD: Alias"},
-    {0xe7, "CSCD: RDMA"},
-    {0xe8, "CSCD: IEEE 1394 EUI-64"},
-    {0xe9, "CSCD: SAS SSP"},
-    {0xea, "CSCD: IPv6"},
-    {0xeb, "CSCD: IP copy service"},
-    {0xfe, "CSCD: ROD"},
-    {0xff, "CSCD: extension"},
-    {0x0, NULL},
-};
-
-static const char *
-get_tpc_desc_name(uint8_t code)
-{
-    const struct tpc_desc_type * dtp;
-
-    for (dtp = tpc_desc_arr; dtp->name; ++dtp) {
-        if (code == dtp->code)
-            return dtp->name;
-    }
-    return "";
-}
-
-struct tpc_rod_type {
-    uint32_t type;
-    const char * name;
-};
-
-static struct tpc_rod_type tpc_rod_arr[] = {
-    {0x0, "copy manager internal"},
-    {0x10000, "access upon reference"},
-    {0x800000, "point in time copy - default"},
-    {0x800001, "point in time copy - change vulnerable"},
-    {0x800002, "point in time copy - persistent"},
-    {0x80ffff, "point in time copy - any"},
-    {0xffff0001, "block device zero"},
-    {0x0, NULL},
-};
-
-static const char *
-get_tpc_rod_name(uint32_t rod_type)
-{
-    const struct tpc_rod_type * rtp;
-
-    for (rtp = tpc_rod_arr; rtp->name; ++rtp) {
-        if (rod_type == rtp->type)
-            return rtp->name;
-    }
-    return "";
-}
-
-struct cscd_desc_id_t {
-    uint16_t id;
-    const char * name;
-};
-
-static struct cscd_desc_id_t cscd_desc_id_arr[] = {
-    /* only values higher than 0x7ff are listed */
-    {0xc000, "copy src or dst null LU, pdt=0"},
-    {0xc001, "copy src or dst null LU, pdt=1"},
-    {0xf800, "copy src or dst in ROD token"},
-    {0xffff, "copy src or dst is copy manager LU"},
-    {0x0, NULL},
-};
-
-static const char *
-get_cscd_desc_id_name(uint16_t cscd_desc_id)
-{
-    const struct cscd_desc_id_t * cdip;
-
-    for (cdip = cscd_desc_id_arr; cdip->name; ++cdip) {
-        if (cscd_desc_id == cdip->id)
-            return cdip->name;
-    }
-    return "";
-}
-
-/* VPD_3PARTY_COPY [3PC, third party copy] */
-static void
-decode_3party_copy_vpd(uint8_t * buff, int len, int do_hex, int pdt,
-                       int verbose)
-{
-    int j, k, m, bump, desc_type, desc_len, sa_len, blen;
-    unsigned int u;
-    const uint8_t * bp;
-    const char * cp;
-    uint64_t ull;
-    char b[120];
-
-    if (len < 4) {
-        pr2serr("Third-party Copy VPD page length too short=%d\n", len);
-        return;
-    }
-    if (3 == do_hex) {
-        hex2stdout(buff, len, -1);
-        return;
-    }
-    blen = sizeof(b);
-    len -= 4;
-    bp = buff + 4;
-    for (k = 0; k < len; k += bump, bp += bump) {
-        desc_type = sg_get_unaligned_be16(bp);
-        desc_len = sg_get_unaligned_be16(bp + 2);
-        if (verbose)
-            printf("Descriptor type=%d [0x%x] , len %d\n", desc_type,
-                   desc_type, desc_len);
-        bump = 4 + desc_len;
-        if ((k + bump) > len) {
-            pr2serr("Third-party Copy VPD page, short descriptor length=%d, "
-                    "left=%d\n", bump, (len - k));
-            return;
-        }
-        if (0 == desc_len)
-            continue;
-        if (2 == do_hex)
-            hex2stdout(bp + 4, desc_len, 1);
-        else if (do_hex > 2)
-            hex2stdout(bp, bump, 1);
-        else {
-            int csll;
-
-            switch (desc_type) {
-            case 0x0000:    /* Required if POPULATE TOKEN (or friend) used */
-                printf(" Block Device ROD Token Limits:\n");
-                u = sg_get_unaligned_be16(bp + 10);
-                printf("  Maximum range descriptors: ");
-                if (0 == u)
-                    printf("0 [not reported]\n");
-                else
-                    printf("%u\n", u);
-                u = sg_get_unaligned_be32(bp + 12);
-                printf("  Maximum inactivity timeout: ");
-                if (0 == u)
-                    printf("0 [not reported]\n");
-                else if (SG_LIB_UNBOUNDED_32BIT == u)
-                    printf("-1 [no maximum given]\n");
-                else
-                    printf("%u seconds\n", u);
-                u = sg_get_unaligned_be32(bp + 16);
-                printf("  Default inactivity timeout: ");
-                if (0 == u)
-                    printf("0 [not reported]\n");
-                else
-                    printf("%u seconds\n", u);
-                ull = sg_get_unaligned_be64(bp + 20);
-                printf("  Maximum token transfer size: ");
-                if (0 == ull)
-                    printf("0 [not reported]\n");
-                else
-                    printf("%" PRIu64 "\n", ull);
-                ull = sg_get_unaligned_be64(bp + 28);
-                printf("  Optimal transfer count: ");
-                if (0 == ull)
-                    printf("0 [not reported]\n");
-                else
-                    printf("%" PRIu64 "\n", ull);
-                break;
-            case 0x0001:    /* Mandatory (SPC-4) */
-                printf(" Supported commands:\n");
-                j = 0;
-                csll = bp[4];
-                if (csll >= desc_len) {
-                    pr2serr("Command supported list length (%d) >= "
-                            "descriptor length (%d), wrong so trim\n",
-                            csll, desc_len);
-                    csll = desc_len - 1;
-                }
-                while (j < csll) {
-                    sa_len = bp[6 + j];
-                    for (m = 0; (m < sa_len) && ((j + m) < csll); ++m) {
-                        sg_get_opcode_sa_name(bp[5 + j], bp[7 + j + m],
-                                              pdt, blen, b);
-                        printf("  %s\n", b);
-                    }
-                    if (0 == sa_len) {
-                        sg_get_opcode_name(bp[5 + j], pdt, blen, b);
-                        printf("  %s\n",  b);
-                    } else if (m < sa_len)
-                        pr2serr("Supported service actions list length (%d) "
-                                "is too large\n", sa_len);
-                    j += m + 2;
-                }
-                break;
-            case 0x0004:
-                printf(" Parameter data:\n");
-                printf("  Maximum CSCD descriptor count: %d\n",
-                       sg_get_unaligned_be16(bp + 8));
-                printf("  Maximum segment descriptor count: %d\n",
-                       sg_get_unaligned_be16(bp + 10));
-                u = sg_get_unaligned_be32(bp + 12);
-                printf("  Maximum descriptor list length: %u\n", u);
-                u = sg_get_unaligned_be32(bp + 16);
-                printf("  Maximum inline data length: %u\n", u);
-                break;
-            case 0x0008:
-                printf(" Supported descriptors:\n");
-                for (j = 0; j < bp[4]; j++) {
-                    cp = get_tpc_desc_name(bp[5 + j]);
-                    if (strlen(cp) > 0)
-                        printf("  %s [0x%x]\n", cp, bp[5 + j]);
-                    else
-                        printf("  0x%x\n", bp[5 + j]);
-                }
-                break;
-            case 0x000C:
-                printf(" Supported CSCD IDs (above 0x7ff):\n");
-                for (j = 0; j < sg_get_unaligned_be16(bp + 4); j += 2) {
-                    u = sg_get_unaligned_be16(bp + 6 + j);
-                    cp = get_cscd_desc_id_name(u);
-                    if (strlen(cp) > 0)
-                        printf("  %s [0x%04x]\n", cp, u);
-                    else
-                        printf("  0x%04x\n", u);
-                }
-                break;
-            case 0x000D:
-                printf(" Copy group identifier:\n");
-                u = bp[4];
-                sg_t10_uuid_desig2str(bp + 5, u, 1 /* c_set */, false,
-                                      false, NULL, blen, b);
-                printf("%s", b);
-                break;
-            case 0x0106:
-                printf(" ROD token features:\n");
-                printf("  Remote tokens: %d\n", bp[4] & 0x0f);
-                u = sg_get_unaligned_be32(bp + 16);
-                printf("  Minimum token lifetime: %u seconds\n", u);
-                u = sg_get_unaligned_be32(bp + 20);
-                printf("  Maximum token lifetime: %u seconds\n", u);
-                u = sg_get_unaligned_be32(bp + 24);
-                printf("  Maximum token inactivity timeout: %u\n", u);
-                decode_rod_descriptor(bp + 48,
-                                      sg_get_unaligned_be16(bp + 46));
-                break;
-            case 0x0108:
-                printf(" Supported ROD token and ROD types:\n");
-                for (j = 0; j < sg_get_unaligned_be16(bp + 6); j+= 64) {
-                    u = sg_get_unaligned_be32(bp + 8 + j);
-                    cp = get_tpc_rod_name(u);
-                    if (strlen(cp) > 0)
-                        printf("  ROD type: %s [0x%x]\n", cp, u);
-                    else
-                        printf("  ROD type: 0x%x\n", u);
-                    printf("    Internal: %s\n",
-                           (bp[8 + j + 4] & 0x80) ? "yes" : "no");
-                    printf("    Token in: %s\n",
-                           (bp[8 + j + 4] & 0x02) ? "yes" : "no");
-                    printf("    Token out: %s\n",
-                           (bp[8 + j + 4] & 0x01) ? "yes" : "no");
-                    printf("    Preference: %d\n",
-                           sg_get_unaligned_be16(bp + 8 + j + 6));
-                }
-                break;
-            case 0x8001:    /* Mandatory (SPC-4) */
-                printf(" General copy operations:\n");
-                u = sg_get_unaligned_be32(bp + 4);
-                printf("  Total concurrent copies: %u\n", u);
-                u = sg_get_unaligned_be32(bp + 8);
-                printf("  Maximum identified concurrent copies: %u\n", u);
-                u = sg_get_unaligned_be32(bp + 12);
-                printf("  Maximum segment length: %u\n", u);
-                printf("  Data segment granularity: ");
-                u = bp[16];     /* field is power of 2 */
-                if (u < 64)
-                    printf("%" PRIu64 "\n", (uint64_t)1 << u);
-                else
-                    printf("too large [2^%u]\n", u);
-                printf("  Inline data granularity: ");
-                u = bp[17];     /* field is power of 2 */
-                if (u < 64)
-                    printf("%" PRIu64 "\n", (uint64_t)1 << u);
-                else
-                    printf("too large [2^%u]\n", u);
-                break;
-            case 0x9101:
-                printf(" Stream copy operations:\n");
-                u = sg_get_unaligned_be32(bp + 4);
-                printf("  Maximum stream device transfer size: %u\n", u);
-                break;
-            case 0xC001:
-                printf(" Held data:\n");
-                u = sg_get_unaligned_be32(bp + 4);
-                printf("  Held data limit: %u\n", u);
-                ull = ((uint64_t)1 << bp[8]);
-                printf("  Held data granularity: %" PRIu64 "\n", ull);
-                break;
-            default:
-                pr2serr("Unexpected type=%d\n", desc_type);
-                hex2stderr(bp, bump, 1);
-                break;
-            }
-        }
-    }
-}
-
-/* VPD_PROTO_LU */
-static void
-decode_proto_lu_vpd(uint8_t * buff, int len, int do_hex)
-{
-    int k, bump, rel_port, desc_len, proto;
-    uint8_t * bp;
-
-    if ((1 == do_hex) || (do_hex > 2)) {
-        hex2stdout(buff, len, (1 == do_hex) ? 1 : -1);
-        return;
-    }
-    if (len < 4) {
-        pr2serr("Protocol-specific logical unit information VPD page length "
-                "too short=%d\n", len);
-        return;
-    }
-    len -= 4;
-    bp = buff + 4;
-    for (k = 0; k < len; k += bump, bp += bump) {
-        rel_port = sg_get_unaligned_be16(bp);
-        printf("  Relative port=%d\n", rel_port);
-        proto = bp[2] & 0xf;
-        desc_len = sg_get_unaligned_be16(bp + 6);
-        bump = 8 + desc_len;
-        if ((k + bump) > len) {
-            pr2serr("Protocol-specific logical unit information VPD page, "
-                    "short descriptor length=%d, left=%d\n", bump, (len - k));
-            return;
-        }
-        if (0 == desc_len)
-            continue;
-        if (2 == do_hex) {
-            hex2stdout(bp + 8, desc_len, 1);
-            continue;
-        }
-        switch (proto) {
-        case TPROTO_SAS:
-            printf("    Protocol identifier: SAS\n");
-            printf("    TLR control supported: %d\n", !!(bp[8] & 0x1));
-            break;
-        default:
-            pr2serr("Unexpected proto=%d\n", proto);
-            hex2stderr(bp, bump, 1);
-            break;
-        }
-    }
-}
-
-/* VPD_PROTO_PORT */
-static void
-decode_proto_port_vpd(uint8_t * buff, int len, int do_hex)
-{
-    int k, j, bump, rel_port, desc_len, proto;
-    uint8_t * bp;
-    uint8_t * pidp;
-
-    if ((1 == do_hex) || (do_hex > 2)) {
-        hex2stdout(buff, len, (1 == do_hex) ? 1 : -1);
-        return;
-    }
-    if (len < 4) {
-        pr2serr("Protocol-specific port information VPD page length too "
-                "short=%d\n", len);
-        return;
-    }
-    len -= 4;
-    bp = buff + 4;
-    for (k = 0; k < len; k += bump, bp += bump) {
-        rel_port = sg_get_unaligned_be16(bp);
-        printf("  Relative port=%d\n", rel_port);
-        proto = bp[2] & 0xf;
-        desc_len = sg_get_unaligned_be16(bp + 6);
-        bump = 8 + desc_len;
-        if ((k + bump) > len) {
-            pr2serr("Protocol-specific port VPD page, short descriptor "
-                    "length=%d, left=%d\n", bump, (len - k));
-            return;
-        }
-        if (0 == desc_len)
-            continue;
-        if (2 == do_hex) {
-            hex2stdout(bp + 8, desc_len, 1);
-            continue;
-        }
-        switch (proto) {
-        case TPROTO_SAS:    /* page added in spl3r02 */
-            printf("    power disable supported (pwr_d_s)=%d\n",
-                   !!(bp[3] & 0x1));       /* added spl3r03 */
-            pidp = bp + 8;
-            for (j = 0; j < desc_len; j += 4, pidp += 4)
-                printf("      phy id=%d, SSP persistent capable=%d\n",
-                       pidp[1], (0x1 & pidp[2]));
-            break;
-        default:
-            pr2serr("Unexpected proto=%d\n", proto);
-            hex2stderr(bp, bump, 1);
-            break;
-        }
-    }
-}
-
 /* VPD_BLOCK_LIMITS sbc */
 /* VPD_SA_DEV_CAP ssc */
 /* VPD_OSD_INFO osd */
@@ -2343,60 +1841,73 @@
         }
         break;
     case VPD_3PARTY_COPY:   /* 0x8f */
-        np = "Third party copy VPD page:";
+        np = "Third party copy VPD page";       /* ["tpc"] */
         if (allow_name)
-            printf("%s%s\n", pre, np);
+            sgj_pr_hr(jsp, "%s%s:\n", pre, np);
         res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
         if (0 == res) {
             if (! allow_name && allow_if_found)
-                printf("%s%s\n", pre, np);
+                sgj_pr_hr(jsp, "%s%s\n", pre, np);
             if (op->do_raw)
                 dStrRaw(rp, len);
-            else if (1 == op->do_hex)
-                hex2stdout(rp, len, 0);
             else {
                 if (vb || long_notquiet)
-                    printf("   [PQual=%d  Peripheral device type: %s]\n",
-                           pqual, pdt_str);
-                decode_3party_copy_vpd(rp, len, op->do_hex, pdt, vb);
+                    sgj_pr_hr(jsp, "   [PQual=%d  Peripheral device type: "
+                              "%s]\n", pqual, pdt_str);
+                if (as_json) {
+                    jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+                    jap = sgj_named_subarray_r(jsp, jo2p,
+                                      "third_party_copy_descriptors");
+                }
+                decode_3party_copy_vpd(rp, len, op, jap);
             }
             return 0;
         }
         break;
-    case VPD_PROTO_LU:          /* 0x90 */
-        np = "Protocol-specific logical unit information:";
+    case VPD_PROTO_LU:          /* 0x90 ["pslu"] */
+        np = "Protocol-specific logical unit information VPD page";
         if (allow_name)
-            printf("%s%s\n", pre, np);
+            sgj_pr_hr(jsp, "%s%s:\n", pre, np);
         res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
         if (0 == res) {
             if (! allow_name && allow_if_found)
-                printf("%s%s\n", pre, np);
+                sgj_pr_hr(jsp, "%s%s:\n", pre, np);
             if (op->do_raw)
                 dStrRaw(rp, len);
             else {
                 if (vb || long_notquiet)
-                    printf("   [PQual=%d  Peripheral device type: %s]\n",
-                           pqual, pdt_str);
-                decode_proto_lu_vpd(rp, len, op->do_hex);
+                    sgj_pr_hr(jsp, "   [PQual=%d  Peripheral device type: "
+                              "%s]\n", pqual, pdt_str);
+                if (as_json) {
+                    jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+                    jap = sgj_named_subarray_r(jsp, jo2p,
+                              "logical_unit_information_descriptor_list");
+                }
+                decode_proto_lu_vpd(rp, len, op, jap);
             }
             return 0;
         }
         break;
-    case VPD_PROTO_PORT:        /* 0x91 */
-        np = "Protocol-specific port information:";
+    case VPD_PROTO_PORT:        /* 0x91  ["pspo"] */
+        np = "Protocol-specific port VPD page";
         if (allow_name)
-            printf("%s%s\n", pre, np);
+            sgj_pr_hr(jsp, "%s%s\n", pre, np);
         res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
         if (0 == res) {
             if (! allow_name && allow_if_found)
-                printf("%s%s\n", pre, np);
+                sgj_pr_hr(jsp, "%s%s:\n", pre, np);
             if (op->do_raw)
                 dStrRaw(rp, len);
             else {
                 if (vb || long_notquiet)
-                    printf("   [PQual=%d  Peripheral device type: %s]\n",
-                           pqual, pdt_str);
-                decode_proto_port_vpd(rp, len, op->do_hex);
+                    sgj_pr_hr(jsp, "   [PQual=%d  Peripheral device type: "
+                              "%s]\n", pqual, pdt_str);
+                if (as_json) {
+                    jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+                    jap = sgj_named_subarray_r(jsp, jo2p,
+                              "port_information_descriptor_list");
+                }
+                decode_proto_port_vpd(rp, len, op, jsp);
             }
             return 0;
         }
diff --git a/src/sg_vpd_common.c b/src/sg_vpd_common.c
index 9497de3..5cc33f6 100644
--- a/src/sg_vpd_common.c
+++ b/src/sg_vpd_common.c
@@ -43,6 +43,8 @@
 const char * product_id_js = "product_identification";
 const char * product_rev_lev_hr = "Product_revision_level";
 const char * product_rev_lev_js = "product_revision_level";
+static const char * const y_s = "yes";
+static const char * const n_s = "no";
 static const char * const nl_s = "no limit";
 static const char * const nlr_s = "no limit reported";
 static const char * const nr_s = "not reported";
@@ -1865,7 +1867,7 @@
                      sg_get_unaligned_be64(bp + 16), true);
         sgj_hr_js_vi_nex(jsp, jo2p, 4, "FMTPINFO", SGJ_SEP_COLON_1_SPACE,
                          (bp[38] >> 6) & 0x3, false,
-                         "ForMaT Protecion INFOrmation (see Format Unit)");
+                         "ForMaT Protection INFOrmation (see Format Unit)");
         sgj_hr_js_vi(jsp, jo2p, 4, "Protection field usage",
                      SGJ_SEP_COLON_1_SPACE, bp[38] & 0x7, false);
         sgj_hr_js_vi(jsp, jo2p, 4, "Protection interval exponent",
@@ -1997,3 +1999,684 @@
         sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
     }
 }
+
+/* This is xcopy(LID4) related: "ROD" == Representation Of Data
+ * Used by VPD_3PARTY_COPY   0x8f ["tpc"] */
+static void
+decode_rod_descriptor(const uint8_t * buff, int len, struct opts_t * op,
+                      sgj_opaque_p jap)
+{
+    uint8_t pdt;
+    uint32_t u;
+    int k, bump;
+    uint64_t ull;
+    const uint8_t * bp = buff;
+    sgj_state * jsp = &op->json_st;
+    sgj_opaque_p jo2p;
+    static const char * ab_pdt = "abnormal use of 'pdt'";
+
+    for (k = 0; k < len; k += bump, bp += bump) {
+        jo2p = sgj_new_unattached_object_r(jsp);
+        bump = sg_get_unaligned_be16(bp + 2) + 4;
+        pdt = 0x1f & bp[0];
+        u = (bp[0] >> 5) & 0x7;
+        sgj_js_nv_i(jsp, jo2p, "descriptor_format", u);
+        if (0 != u) {
+            sgj_pr_hr(jsp, "  Unhandled descriptor (format %u, device type "
+                      "%u)\n", u, pdt);
+            sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+            break;
+        }
+        switch (pdt) {
+        case 0:
+            /* Block ROD device type specific descriptor */
+            sgj_js_nv_ihexstr_nex(jsp, jo2p, "peripheral_device_type",
+                                  pdt, false, NULL, "Block ROD device "
+                                  "type specific descriptor", ab_pdt);
+            sgj_hr_js_vi_nex(jsp, jo2p, 4, "Optimal block ROD length "
+                             "granularity", SGJ_SEP_COLON_1_SPACE,
+                             sg_get_unaligned_be16(bp + 6), true, "unit: LB");
+            ull = sg_get_unaligned_be64(bp + 8);
+            sgj_hr_js_vi(jsp, jo2p, 4, "Maximum bytes in block ROD",
+                         SGJ_SEP_COLON_1_SPACE, ull, true);
+            ull = sg_get_unaligned_be64(bp + 16);
+            sgj_hr_js_vistr(jsp, jo2p, 4, "Optimal Bytes in block ROD "
+                            "transfer", SGJ_SEP_COLON_1_SPACE, ull, true,
+                            (SG_LIB_UNBOUNDED_64BIT == ull) ? nl_s : NULL);
+            ull = sg_get_unaligned_be64(bp + 24);
+            sgj_hr_js_vistr(jsp, jo2p, 4, "Optimal Bytes to token per "
+                            "segment", SGJ_SEP_COLON_1_SPACE, ull, true,
+                            (SG_LIB_UNBOUNDED_64BIT == ull) ? nl_s : NULL);
+            ull = sg_get_unaligned_be64(bp + 32);
+            sgj_hr_js_vistr(jsp, jo2p, 4, "Optimal Bytes from token per "
+                            "segment", SGJ_SEP_COLON_1_SPACE, ull, true,
+                            (SG_LIB_UNBOUNDED_64BIT == ull) ? nl_s : NULL);
+            break;
+        case 1:
+            /* Stream ROD device type specific descriptor */
+            sgj_js_nv_ihexstr_nex(jsp, jo2p, "peripheral_device_type",
+                                  pdt, false, NULL, "Stream ROD device "
+                                  "type specific descriptor", ab_pdt);
+            ull = sg_get_unaligned_be64(bp + 8);
+            sgj_hr_js_vi(jsp, jo2p, 4, "Maximum bytes in stream ROD",
+                         SGJ_SEP_COLON_1_SPACE, ull, true);
+            ull = sg_get_unaligned_be64(bp + 16);
+            printf("  Optimal Bytes in stream ROD transfer: ");
+            if (SG_LIB_UNBOUNDED_64BIT == ull)
+                printf("-1 [no limit]\n");
+            else
+                printf("%" PRIu64 "\n", ull);
+            break;
+        case 3:
+            /* Copy manager ROD device type specific descriptor */
+            sgj_js_nv_ihexstr_nex(jsp, jo2p, "peripheral_device_type",
+                                  pdt, false, NULL, "Copy manager ROD "
+                                  "device type specific descriptor",
+                                  ab_pdt);
+            printf("  Maximum Bytes in processor ROD: %" PRIu64 "\n",
+                   sg_get_unaligned_be64(bp + 8));
+            ull = sg_get_unaligned_be64(bp + 16);
+            printf("  Optimal Bytes in processor ROD transfer: ");
+            if (SG_LIB_UNBOUNDED_64BIT == ull)
+                printf("-1 [no limit]\n");
+            else
+                printf("%" PRIu64 "\n", ull);
+            break;
+        default:
+            sgj_js_nv_ihexstr(jsp, jo2p, "peripheral_device_type",
+                              pdt, false, "unknown");
+            break;
+        }
+        sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+    }
+}
+
+struct tpc_desc_type {
+    uint8_t code;
+    const char * name;
+};
+
+static struct tpc_desc_type tpc_desc_arr[] = {
+    {0x0, "block -> stream"},
+    {0x1, "stream -> block"},
+    {0x2, "block -> block"},
+    {0x3, "stream -> stream"},
+    {0x4, "inline -> stream"},
+    {0x5, "embedded -> stream"},
+    {0x6, "stream -> discard"},
+    {0x7, "verify CSCD"},
+    {0x8, "block<o> -> stream"},
+    {0x9, "stream -> block<o>"},
+    {0xa, "block<o> -> block<o>"},
+    {0xb, "block -> stream & application_client"},
+    {0xc, "stream -> block & application_client"},
+    {0xd, "block -> block & application_client"},
+    {0xe, "stream -> stream&application_client"},
+    {0xf, "stream -> discard&application_client"},
+    {0x10, "filemark -> tape"},
+    {0x11, "space -> tape"},            /* obsolete: spc5r02 */
+    {0x12, "locate -> tape"},           /* obsolete: spc5r02 */
+    {0x13, "<i>tape -> <i>tape"},
+    {0x14, "register persistent reservation key"},
+    {0x15, "third party persistent reservation source I_T nexus"},
+    {0x16, "<i>block -> <i>block"},
+    {0x17, "positioning -> tape"},      /* this and next added spc5r02 */
+    {0x18, "<loi>tape -> <loi>tape"},   /* loi: logical object identifier */
+    {0xbe, "ROD <- block range(n)"},
+    {0xbf, "ROD <- block range(1)"},
+    {0xe0, "CSCD: FC N_Port_Name"},
+    {0xe1, "CSCD: FC N_Port_ID"},
+    {0xe2, "CSCD: FC N_Port_ID with N_Port_Name, checking"},
+    {0xe3, "CSCD: Parallel interface: I_T"},
+    {0xe4, "CSCD: Identification Descriptor"},
+    {0xe5, "CSCD: IPv4"},
+    {0xe6, "CSCD: Alias"},
+    {0xe7, "CSCD: RDMA"},
+    {0xe8, "CSCD: IEEE 1394 EUI-64"},
+    {0xe9, "CSCD: SAS SSP"},
+    {0xea, "CSCD: IPv6"},
+    {0xeb, "CSCD: IP copy service"},
+    {0xfe, "CSCD: ROD"},
+    {0xff, "CSCD: extension"},
+    {0x0, NULL},
+};
+
+static const char *
+get_tpc_desc_name(uint8_t code)
+{
+    const struct tpc_desc_type * dtp;
+
+    for (dtp = tpc_desc_arr; dtp->name; ++dtp) {
+        if (code == dtp->code)
+            return dtp->name;
+    }
+    return "";
+}
+
+struct tpc_rod_type {
+    uint32_t type;
+    const char * name;
+};
+
+static struct tpc_rod_type tpc_rod_arr[] = {
+    {0x0, "copy manager internal"},
+    {0x10000, "access upon reference"},
+    {0x800000, "point in time copy - default"},
+    {0x800001, "point in time copy - change vulnerable"},
+    {0x800002, "point in time copy - persistent"},
+    {0x80ffff, "point in time copy - any"},
+    {0xffff0001, "block device zero"},
+    {0x0, NULL},
+};
+
+static const char *
+get_tpc_rod_name(uint32_t rod_type)
+{
+    const struct tpc_rod_type * rtp;
+
+    for (rtp = tpc_rod_arr; rtp->name; ++rtp) {
+        if (rod_type == rtp->type)
+            return rtp->name;
+    }
+    return "";
+}
+
+struct cscd_desc_id_t {
+    uint16_t id;
+    const char * name;
+};
+
+static struct cscd_desc_id_t cscd_desc_id_arr[] = {
+    /* only values higher than 0x7ff are listed */
+    {0xc000, "copy src or dst null LU, pdt=0"},
+    {0xc001, "copy src or dst null LU, pdt=1"},
+    {0xf800, "copy src or dst in ROD token"},
+    {0xffff, "copy src or dst is copy manager LU"},
+    {0x0, NULL},
+};
+
+static const char *
+get_cscd_desc_id_name(uint16_t cscd_desc_id)
+{
+    const struct cscd_desc_id_t * cdip;
+
+    for (cdip = cscd_desc_id_arr; cdip->name; ++cdip) {
+        if (cscd_desc_id == cdip->id)
+            return cdip->name;
+    }
+    return "";
+}
+
+static const char *
+get_tpc_desc_type_s(uint32_t desc_type)
+{
+    switch(desc_type) {
+    case 0:
+        return "Block Device ROD Limits";
+    case 1:
+        return "Supported Commands";
+    case 4:
+        return "Parameter Data";
+    case 8:
+        return "Supported Descriptors";
+    case 0xc:
+        return "Supported CSCD Descriptor IDs";
+    case 0xd:
+        return "Copy Group Identifier";
+    case 0x106:
+        return "ROD Token Features";
+    case 0x108:
+        return "Supported ROD Token and ROD Types";
+    case 0x8001:
+        return "General Copy Operations";
+    case 0x9101:
+        return "Stream Copy Operations";
+    case 0xC001:
+        return "Held Data";
+    default:
+        if ((desc_type >= 0xE000) && (desc_type <= 0xEFFF))
+            return "Restricted";
+        else
+            return "Reserved";
+    }
+}
+
+/* VPD_3PARTY_COPY   3PC, third party copy  0x8f ["tpc"] */
+void
+decode_3party_copy_vpd(uint8_t * buff, int len, struct opts_t * op,
+                       sgj_opaque_p jap)
+{
+    int j, k, m, bump, desc_type, desc_len, sa_len, pdt;
+    uint32_t u, v;
+    uint64_t ull;
+    const uint8_t * bp;
+    const char * cp;
+    const char * dtp;
+    sgj_state * jsp = &op->json_st;
+    sgj_opaque_p jo2p = NULL;
+    sgj_opaque_p ja2p = NULL;
+    sgj_opaque_p jo3p = NULL;
+    char b[144];
+    static const int blen = sizeof(b);
+
+    if (len < 4) {
+        pr2serr("VPD page length too short=%d\n", len);
+        return;
+    }
+    if (3 == op->do_hex) {
+        hex2stdout(buff, len, -1);
+        return;
+    }
+    pdt = buff[0] & PDT_MASK;
+    len -= 4;
+    bp = buff + 4;
+    for (k = 0; k < len; k += bump, bp += bump) {
+        jo2p = sgj_new_unattached_object_r(jsp);
+        desc_type = sg_get_unaligned_be16(bp);
+        desc_len = sg_get_unaligned_be16(bp + 2);
+        if (op->verbose)
+            sgj_pr_hr(jsp, "Descriptor type=%d [0x%x] , len %d\n", desc_type,
+                      desc_type, desc_len);
+        bump = 4 + desc_len;
+        if ((k + bump) > len) {
+            pr2serr("VPD page, short descriptor length=%d, left=%d\n", bump,
+                    (len - k));
+            break;
+        }
+        if (0 == desc_len)
+            goto skip;          /* continue plus attach jo2p */
+        if (2 == op->do_hex)
+            hex2stdout(bp + 4, desc_len, 1);
+        else if (op->do_hex > 2)
+            hex2stdout(bp, bump, 1);
+        else {
+            int csll;
+
+            dtp = get_tpc_desc_type_s(desc_type);
+            sgj_js_nv_ihexstr(jsp, jo2p, "third_party_copy_descriptor_type",
+                              desc_type, NULL, dtp);
+            sgj_js_nv_ihex(jsp, jo2p, "third_party_copy_descriptor_length",
+                           desc_len);
+
+            switch (desc_type) {
+            case 0x0000:    /* Required if POPULATE TOKEN (or friend) used */
+                sgj_pr_hr(jsp, " %s:\n", dtp);
+                u = sg_get_unaligned_be16(bp + 10);
+                sgj_hr_js_vistr(jsp, jo2p, 2, "Maximum range descriptors",
+                                SGJ_SEP_COLON_1_SPACE, u, true,
+                                (0 == u) ? nr_s : NULL);
+                u = sg_get_unaligned_be32(bp + 12);
+                if (0 == u)
+                    cp = nr_s;
+                else if (SG_LIB_UNBOUNDED_32BIT == u)
+                    cp = "No maximum given";
+                else
+                    cp = NULL;
+                sgj_hr_js_vistr_nex(jsp, jo2p, 2, "Maximum inactivity "
+                                    "timeout", SGJ_SEP_COLON_1_SPACE, u, true,
+                                    cp, "unit: second");
+                u = sg_get_unaligned_be32(bp + 16);
+                sgj_hr_js_vistr_nex(jsp, jo2p, 2, "Default inactivity "
+                                    "timeout", SGJ_SEP_COLON_1_SPACE, u, true,
+                                    (0 == u) ? nr_s : NULL, "unit: second");
+                ull = sg_get_unaligned_be64(bp + 20);
+                sgj_hr_js_vistr_nex(jsp, jo2p, 2, "Maximum token transfer "
+                                    "size", SGJ_SEP_COLON_1_SPACE, ull, true,
+                                    (0 == ull) ? nr_s : NULL, "unit: LB");
+                ull = sg_get_unaligned_be64(bp + 28);
+                sgj_hr_js_vistr_nex(jsp, jo2p, 2, "Optimal transfer count",
+                                    SGJ_SEP_COLON_1_SPACE, ull, true,
+                                    (0 == ull) ? nr_s : NULL, "unit: LB");
+                break;
+            case 0x0001:    /* Mandatory (SPC-4) */
+                sgj_pr_hr(jsp, " %s:\n", "Commands supported list");
+                ja2p = sgj_named_subarray_r(jsp, jo2p,
+                                            "commands_supported_list");
+                j = 0;
+                csll = bp[4];
+                if (csll >= desc_len) {
+                    pr2serr("Command supported list length (%d) >= "
+                            "descriptor length (%d), wrong so trim\n",
+                            csll, desc_len);
+                    csll = desc_len - 1;
+                }
+                while (j < csll) {
+                    uint8_t opc, sa;
+                    static const char * soc = "supported_operation_code";
+                    static const char * ssa = "supported_service_action";
+
+                    jo3p = NULL;
+                    opc = bp[5 + j];
+                    sa_len = bp[6 + j];
+                    for (m = 0; (m < sa_len) && ((j + m) < csll); ++m) {
+                        jo3p = sgj_new_unattached_object_r(jsp);
+                        sa = bp[7 + j + m];
+                        sg_get_opcode_sa_name(opc, sa, pdt, blen, b);
+                        sgj_pr_hr(jsp, "  %s\n", b);
+                        sgj_js_nv_s(jsp, jo3p, "name", b);
+                        sgj_js_nv_ihex(jsp, jo3p, soc, opc);
+                        sgj_js_nv_ihex(jsp, jo3p, ssa, sa);
+                        sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
+                    }
+                    if (0 == sa_len) {
+                        jo3p = sgj_new_unattached_object_r(jsp);
+                        sg_get_opcode_name(opc, pdt, blen, b);
+                        sgj_pr_hr(jsp, "  %s\n", b);
+                        sgj_js_nv_s(jsp, jo3p, "name", b);
+                        sgj_js_nv_ihex(jsp, jo3p, soc, opc);
+                        sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
+                    } else if (m < sa_len)
+                        pr2serr("Supported service actions list length (%d) "
+                                "is too large\n", sa_len);
+                    j += m + 2;
+                }
+                break;
+            case 0x0004:
+                sgj_pr_hr(jsp, " %s:\n", dtp);
+                sgj_hr_js_vi(jsp, jo2p, 2, "Maximum CSCD descriptor count",
+                             SGJ_SEP_COLON_1_SPACE,
+                             sg_get_unaligned_be16(bp + 8), true);
+                sgj_hr_js_vi(jsp, jo2p, 2, "Maximum segment descriptor count",
+                             SGJ_SEP_COLON_1_SPACE,
+                             sg_get_unaligned_be16(bp + 10), true);
+                sgj_hr_js_vi(jsp, jo2p, 2, "Maximum descriptor list length",
+                             SGJ_SEP_COLON_1_SPACE,
+                             sg_get_unaligned_be32(bp + 12), true);
+                sgj_hr_js_vi(jsp, jo2p, 2, "Maximum inline data length",
+                             SGJ_SEP_COLON_1_SPACE,
+                             sg_get_unaligned_be32(bp + 17), true);
+                break;
+            case 0x0008:
+                sgj_pr_hr(jsp, " Supported descriptors:\n");
+                ja2p = sgj_named_subarray_r(jsp, jo2p,
+                                            "supported_descriptor_list");
+                for (j = 0; j < bp[4]; j++) {
+                    bool found_name;
+
+                    jo3p = sgj_new_unattached_object_r(jsp);
+                    u = bp[5 + j];
+                    cp = get_tpc_desc_name(u);
+                    found_name = (strlen(cp) > 0);
+                    if (found_name)
+                        sgj_pr_hr(jsp, "  %s [0x%x]\n", cp, u);
+                    else
+                        sgj_pr_hr(jsp, "  0x%x\n", u);
+                    sgj_js_nv_s(jsp, jo3p, "name", found_name ? cp : nr_s);
+                    sgj_js_nv_ihex(jsp, jo3p, "code", u);
+                    sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
+                }
+                break;
+            case 0x000C:
+                sgj_pr_hr(jsp, " Supported CSCD IDs (above 0x7ff):\n");
+                ja2p = sgj_named_subarray_r(jsp, jo2p, "supported_cscd_"
+                                            "descriptor_id_list");
+                v = sg_get_unaligned_be16(bp + 4);
+                for (j = 0; j < (int)v; j += 2) {
+                    bool found_name;
+
+                    jo3p = sgj_new_unattached_object_r(jsp);
+                    u = sg_get_unaligned_be16(bp + 6 + j);
+                    cp = get_cscd_desc_id_name(u);
+                    found_name = (strlen(cp) > 0);
+                    if (found_name)
+                        sgj_pr_hr(jsp, "  %s [0x%04x]\n", cp, u);
+                    else
+                        sgj_pr_hr(jsp, "  0x%04x\n", u);
+                    sgj_js_nv_s(jsp, jo3p, "name", found_name ? cp : nr_s);
+                    sgj_js_nv_ihex(jsp, jo3p, "id", u);
+                    sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
+                }
+                break;
+            case 0x000D:
+                sgj_pr_hr(jsp, " Copy group identifier:\n");
+                u = bp[4];
+                sg_t10_uuid_desig2str(bp + 5, u, 1 /* c_set */, false,
+                                      true, NULL, blen, b);
+                sgj_pr_hr(jsp, "  Locally assigned UUID: %s", b);
+                sgj_js_nv_s(jsp, jo2p, "locally_assigned_uuid", b);
+                break;
+            case 0x0106:
+                sgj_pr_hr(jsp, " ROD token features:\n");
+                sgj_hr_js_vi(jsp, jo2p, 2, "Remote tokens",
+                             SGJ_SEP_COLON_1_SPACE, bp[4] & 0x0f, true);
+                u = sg_get_unaligned_be32(bp + 16);
+                sgj_pr_hr(jsp, "  Minimum token lifetime: %u seconds\n", u);
+                sgj_js_nv_ihex_nex(jsp, jo2p, "minimum_token_lifetime", u,
+                                   true, "unit: second");
+                u = sg_get_unaligned_be32(bp + 20);
+                sgj_pr_hr(jsp, "  Maximum token lifetime: %u seconds\n", u);
+                sgj_js_nv_ihex_nex(jsp, jo2p, "maximum_token_lifetime", u,
+                                   true, "unit: second");
+                u = sg_get_unaligned_be32(bp + 24);
+                sgj_hr_js_vi_nex(jsp, jo2p, 2, "Maximum token inactivity "
+                                 "timeout", SGJ_SEP_COLON_1_SPACE, u,
+                                 true, "unit: second");
+                u = sg_get_unaligned_be16(bp + 46);
+                ja2p = sgj_named_subarray_r(jsp, jo2p,
+                    "rod_device_type_specific_features_descriptor_list");
+                decode_rod_descriptor(bp + 48, u, op, ja2p);
+                break;
+            case 0x0108:
+                sgj_pr_hr(jsp, " Supported ROD token and ROD types:\n");
+                ja2p = sgj_named_subarray_r(jsp, jo2p, "rod_type_"
+                                            "descriptor_list");
+                for (j = 0; j < sg_get_unaligned_be16(bp + 6); j+= 64) {
+                    bool found_name;
+
+                    jo3p = sgj_new_unattached_object_r(jsp);
+                    u = sg_get_unaligned_be32(bp + 8 + j);
+                    cp = get_tpc_rod_name(u);
+                    found_name = (strlen(cp) > 0);
+                    if (found_name > 0)
+                        sgj_pr_hr(jsp, "  ROD type: %s [0x%x]\n", cp, u);
+                    else
+                        sgj_pr_hr(jsp, "  ROD type: 0x%x\n", u);
+                    sgj_js_nv_ihexstr(jsp, jo3p, "rod_type", u, NULL,
+                                      found_name ? cp : NULL);
+                    u = bp[8 + j + 4];
+                    sgj_pr_hr(jsp, "    ECPY_INT: %s\n",
+                              (u & 0x80) ? y_s : n_s);
+                    sgj_js_nv_ihex_nex(jsp, jo3p, "ecpy_int", !!(0x80 & u),
+                                       false, "Extended CoPY INTernal rods");
+                    sgj_pr_hr(jsp, "    Token in: %s\n",
+                              (u & 0x2) ? y_s : n_s);
+                    sgj_js_nv_i(jsp, jo3p, "token_in", !!(0x2 & u));
+                    sgj_pr_hr(jsp, "    Token out: %s\n",
+                              (u & 0x1) ? y_s : n_s);
+                    sgj_js_nv_i(jsp, jo3p, "token_out", !!(0x2 & u));
+                    u = sg_get_unaligned_be16(bp + 8 + j + 6);
+                    sgj_hr_js_vi(jsp, jo3p, 4, "Preference indicator",
+                                 SGJ_SEP_COLON_1_SPACE, u, true);
+                    sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
+                }
+                break;
+            case 0x8001:    /* Mandatory (SPC-4) */
+                sgj_pr_hr(jsp, " General copy operations:\n");
+                u = sg_get_unaligned_be32(bp + 4);
+                sgj_hr_js_vi(jsp, jo2p, 2, "Total concurrent copies",
+                             SGJ_SEP_COLON_1_SPACE, u, true);
+                u = sg_get_unaligned_be32(bp + 8);
+                sgj_hr_js_vi(jsp, jo2p, 2, "Maximum identified concurrent "
+                             "copies", SGJ_SEP_COLON_1_SPACE, u, true);
+                u = sg_get_unaligned_be32(bp + 12);
+                sgj_hr_js_vi_nex(jsp, jo2p, 2, "Maximum segment length",
+                                 SGJ_SEP_COLON_1_SPACE, u, true,
+                                 "unit: byte");
+                u = bp[16];     /* field is power of 2 */
+                sgj_hr_js_vi_nex(jsp, jo2p, 2, "Data segment granularity",
+                                 SGJ_SEP_COLON_1_SPACE, u, true,
+                                 "unit: 2^val LB");
+                u = bp[17];     /* field is power of 2 */
+                sgj_hr_js_vi_nex(jsp, jo2p, 2, "Inline data granularity",
+                                 SGJ_SEP_COLON_1_SPACE, u, true,
+                                 "unit: 2^val LB");
+                break;
+            case 0x9101:
+                sgj_pr_hr(jsp, " Stream copy operations:\n");
+                u = sg_get_unaligned_be32(bp + 4);
+                sgj_hr_js_vi_nex(jsp, jo2p, 2, "Maximum stream device "
+                                 "transfer size", SGJ_SEP_COLON_1_SPACE, u,
+                                 true, "unit: byte");
+                break;
+            case 0xC001:
+                sgj_pr_hr(jsp, " Held data:\n");
+                u = sg_get_unaligned_be32(bp + 4);
+                sgj_hr_js_vi_nex(jsp, jo2p, 2, "Held data limit",
+                                 SGJ_SEP_COLON_1_SPACE, u, true,
+                                 "unit: byte; (lower limit: minimum)");
+                sgj_hr_js_vi_nex(jsp, jo2p, 2, "Held data granularity",
+                                 SGJ_SEP_COLON_1_SPACE, bp[8], true,
+                                 "unit: 2^val byte");
+                break;
+            default:
+                pr2serr("Unexpected type=%d\n", desc_type);
+                hex2stderr(bp, bump, 1);
+                break;
+            }
+        }
+skip:
+        sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+        jo2p = NULL;
+    }
+    if (jo2p)
+        sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+}
+
+/* VPD_PROTO_LU  0x90 ["pslu"] */
+void
+decode_proto_lu_vpd(uint8_t * buff, int len, struct opts_t * op,
+                    sgj_opaque_p jap)
+{
+    int k, bump, rel_port, desc_len, proto;
+    uint8_t * bp;
+    sgj_state * jsp = &op->json_st;
+    sgj_opaque_p jo2p = NULL;
+    char b[128];
+    static const int blen = sizeof(b);
+
+    if ((1 == op->do_hex) || (op->do_hex > 2)) {
+        hex2stdout(buff, len, (1 == op->do_hex) ? 1 : -1);
+        return;
+    }
+    if (len < 4) {
+        pr2serr("VPD page length too short=%d\n", len);
+        return;
+    }
+    len -= 4;
+    bp = buff + 4;
+    for (k = 0; k < len; k += bump, bp += bump) {
+        jo2p = sgj_new_unattached_object_r(jsp);
+        rel_port = sg_get_unaligned_be16(bp);
+        sgj_hr_js_vi(jsp, jo2p, 2, "Relative port",
+                     SGJ_SEP_COLON_1_SPACE, rel_port, true);
+        proto = bp[2] & 0xf;
+        sg_get_trans_proto_str(proto, blen, b);
+        sgj_hr_js_vistr(jsp, jo2p, 4, "Protocol identifier",
+                        SGJ_SEP_COLON_1_SPACE, proto, false, b);
+        desc_len = sg_get_unaligned_be16(bp + 6);
+        bump = 8 + desc_len;
+        if ((k + bump) > len) {
+            pr2serr("Protocol-specific logical unit information VPD page, "
+                    "short descriptor length=%d, left=%d\n", bump, (len - k));
+            sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+            return;
+        }
+        if (0 == desc_len)
+            goto again;;
+        if (2 == op->do_hex) {
+            hex2stdout(bp + 8, desc_len, 1);
+            goto again;;
+        }
+        switch (proto) {
+        case TPROTO_SAS:
+            sgj_hr_js_vi(jsp, jo2p, 2, "TLR control supported",
+                         SGJ_SEP_COLON_1_SPACE, !!(bp[8] & 0x1), false);
+            break;
+        default:
+            pr2serr("Unexpected proto=%d\n", proto);
+            hex2stderr(bp, bump, 1);
+            break;
+        }
+again:
+        sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+    }
+}
+
+/* VPD_PROTO_PORT  0x91 ["pspo"] */
+void
+decode_proto_port_vpd(uint8_t * buff, int len, struct opts_t * op,
+                      sgj_opaque_p jap)
+{
+    bool pds, ssp_pers;
+    int k, j, bump, rel_port, desc_len, proto, phy;
+    uint8_t * bp;
+    uint8_t * pidp;
+    sgj_state * jsp = &op->json_st;
+    sgj_opaque_p jo2p = NULL;
+    sgj_opaque_p ja2p = NULL;
+    sgj_opaque_p jo3p = NULL;
+    char b[128];
+    static const int blen = sizeof(b);
+
+    if ((1 == op->do_hex) || (op->do_hex > 2)) {
+        hex2stdout(buff, len, (1 == op->do_hex) ? 1 : -1);
+        return;
+    }
+    if (len < 4) {
+        pr2serr("VPD page length too short=%d\n", len);
+        return;
+    }
+    len -= 4;
+    bp = buff + 4;
+    for (k = 0; k < len; k += bump, bp += bump) {
+        jo2p = sgj_new_unattached_object_r(jsp);
+        rel_port = sg_get_unaligned_be16(bp);
+        sgj_hr_js_vi(jsp, jo2p, 2, "Relative port",
+                     SGJ_SEP_COLON_1_SPACE, rel_port, true);
+        proto = bp[2] & 0xf;
+        sg_get_trans_proto_str(proto, blen, b);
+        sgj_hr_js_vistr(jsp, jo2p, 4, "Protocol identifier",
+                        SGJ_SEP_COLON_1_SPACE, proto, false, b);
+        desc_len = sg_get_unaligned_be16(bp + 6);
+        bump = 8 + desc_len;
+        if ((k + bump) > len) {
+            pr2serr("VPD page, short descriptor length=%d, left=%d\n",
+                    bump, (len - k));
+            sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+            return;
+        }
+        if (0 == desc_len)
+            goto again;
+        if (2 == op->do_hex) {
+            hex2stdout(bp + 8, desc_len, 1);
+            goto again;
+        }
+        switch (proto) {
+        case TPROTO_SAS:    /* page added in spl3r02 */
+            pds = !!(bp[3] & 0x1);
+            sgj_pr_hr(jsp, "    power disable supported (pwr_d_s)=%d\n", pds);
+            sgj_js_nv_ihex_nex(jsp, jo2p, "pwr_d_s", pds, false,
+                       "PoWeR Disable Supported");
+            ja2p = sgj_named_subarray_r(jsp, jo2p,
+                                    "sas_phy_information_descriptor_list");
+            pidp = bp + 8;
+            for (j = 0; j < desc_len; j += 4, pidp += 4) {
+                jo3p = sgj_new_unattached_object_r(jsp);
+                phy = pidp[1];
+                ssp_pers = !!(0x1 & pidp[2]);
+                sgj_pr_hr(jsp, "      phy id=%d, SSP persistent capable=%d\n",
+                          phy, ssp_pers);
+                sgj_js_nv_ihex(jsp, jo3p, "phy_identifier", phy);
+                sgj_js_nv_i(jsp, jo3p, "ssp_persistent_capable", ssp_pers);
+                sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
+            }
+            break;
+        default:
+            pr2serr("Unexpected proto=%d\n", proto);
+            hex2stderr(bp, bump, 1);
+            break;
+        }
+again:
+        sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
+    }
+}
diff --git a/src/sg_vpd_common.h b/src/sg_vpd_common.h
index 7323352..bc2bbfa 100644
--- a/src/sg_vpd_common.h
+++ b/src/sg_vpd_common.h
@@ -42,7 +42,7 @@
 #define VPD_DEVICE_CONSTITUENTS 0x8b
 #define VPD_CFA_PROFILE_INFO 0x8c
 #define VPD_POWER_CONSUMPTION  0x8d
-#define VPD_3PARTY_COPY 0x8f            /* 3PC, XCOPY, SPC-4, SBC-3 */
+#define VPD_3PARTY_COPY 0x8f            /* 3PC, XCOPY, SPC-5, SBC-4 */
 #define VPD_PROTO_LU 0x90
 #define VPD_PROTO_PORT 0x91
 #define VPD_SCSI_FEATURE_SETS 0x92      /* spc5r11 */
@@ -174,6 +174,14 @@
                                sgj_opaque_p jap);
 void decode_con_pos_range_vpd(uint8_t * buff, int len, struct opts_t * op,
                               sgj_opaque_p jap);
+void decode_3party_copy_vpd(uint8_t * buff, int len, struct opts_t * op,
+                            sgj_opaque_p jap);
+void
+decode_proto_lu_vpd(uint8_t * buff, int len, struct opts_t * op,
+                    sgj_opaque_p jap);
+void
+decode_proto_port_vpd(uint8_t * buff, int len, struct opts_t * op,
+                      sgj_opaque_p jap);
 const char * pqual_str(int pqual);
 
 void svpd_enumerate_vendor(int vend_prod_num);