ci: Add more checks to ci_verify_version.sh; refactor

In addition to png.h, configure.ac and CMakeLists.txt, the script
ci_verify_version.sh is now able to verify libpng-config-head.in also.

For the benefit of readability, the old script ci_shellify.sh has been
split into smaller, independent scriptlets: libexec/ci_shellify_*.sh.

The linting script ci_lint.sh has been updated as needed.
diff --git a/ci/ci_lint.sh b/ci/ci_lint.sh
index 163d955..674e55f 100755
--- a/ci/ci_lint.sh
+++ b/ci/ci_lint.sh
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 set -o errexit -o pipefail -o posix
 
-# Copyright (c) 2019-2024 Cosmin Truta.
+# Copyright (c) 2019-2025 Cosmin Truta.
 #
 # Use, modification and distribution are subject to the MIT License.
 # Please see the accompanying file LICENSE_MIT.txt
@@ -61,7 +61,7 @@
     }
     ci_info "## LINTING: CI scripts ##"
     ci_spawn "$CI_SHELLCHECK" --version
-    find ./ci -maxdepth 1 -name "*.sh" | {
+    find ./ci -name "ci_*.sh" -not -name "ci_env.*.sh" | {
         local my_file
         while IFS="" read -r my_file
         do
diff --git a/ci/ci_shellify.sh b/ci/ci_shellify.sh
deleted file mode 100755
index e6693af..0000000
--- a/ci/ci_shellify.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/usr/bin/env bash
-set -o errexit -o pipefail -o posix
-
-# Copyright (c) 2019-2024 Cosmin Truta.
-#
-# Use, modification and distribution are subject to the MIT License.
-# Please see the accompanying file LICENSE_MIT.txt
-#
-# SPDX-License-Identifier: MIT
-
-# shellcheck source=ci/lib/ci.lib.sh
-source "$(dirname "$0")/lib/ci.lib.sh"
-cd "$CI_TOPLEVEL_DIR"
-
-function ci_shellify_c {
-    # Convert C preprocessor text, specifically originating
-    # from png.h, to shell scripting text.
-    # Select only the easy-to-parse definitions of PNG_LIBPNG_*.
-    sed -n -e '/^\# *define * PNG_LIBPNG_[^ ]* * ["0-9A-Za-z_]/ p' |
-        sed -e 's/^\# *define * PNG\([^ ]*\) * \([^ ]*\)/PNG\1=\2/' \
-            -e 's/=PNG\([0-9A-Za-z_]*\)/=\${PNG\1}/' \
-            -e 's/^\([^ ]*=[^ ]*\).*$/export \1;/'
-}
-
-function ci_shellify_autoconf {
-    # Convert autoconf (M4) text, specifically originating
-    # from configure.ac, to shell scripting text.
-    # Select only the easy-to-parse definitions of PNGLIB_*.
-    sed -n -e '/^ *PNGLIB_[^ ]*=[$"0-9A-Za-z_]/ p' |
-        sed -e 's/^ *PNG\([0-9A-Za-z_]*\)=\([^# ]*\).*$/PNG\1=\2/' \
-            -e 's/^\([^ ]*=[^ ]*\).*$/export \1;/'
-}
-
-function ci_shellify_cmake {
-    # Convert CMake lists text, specifically originating
-    # from CMakeLists.txt, to shell scripting text.
-    # Select only the easy-to-parse definitions of PNGLIB_*.
-    sed -n -e '/^ *set *(PNGLIB_[^ ]* * [$"0-9A-Za-z_].*)/ p' |
-        sed -e 's/^ *set *(PNG\([^ ]*\) * \([^() ]*\)).*$/PNG\1=\2/' \
-            -e 's/^\([^ ]*=[^ ]*\).*$/export \1;/'
-}
-
-function ci_shellify {
-    local arg filename
-    for arg in "$@"
-    do
-        test -f "$arg" || ci_err "no such file: '$arg'"
-        filename="$(basename -- "$arg")"
-        case "$filename" in
-        ( *.[ch] )
-            [[ $filename == png.h ]] || {
-                ci_err "unable to shellify: '$filename' (expecting: 'png.h')"
-            }
-            ci_shellify_c <"$arg" ;;
-        ( config* | *.ac )
-            [[ $filename == configure.ac ]] || {
-                ci_err "unable to shellify: '$filename' (expecting: 'configure.ac')"
-            }
-            ci_shellify_autoconf <"$arg" ;;
-        ( *CMake* | *cmake* | *.txt )
-            [[ $filename == [Cc][Mm]ake[Ll]ists.txt ]] || {
-                ci_err "unable to shellify: '$filename' (expecting: 'CMakeLists.txt')"
-            }
-            ci_shellify_cmake <"$arg" ;;
-        ( * )
-            ci_err "unable to shellify: '$arg'" ;;
-        esac
-    done
-}
-
-function usage {
-    echo "usage: $CI_SCRIPT_NAME [<options>] <files>..."
-    echo "options: -?|-h|--help"
-    echo "files: png.h|configure.ac|CMakeLists.txt"
-    exit "${@:-0}"
-}
-
-function main {
-    local opt
-    while getopts ":" opt
-    do
-        # This ain't a while-loop. It only pretends to be.
-        [[ $1 == -[?h]* || $1 == --help || $1 == --help=* ]] && usage 0
-        ci_err "unknown option: '$1'"
-    done
-    shift $((OPTIND - 1))
-    [[ $# -eq 0 ]] && usage 2
-    # And... go!
-    ci_shellify "$@"
-}
-
-main "$@"
diff --git a/ci/ci_verify_version.sh b/ci/ci_verify_version.sh
index 3203b20..5908724 100755
--- a/ci/ci_verify_version.sh
+++ b/ci/ci_verify_version.sh
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 set -o errexit -o pipefail -o posix
 
-# Copyright (c) 2019-2024 Cosmin Truta.
+# Copyright (c) 2019-2025 Cosmin Truta.
 #
 # Use, modification and distribution are subject to the MIT License.
 # Please see the accompanying file LICENSE_MIT.txt
@@ -12,33 +12,43 @@
 source "$(dirname "$0")/lib/ci.lib.sh"
 cd "$CI_TOPLEVEL_DIR"
 
-function ci_init_shellify {
-    [[ -f $CI_SCRIPT_DIR/ci_shellify.sh ]] || {
-        ci_err_internal "missing script: '$CI_SCRIPT_DIR/ci_shellify.sh'"
-    }
-}
+# Declare the global environments collected from various sources.
+declare CI_ENV_LIBPNG_VER        # collected from png.h
+declare CI_ENV_AUTOCONF_VER      # collected from configure.ac
+declare CI_ENV_CMAKE_VER         # collected from CMakeLists.txt
+declare CI_ENV_LIBPNGCONFIG_VER  # collected from scripts/libpng-config-head.in
 
 function ci_run_shellify {
+    local my_script my_result
+    my_script="$CI_SCRIPT_DIR/libexec/ci_shellify_${1#--}.sh"
+    shift 1
+    [[ -f $my_script ]] || {
+        ci_err_internal "missing script: '$my_script'"
+    }
     ci_info "shellifying:" "$@"
-    local my_result
-    "$BASH" "$CI_SCRIPT_DIR/ci_shellify.sh" "$@"
+    "$BASH" "$my_script" "$@"
     echo "$my_result" | "$BASH" --posix || ci_err "bad shellify output"
     echo "$my_result"
 }
 
-function ci_verify_version {
+function ci_init_version_verification {
     ci_info "## START OF VERIFICATION ##"
-    local my_env_libpng_ver my_env_autoconf_ver my_env_cmake_ver my_expect
-    ci_init_shellify
-    my_env_libpng_ver="$(ci_run_shellify png.h)"
-    echo "$my_env_libpng_ver"
-    my_env_autoconf_ver="$(ci_run_shellify configure.ac)"
-    echo "$my_env_autoconf_ver"
-    my_env_cmake_ver="$(ci_run_shellify CMakeLists.txt)"
-    echo "$my_env_cmake_ver"
-    ci_info "## VERIFYING: png.h version definitions ##"
-    eval "$my_env_libpng_ver"
-    local my_expect="${PNG_LIBPNG_VER_MAJOR}.${PNG_LIBPNG_VER_MINOR}.${PNG_LIBPNG_VER_RELEASE}"
+    CI_ENV_LIBPNG_VER="$(ci_run_shellify --c png.h)"
+    echo "$CI_ENV_LIBPNG_VER"
+    CI_ENV_AUTOCONF_VER="$(ci_run_shellify --autoconf configure.ac)"
+    echo "$CI_ENV_AUTOCONF_VER"
+    CI_ENV_CMAKE_VER="$(ci_run_shellify --cmake CMakeLists.txt)"
+    echo "$CI_ENV_CMAKE_VER"
+    CI_ENV_LIBPNGCONFIG_VER="$(ci_run_shellify --shell scripts/libpng-config-head.in)"
+    echo "$CI_ENV_LIBPNGCONFIG_VER"
+}
+
+# shellcheck disable=SC2154
+function ci_do_version_verification {
+    local my_expect
+    ci_info "## VERIFYING: version definitions in 'png.h' ##"
+    eval "$CI_ENV_LIBPNG_VER"
+    my_expect="${PNG_LIBPNG_VER_MAJOR}.${PNG_LIBPNG_VER_MINOR}.${PNG_LIBPNG_VER_RELEASE}"
     if [[ "$PNG_LIBPNG_VER_STRING" == "$my_expect"* ]]
     then
         ci_info "matched: \$PNG_LIBPNG_VER_STRING == $my_expect*"
@@ -77,7 +87,7 @@
     else
         ci_err "mismatched: \$PNG_LIBPNG_VER_BUILD != [01]"
     fi
-    ci_info "## VERIFYING: png.h build definitions ##"
+    ci_info "## VERIFYING: build definitions in 'png.h' ##"
     my_expect="${PNG_LIBPNG_VER_MAJOR}.${PNG_LIBPNG_VER_MINOR}.${PNG_LIBPNG_VER_RELEASE}"
     if [[ "$PNG_LIBPNG_VER_STRING" == "$my_expect" ]]
     then
@@ -110,19 +120,19 @@
     else
         ci_err "unexpected: \$PNG_LIBPNG_VER_STRING == '$PNG_LIBPNG_VER_STRING'"
     fi
-    ci_info "## VERIFYING: png.h type definitions ##"
+    ci_info "## VERIFYING: type definitions in 'png.h' ##"
     my_expect="$(echo "png_libpng_version_${PNG_LIBPNG_VER_STRING}" | tr . _)"
     ci_spawn grep -w -e "$my_expect" png.h
-    ci_info "## VERIFYING: configure.ac version definitions ##"
-    eval "$my_env_autoconf_ver"
+    ci_info "## VERIFYING: version definitions in 'configure.ac' ##"
+    eval "$CI_ENV_AUTOCONF_VER"
     if [[ "$PNGLIB_VERSION" == "$PNG_LIBPNG_VER_STRING" ]]
     then
         ci_info "matched: \$PNGLIB_VERSION == \$PNG_LIBPNG_VER_STRING"
     else
         ci_err "mismatched: \$PNGLIB_VERSION != \$PNG_LIBPNG_VER_STRING"
     fi
-    ci_info "## VERIFYING: CMakeLists.txt version definitions ##"
-    eval "$my_env_cmake_ver"
+    ci_info "## VERIFYING: version definitions in 'CMakeLists.txt' ##"
+    eval "$CI_ENV_CMAKE_VER"
     if [[ "$PNGLIB_VERSION" == "$PNG_LIBPNG_VER_STRING" && "$PNGLIB_SUBREVISION" == 0 ]]
     then
         ci_info "matched: \$PNGLIB_VERSION == \$PNG_LIBPNG_VER_STRING"
@@ -133,8 +143,26 @@
     else
         ci_err "mismatched: \$PNGLIB_VERSION != \$PNG_LIBPNG_VER_STRING"
     fi
+    ci_info "## VERIFYING: version definitions in 'scripts/libpng-config-head.in' ##"
+    eval "$CI_ENV_LIBPNGCONFIG_VER"
+    if [[ "$version" == "$PNG_LIBPNG_VER_STRING" ]]
+    then
+        ci_info "matched: \$version == \$PNG_LIBPNG_VER_STRING"
+    else
+        ci_err "mismatched: \$version != \$PNG_LIBPNG_VER_STRING"
+    fi
+}
+
+function ci_finish_version_verification {
     ci_info "## END OF VERIFICATION ##"
-    ci_info "success!"
+    # Relying on "set -o errexit" to not reach here in case of error.
+    ci_info "## SUCCESS ##"
+}
+
+function ci_verify_version {
+    ci_init_version_verification
+    ci_do_version_verification
+    ci_finish_version_verification
 }
 
 function usage {
diff --git a/ci/libexec/ci_shellify_autoconf.sh b/ci/libexec/ci_shellify_autoconf.sh
new file mode 100755
index 0000000..bf37f0d
--- /dev/null
+++ b/ci/libexec/ci_shellify_autoconf.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+set -o errexit -o pipefail -o posix
+
+# Copyright (c) 2019-2025 Cosmin Truta.
+#
+# Use, modification and distribution are subject to the MIT License.
+# Please see the accompanying file LICENSE_MIT.txt
+#
+# SPDX-License-Identifier: MIT
+
+# shellcheck source=ci/lib/ci.lib.sh
+source "$(dirname "$0")/../lib/ci.lib.sh"
+
+function ci_shellify_autoconf {
+    # Convert autoconf (M4) text, specifically originating
+    # from configure.ac, to shell scripting text.
+    # Select only the easy-to-parse definitions of PNGLIB_*.
+    sed -n -e '/^ *PNGLIB_[^ ]*=[$"0-9A-Za-z_]/ p' |
+        sed -e 's/^ *PNG\([0-9A-Za-z_]*\)=\([^# ]*\).*$/PNG\1=\2/' \
+            -e 's/^\([^ ]*=[^ ]*\).*$/export \1;/'
+}
+
+function usage {
+    echo "usage: $CI_SCRIPT_NAME [<options>] configure.ac"
+    echo "options: -?|-h|--help"
+    exit "${@:-0}"
+}
+
+function main {
+    local opt
+    while getopts ":" opt
+    do
+        # This ain't a while-loop. It only pretends to be.
+        [[ $1 == -[?h]* || $1 == --help || $1 == --help=* ]] && usage 0
+        ci_err "unknown option: '$1'"
+    done
+    shift $((OPTIND - 1))
+    [[ $# -eq 0 ]] && usage 2
+    [[ $# -eq 1 ]] || ci_err "too many operands"
+    # And... go!
+    test -e "$1" || ci_err "no such file: '$1'"
+    [[ $(basename -- "$1") == configure.ac ]] || {
+        ci_err "incorrect operand: '$1' (expecting: 'configure.ac')"
+    }
+    ci_shellify_autoconf <"$1"
+}
+
+main "$@"
diff --git a/ci/libexec/ci_shellify_c.sh b/ci/libexec/ci_shellify_c.sh
new file mode 100755
index 0000000..244fc22
--- /dev/null
+++ b/ci/libexec/ci_shellify_c.sh
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+set -o errexit -o pipefail -o posix
+
+# Copyright (c) 2019-2025 Cosmin Truta.
+#
+# Use, modification and distribution are subject to the MIT License.
+# Please see the accompanying file LICENSE_MIT.txt
+#
+# SPDX-License-Identifier: MIT
+
+# shellcheck source=ci/lib/ci.lib.sh
+source "$(dirname "$0")/../lib/ci.lib.sh"
+
+function ci_shellify_c {
+    # Convert C preprocessor text, specifically originating
+    # from png.h, to shell scripting text.
+    # Select only the easy-to-parse definitions of PNG_LIBPNG_*.
+    sed -n -e '/^\# *define * PNG_LIBPNG_[^ ]* * ["0-9A-Za-z_]/ p' |
+        sed -e 's/^\# *define * PNG\([^ ]*\) * \([^ ]*\)/PNG\1=\2/' \
+            -e 's/=PNG\([0-9A-Za-z_]*\)/=\${PNG\1}/' \
+            -e 's/^\([^ ]*=[^ ]*\).*$/export \1;/'
+}
+
+function usage {
+    echo "usage: $CI_SCRIPT_NAME [<options>] png.h"
+    echo "options: -?|-h|--help"
+    exit "${@:-0}"
+}
+
+function main {
+    local opt
+    while getopts ":" opt
+    do
+        # This ain't a while-loop. It only pretends to be.
+        [[ $1 == -[?h]* || $1 == --help || $1 == --help=* ]] && usage 0
+        ci_err "unknown option: '$1'"
+    done
+    shift $((OPTIND - 1))
+    [[ $# -eq 0 ]] && usage 2
+    [[ $# -eq 1 ]] || ci_err "too many operands"
+    # And... go!
+    test -e "$1" || ci_err "no such file: '$1'"
+    [[ $(basename -- "$1") == png.h ]] || {
+        ci_err "incorrect operand: '$1' (expecting: 'png.h')"
+    }
+    ci_shellify_c <"$1"
+}
+
+main "$@"
diff --git a/ci/libexec/ci_shellify_cmake.sh b/ci/libexec/ci_shellify_cmake.sh
new file mode 100755
index 0000000..5596241
--- /dev/null
+++ b/ci/libexec/ci_shellify_cmake.sh
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+set -o errexit -o pipefail -o posix
+
+# Copyright (c) 2019-2025 Cosmin Truta.
+#
+# Use, modification and distribution are subject to the MIT License.
+# Please see the accompanying file LICENSE_MIT.txt
+#
+# SPDX-License-Identifier: MIT
+
+# shellcheck source=ci/lib/ci.lib.sh
+source "$(dirname "$0")/../lib/ci.lib.sh"
+
+function ci_shellify_cmake {
+    # Convert CMake lists text, specifically originating
+    # from CMakeLists.txt, to shell scripting text.
+    # Select only the easy-to-parse definitions of PNGLIB_*.
+    sed -n -e '/^ *set *(PNGLIB_[^ ]* * [$"0-9A-Za-z_].*)/ p' |
+        sed -e 's/^ *set *(PNG\([^ ]*\) * \([^() ]*\)).*$/PNG\1=\2/' \
+            -e 's/^\([^ ]*=[^ ]*\).*$/export \1;/'
+}
+
+function usage {
+    echo "usage: $CI_SCRIPT_NAME [<options>] CMakeLists.txt"
+    echo "options: -?|-h|--help"
+    exit "${@:-0}"
+}
+
+function main {
+    local opt
+    while getopts ":" opt
+    do
+        # This ain't a while-loop. It only pretends to be.
+        [[ $1 == -[?h]* || $1 == --help || $1 == --help=* ]] && usage 0
+        ci_err "unknown option: '$1'"
+    done
+    shift $((OPTIND - 1))
+    [[ $# -eq 0 ]] && usage 2
+    [[ $# -eq 1 ]] || ci_err "too many operands"
+    # And... go!
+    test -e "$1" || ci_err "no such file: '$1'"
+    filename="$(basename -- "$1")"
+    [[ $filename == [Cc][Mm]ake[Ll]ists.txt ]] || {
+        ci_err "incorrect operand: '$1' (expecting: 'CMakeLists.txt')"
+    }
+    ci_shellify_cmake <"$1"
+}
+
+main "$@"
diff --git a/ci/libexec/ci_shellify_shell.sh b/ci/libexec/ci_shellify_shell.sh
new file mode 100755
index 0000000..4170063
--- /dev/null
+++ b/ci/libexec/ci_shellify_shell.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+set -o errexit -o pipefail -o posix
+
+# Copyright (c) 2019-2025 Cosmin Truta.
+#
+# Use, modification and distribution are subject to the MIT License.
+# Please see the accompanying file LICENSE_MIT.txt
+#
+# SPDX-License-Identifier: MIT
+
+# shellcheck source=ci/lib/ci.lib.sh
+source "$(dirname "$0")/../lib/ci.lib.sh"
+
+function ci_shellify_shell {
+    # Convert shell scripting text to shell scripting text.
+    # Select only the easy-to-parse version definitions.
+    sed -n -e '/^ *[A-Za-z_][0-9A-Za-z_]*=[0-9][^ #]* *$/ p' |
+        sed -e 's/^ *\([^ ]*=[^ ]*\) *$/export \1;/'
+}
+
+function usage {
+    echo "usage: $CI_SCRIPT_NAME [<options>] libpng-config-head.in"
+    echo "options: -?|-h|--help"
+    exit "${@:-0}"
+}
+
+function main {
+    local opt
+    while getopts ":" opt
+    do
+        # This ain't a while-loop. It only pretends to be.
+        [[ $1 == -[?h]* || $1 == --help || $1 == --help=* ]] && usage 0
+        ci_err "unknown option: '$1'"
+    done
+    shift $((OPTIND - 1))
+    [[ $# -eq 0 ]] && usage 2
+    [[ $# -eq 1 ]] || ci_err "too many operands"
+    # And... go!
+    test -e "$1" || ci_err "no such file: '$1'"
+    [[ $(basename -- "$1") == libpng-config-head.in ]] || {
+        ci_err "incorrect operand: '$1' (expecting: 'libpng-config-head.in')"
+    }
+    ci_shellify_shell <"$1"
+}
+
+main "$@"