]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - tools/checkmans.sh
whereis: use xstrncpy()
[thirdparty/util-linux.git] / tools / checkmans.sh
index 4b149d0774e8e7ef4ac0b9acd9017c4639b8dfb1..a48549e0ddc9db6a43b39a225b4b5979fdca7233 100755 (executable)
@@ -13,15 +13,21 @@ SCRIPT_INVOCATION_SHORT_NAME=$(basename ${0})
 trap 'echo "${SCRIPT_INVOCATION_SHORT_NAME}: exit on error"; exit 1' ERR
 
 usage() {
-       echo "Usage: ${0} [-ph]"
-       echo " -p   print file names before checking"
+       echo "Usage: ${0} [-vVh]"
+       echo " -v  verbose messaging"
+       echo " -V  print version and exit"
+       echo " -h  print this help and exit"
 }
 
-PRINT_FILE_NAMES='false'
-while getopts ph OPTIONS; do
+VERBOSE='false'
+while getopts vVh OPTIONS; do
        case ${OPTIONS} in
-               p)
-                       PRINT_FILE_NAMES='true'
+               v)
+                       VERBOSE='true'
+                       ;;
+               V)
+                       echo "util-linux: ${SCRIPT_INVOCATION_SHORT_NAME}: v2.1"
+                       exit 0
                        ;;
                h)
                        usage
@@ -33,43 +39,149 @@ while getopts ph OPTIONS; do
        esac
 done
 
