ci: Update and rename ci_lint_ci.sh to ci_lint.sh; update .shellcheckrc

The ci_lint.sh program can now lint the entire libpng source tree.
diff --git a/ci/.shellcheckrc b/ci/.shellcheckrc
index 0260dcc..051d551 100644
--- a/ci/.shellcheckrc
+++ b/ci/.shellcheckrc
@@ -1,3 +1,7 @@
+# Disable the "expressions don't expand in single quotes, use double quotes"
+# advice. We need the regular expressions to remain uninterpolated.
+disable=SC2016
+
 # Disable the "variable appears unused" warning caused by the use of getopts
 # with an obligatory (but unused) variable name in the main function.
 disable=SC2034
diff --git a/ci/ci_lint.sh b/ci/ci_lint.sh
new file mode 100755
index 0000000..9b9dc6b
--- /dev/null
+++ b/ci/ci_lint.sh
@@ -0,0 +1,135 @@
+#!/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"
+
+# Initialize the global constants CI_{...}{CHECK,CHECKER,LINT}.
+CI_SHELLCHECK="${CI_SHELLCHECK:-shellcheck}"
+CI_EDITORCONFIG_CHECKER="${CI_EDITORCONFIG_CHECKER:-editorconfig-checker}"
+CI_YAMLLINT="${CI_YAMLLINT:-yamllint}"
+
+# Initialize the global lint counter.
+CI_LINT_COUNTER=0
+
+function ci_init_lint {
+    ci_info "## START OF LINTING ##"
+    local my_program
+    # Complete the initialization of CI_SHELLCHECK.
+    # Set it to the empty string if the shellcheck program is unavailable.
+    my_program="$(command -v "$CI_SHELLCHECK")" || {
+        ci_warn "program not found: '$CI_SHELLCHECK'"
+    }
+    CI_SHELLCHECK="$my_program"
+    # Complete the initialization of CI_EDITORCONFIG_CHECKER.
+    # Set it to the empty string if the editorconfig-checker program is unavailable.
+    my_program="$(command -v "$CI_EDITORCONFIG_CHECKER")" || {
+        ci_warn "program not found: '$CI_EDITORCONFIG_CHECKER'"
+    }
+    CI_EDITORCONFIG_CHECKER="$my_program"
+    # Complete the initialization of CI_YAMLLINT.
+    # Set it to the empty string if the yamllint program is unavailable.
+    my_program="$(command -v "$CI_YAMLLINT")" || {
+        ci_warn "program not found: '$CI_YAMLLINT'"
+    }
+    CI_YAMLLINT="$my_program"
+}
+
+function ci_finish_lint {
+    ci_info "## END OF LINTING ##"
+    if [[ $CI_LINT_COUNTER -eq 0 ]]
+    then
+        ci_info "success!"
+        return 0
+    else
+        ci_warn "$CI_LINT_COUNTER failure(s)"
+        return 1
+    fi
+}
+
+function ci_lint_ci_scripts {
+    [[ -x $CI_SHELLCHECK ]] || {
+        ci_warn "## NOT LINTING: CI scripts ##"
+        return 0
+    }
+    ci_info "## LINTING: CI scripts ##"
+    local my_file
+    ci_spawn "$CI_SHELLCHECK" --version
+    for my_file in ci/*.sh
+    do
+        ci_spawn "$CI_SHELLCHECK" -x "$my_file" || {
+            CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1))
+        }
+    done
+}
+
+function ci_lint_text_files {
+    [[ -x $CI_EDITORCONFIG_CHECKER ]] || {
+        ci_warn "## NOT LINTING: text files ##"
+        return 0
+    }
+    ci_info "## LINTING: text files ##"
+    local my_file
+    ci_spawn "$CI_EDITORCONFIG_CHECKER" --version
+    ci_spawn "$CI_EDITORCONFIG_CHECKER" || {
+        CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1))
+    }
+}
+
+function ci_lint_yaml_files {
+    [[ -x $CI_YAMLLINT ]] || {
+        ci_warn "## NOT LINTING: YAML files ##"
+        return 0
+    }
+    ci_info "## LINTING: YAML files ##"
+    local my_file
+    ci_spawn "$CI_YAMLLINT" --version
+    for my_file in .*.yml
+    do
+        ci_spawn "$CI_YAMLLINT" --strict "$my_file" || {
+            CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1))
+        }
+    done
+}
+
+function ci_lint {
+    ci_init_lint
+    ci_lint_ci_scripts
+    ci_lint_text_files
+    ci_lint_yaml_files
+    # TODO: ci_lint_png_files, etc.
+    ci_finish_lint
+}
+
+function usage {
+    echo "usage: $CI_SCRIPT_NAME [<options>]"
+    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 ]] || {
+        echo >&2 "error: unexpected argument: '$1'"
+        usage 2
+    }
+    # And... go!
+    ci_lint
+}
+
+main "$@"
diff --git a/ci/ci_lint_ci.sh b/ci/ci_lint_ci.sh
deleted file mode 100755
index 60b7faf..0000000
--- a/ci/ci_lint_ci.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-# 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"
-
-CI_SHELLCHECK="$(command -v shellcheck || true)"
-CI_YAMLLINT="$(command -v yamllint || true)"
-CI_LINT_COUNTER=0
-
-function ci_lint_ci_config_files {
-    ci_info "linting: CI config files"
-    local MY_FILE
-    if [[ -x $CI_YAMLLINT ]]
-    then
-        ci_spawn "$CI_YAMLLINT" --version
-        for MY_FILE in "$CI_TOPLEVEL_DIR"/.*.yml
-        do
-            ci_spawn "$CI_YAMLLINT" --strict "$MY_FILE" || {
-                CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1))
-            }
-        done
-    else
-        ci_warn "program not found: 'yamllint'; skipping checks"
-    fi
-}
-
-function ci_lint_ci_scripts {
-    ci_info "linting: CI scripts"
-    local MY_FILE
-    if [[ -x $CI_SHELLCHECK ]]
-    then
-        ci_spawn "$CI_SHELLCHECK" --version
-        for MY_FILE in "$CI_SCRIPT_DIR"/*.sh
-        do
-            ci_spawn "$CI_SHELLCHECK" -x "$MY_FILE" || {
-                CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1))
-            }
-        done
-    else
-        ci_warn "program not found: 'shellcheck'; skipping checks"
-    fi
-}
-
-function ci_lint_ci_scripts_license {
-    ci_info "linting: CI scripts license"
-    ci_spawn grep -F "MIT License" ci/LICENSE_MIT.txt || {
-        ci_warn "bad or missing CI license file: '$CI_SCRIPT_DIR/LICENSE_MIT.txt'"
-        CI_LINT_COUNTER=$((CI_LINT_COUNTER + 1))
-    }
-}
-
-function usage {
-    echo "usage: $CI_SCRIPT_NAME"
-    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 ]] && usage
-        ci_err "unknown option: '$1'"
-    done
-    shift $((OPTIND - 1))
-    # And... go!
-    [[ $# -eq 0 ]] || ci_err "unexpected argument: '$1'"
-    ci_lint_ci_config_files
-    ci_lint_ci_scripts
-    ci_lint_ci_scripts_license
-    if [[ $CI_LINT_COUNTER -eq 0 ]]
-    then
-        ci_info "success!"
-        exit 0
-    else
-        ci_info "failed on $CI_LINT_COUNTER file(s)"
-        exit 1
-    fi
-}
-
-main "$@"