-ERROR_FILE=$(mktemp ${SCRIPT_INVOCATION_SHORT_NAME}.XXXXXXXXXX)
-# remove tmp file at exit
-trap "rm -f ${ERROR_FILE}" 0
+# Try to find missing manuals matching build targets with manual files.
+declare -A MAN_LIST BIN_LIST
+
+declare -i ITER
+declare -i COUNT_GROG=0
+declare -i COUNT_TROFF=0
+declare -i COUNT_REPEATS=0
+declare -a REPEATS
+declare -A KNOWN_REPEATS
+KNOWN_REPEATS[mount.8]='foo l2 l c overlay'
+KNOWN_REPEATS[hexdump.1]='l'
+KNOWN_REPEATS[flock.1]='"$0"'
+KNOWN_REPEATS[switch_root.8]='$DIR'
+KNOWN_REPEATS[logger.1]='-'
+
+remove_repeats()
+{
+       set +u
+       for KN in ${KNOWN_REPEATS[${I##*/}]}; do
+               if [ "${KN}" = "${REPEATS[$1]}" ]; then
+                       if $VERBOSE; then
+                               echo "info: ${I} removing repeat: ${REPEATS[$1]}"
+                       fi
+                       unset REPEATS[$1]
+               fi
+       done
+       set -u
+}
+
+cd $(git rev-parse --show-toplevel)
 
 for I in $(
-       find $(git rev-parse --show-toplevel) -name '*.[1-8]' |
-       egrep -v '(Documentation|.git|/.libs/|autom4te.cache)'
+       find . -type f -name '*[[:alpha:]].[1-8]' |grep -v "autom4te.cache\|\.libs/\|\.git"
 ); do
-       # FIXME: the determination whether a manual does include
-       # should probably be somewhat smarter.
-       IS_INCLUDE=$(wc -w ${I} | awk '{print $1}')
-       if [ ${IS_INCLUDE} -eq 2 ]; then
-               # Some manuals, such as x86_64, call include which
-               # will read system manual.  Testing what comes from
-               # package does not make much sense, so skip doing it.
-               if ${PRINT_FILE_NAMES}; then
-                       echo "skipping: ${I}"
+       MAN_FILE=${I##*/}
+       MAN_LIST[${MAN_FILE%%.[0-9]}]=1
+       if awk '{if (1 < NR) {exit 1}; if ($1 ~ /^.so$/) {exit 0}}' ${I}; then
+               # Some manuals, such as x86_64, call inclusion and they
+               # should not be tested any further.
+               if ${VERBOSE}; then
+                       printf "skipping: ${I}: includes "
+                       awk '{print $2}' ${I}
                fi
                continue
        fi
-       if ${PRINT_FILE_NAMES}; then
+       if ${VERBOSE}; then
                echo "testing: ${I}"
-               man --warnings=all ${I} >/dev/null
+       fi
+       RET=1
+       cat ${I} | troff -mandoc -ww -z |& grep "<" && RET=$?
+       if [ $RET = 0 ]; then
+       echo "From: cat ${I} | troff -mandoc -ww -z"
+       echo "=================================================="
+       ((++COUNT_TROFF))
+       fi
+       GROG=1
+       if command -v lexgrog &> /dev/null; then
+               if ! lexgrog ${I} >/dev/null; then
+                       echo "error: run: lexgrog ${I}"
+                       echo "=================================================="
+                       ((++COUNT_GROG))
+               fi
+       elif command -v grog &> /dev/null; then
+               if ! grog ${I} | grep man >/dev/null; then
+                       echo "error: grog ${I} is not a man file"
+                       echo "=================================================="
+                       ((++COUNT_GROG))
+               fi
        else
-               man --warnings=all ${I} >/dev/null 2>> ${ERROR_FILE}
+               GROG=0
+       fi
+       REPEATS=( $(cat ${I} | troff -mandoc -Tascii 2>/dev/null | grotty |
+               col -b |
+               sed  -e 's/\s\+/\n/g; /^$/d' |
+               awk 'BEGIN { p="" } { if (0 < length($0)) { if (p == $0) { print } } p = $0 }') )
+       if [ 0 -lt "${#REPEATS[@]}" ]; then
+               ITER=${#REPEATS[@]}+1
+               while ((ITER--)); do
+                       remove_repeats ${ITER}
+               done
+               if [ 0 -lt "${#REPEATS[@]}" ]; then
+                       echo "warning: ${I} has repeating words: ${REPEATS[@]}"
+                       echo "=================================================="
+                       ((++COUNT_REPEATS))
+               fi
        fi
 done
 
-COUNT_ERRORS=$(awk 'END {print NR}' ${ERROR_FILE})
-if [ ${COUNT_ERRORS} -ne 0 ]; then
-       echo "${SCRIPT_INVOCATION_SHORT_NAME}: failed"
-       echo "use: $(readlink -f ${0}) -p"
-       echo "     to find where the problems are."
+# Create a list of build targets.
+for I in $(find $(git rev-parse --show-toplevel) -name 'Make*.am' | xargs awk '
+$1 ~ /_SOURCES/ {
+       if ($1 ~ /^test/ ||
+           $1 ~ /^no(inst|dist)/ ||
+           $1 ~ /^sample/ ||
+           $1 ~ /^BUILT/) {
+               next
+       }
+       sub(/_SOURCES/, "")
+       if ($1 ~ /^lib.*_la/) {
+               next
+       }
+       sub(/_static/, "")
+       gsub(/_/, ".")
+       sub(/switch.root/, "switch_root")
+       sub(/pivot.root/, "pivot_root")
+       print $1
+}'); do
+       BIN_LIST[$I]=1
+done
+
+# Find if build target does not have manual.
+set +u
+for I in ${!BIN_LIST[@]}; do
+       if [ -v ${MAN_LIST[$I]} ]; then
+               echo "warning: ${SCRIPT_INVOCATION_SHORT_NAME}: ${I} does not have man page"
+       fi
+done
+set -u
+
+echo "${SCRIPT_INVOCATION_SHORT_NAME}: ${#BIN_LIST[*]} build targets were found"
+echo "${SCRIPT_INVOCATION_SHORT_NAME}: ${#MAN_LIST[*]} files were tested"
+
+if [ ${GROG} = 0 ]; then
+echo "warning: neither grog nor lexgrog commands were found"
+fi
+
+if [ ${COUNT_GROG} -ne 0 ]; then
+       echo "error: ${SCRIPT_INVOCATION_SHORT_NAME}: ${COUNT_GROG} files failed (lex)grog man-page test"
+fi
+if [ ${COUNT_TROFF} -ne 0 ]; then
+       echo "error: ${SCRIPT_INVOCATION_SHORT_NAME}: ${COUNT_TROFF} files failed troff parsing test"
+fi
+if [ ${COUNT_REPEATS} -ne 0 ]; then
+       echo "error: ${SCRIPT_INVOCATION_SHORT_NAME}: ${COUNT_REPEATS} files have repeating words"
+fi
+ITER=${#MAN_LIST[*]}-${COUNT_GROG}-${COUNT_TROFF}-${COUNT_REPEATS}
+echo "${SCRIPT_INVOCATION_SHORT_NAME}: ${ITER} man-pages approved"
+
+if [ ${COUNT_GROG} -ne 0 -o ${COUNT_TROFF} -ne 0 -o ${COUNT_REPEATS} -ne 0 ]; then
        exit 1
 fi
 
-if ! ${PRINT_FILE_NAMES}; then
+if ! ${VERBOSE}; then
        echo "${SCRIPT_INVOCATION_SHORT_NAME}: success"
 fi
 exit 0