From 04d1e65f8d9381cec0ce2e02037a62f30fd4f15f Mon Sep 17 00:00:00 2001 From: Duncan Roe Date: Sat, 28 Aug 2021 13:35:04 +1000 Subject: build: doc: Add a man page post-processor to build_man.sh - If there is a "Modules" section, delete it - If "Detailed Description" is empty, delete "Detailed Description" line - Reposition SYNOPSIS (with headers that we inserted) to start of page, integrating with defined functions to look like other man pages - Delete all "Definition at line nnn" lines - Delete lines that make older versions of man o/p an unwanted blank line For better readability, shell function definitions are separated by blank lines, and there is a bit of annotation. Signed-off-by: Duncan Roe Signed-off-by: Pablo Neira Ayuso --- doxygen/build_man.sh | 200 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 195 insertions(+), 5 deletions(-) diff --git a/doxygen/build_man.sh b/doxygen/build_man.sh index 304a305..e0cda71 100755 --- a/doxygen/build_man.sh +++ b/doxygen/build_man.sh @@ -1,20 +1,37 @@ #!/bin/bash -p -# We need to use bash for its associative array facility + +# Script to process man pages output by doxygen. +# We need to use bash for its associative array facility. # (`bash -p` prevents import of functions from the environment). + declare -A renamed_page -main(){ set -e; cd man/man3; rm -f _* + +main(){ + set -e + cd man/man3; rm -f _* count_real_pages rename_real_pages make_symlinks + post_process } -count_real_pages(){ page_count=0 + +count_real_pages(){ + page_count=0 + # + # Count "real" man pages (i.e. not generated by MAN_LINKS) + # MAN_LINKS pages are 1-liners starting .so + # Method: list files in descending order of size, + # looking for the first 1-liner + # for i in $(ls -S) do head -n1 $i | grep -E -q '^\.so' && break page_count=$(($page_count + 1)) done first_link=$(($page_count + 1)) } -rename_real_pages(){ for i in $(ls -S | head -n$page_count) + +rename_real_pages(){ + for i in $(ls -S | head -n$page_count) do for j in $(ls -S | tail -n+$first_link) do grep -E -q $i$ $j && break done @@ -22,8 +39,181 @@ rename_real_pages(){ for i in $(ls -S | head -n$page_count) renamed_page[$i]=$j done } -make_symlinks(){ for j in $(ls -S | tail -n+$first_link) + +make_symlinks(){ + for j in $(ls -S | tail -n+$first_link) do ln -sf ${renamed_page[$(cat $j | cut -f2 -d/)]} $j done } + +post_process(){ + make_temp_files + # + # DIAGNOSTIC / DEVELOPMENT CODE + # set -x and restrict processing to keep_me: un-comment to activate + # Change keep_me as required + # + #keep_me=nfq_icmp_get_hdr.3;\ + #do_diagnostics;\ + # + # Work through the "real" man pages + for target in $(ls -S | head -n$page_count) + do mygrep "^\\.SH \"Function Documentation" $target + # Next file if this isn't a function page + [ $linnum -ne 0 ] || continue + + del_modules + del_bogus_synopsis + fix_name_line + move_synopsis + del_empty_det_desc + del_def_at_lines + fix_double_blanks + done + + remove_temp_files +} + +fix_double_blanks(){ + linnum=1 + # + # Older versions of man display a blank line on encountering "\fB\fP"; + # newer versions of man do not. + # doxygen emits "\fB\fP" on seeing "\par" on a line by itself. + # "\par" gives us double-spacing in the web doc, which we want, but double- + # spacing looks odd in a man page so remove "\fB\fP". + # + while [ $linnum -ne 0 ] + do mygrep \\\\fB\\\\fP $target + [ $linnum -eq 0 ] || delete_lines $linnum $linnum + done +} + +del_def_at_lines(){ + linnum=1 + while [ $linnum -ne 0 ] + do mygrep "^Definition at line [[:digit:]]* of file" $target + [ $linnum -eq 0 ] || delete_lines $(($linnum - 1)) $linnum + done +} + +# Only invoked if you un-comment the 2 diagnostic / development lines above +do_diagnostics(){ + mv $keep_me xxx + rm *.3 + mv xxx $keep_me + page_count=1 + set -x +} + +del_empty_det_desc(){ + mygrep "^\\.SH \"Function Documentation" $target + i=$linnum + mygrep "^\\.SH \"Detailed Description" $target + [ $linnum -ne 0 ] || return 0 + [ $(($i - $linnum)) -eq 3 ] || return 0 + delete_lines $linnum $(($i -1)) +} + +move_synopsis(){ + mygrep "SH SYNOPSIS" $target + [ $linnum -ne 0 ] || return 0 + i=$linnum + # If this is a doxygen-created synopsis, leave it. + # (We haven't inserted our own one in the source yet) + mygrep "^\\.SS \"Functions" $target + [ $i -gt $linnum ] || return 0 + + mygrep "^\\.SH \"Function Documentation" $target + j=$(($linnum - 1)) + head -n$(($j - 1)) $target | tail -n$(($linnum - $i - 1)) >$fileC + delete_lines $i $j + mygrep "^\\.SS \"Functions" $target + head -n$(($linnum - 1)) $target >$fileA + tail -n+$(($linnum + 1)) $target >$fileB + cat $fileA $fileC $fileB >$target +} + +fix_name_line(){ + all_funcs="" + + # Search a shortened version of the page in case there are .RI lines later + mygrep "^\\.SH \"Function Documentation" $target + head -n$linnum $target >$fileC + + while : + do mygrep ^\\.RI $fileC + [ $linnum -ne 0 ] || break + # Discard this entry + tail -n+$(($linnum + 1)) $fileC >$fileB + cp $fileB $fileC + + func=$(cat $fileG | cut -f2 -d\\ | cut -c3-) + [ -z "$all_funcs" ] && all_funcs=$func ||\ + all_funcs="$all_funcs, $func" + done + # For now, assume name is at line 5 + head -n4 $target >$fileA + desc=$(head -n5 $target | tail -n1 | cut -f3- -d" ") + tail -n+6 $target >$fileB + cat $fileA >$target + echo "$all_funcs \\- $desc" >>$target + cat $fileB >>$target +} + +del_modules(){ + mygrep "^\.SS \"Modules" $target + [ $linnum -ne 0 ] || return 0 + i=$linnum + mygrep "^\\.SS \"Functions" $target + delete_lines $i $(($linnum - 1)) +} + +del_bogus_synopsis(){ + mygrep "SH SYNOPSIS" $target + # + # doxygen 1.8.20 inserts its own SYNOPSIS line but there is no mention + # in the documentation or git log what to do with it. + # So get rid of it + # + [ $linnum -ne 0 ] || return 0 + i=$linnum + # Look for the next one + tail -n+$(($i + 1)) $target >$fileC;\ + mygrep "SH SYNOPSIS" $fileC + [ $linnum -ne 0 ] || return 0 + + mygrep "^\\.SS \"Functions" $target + delete_lines $i $(($linnum - 1)) +} + +# Delete lines $1 through $2 from $target +delete_lines(){ + head -n$(($1 - 1)) $target >$fileA + tail -n+$(($2 +1)) $target >$fileB + cat $fileA $fileB >$target +} + +mygrep(){ + set +e + grep -En "$1" $2 2>/dev/null >$fileH + [ $? -ne 0 ] && linnum=0 ||\ + { head -n1 $fileH >$fileG; linnum=$(cat $fileG | cut -f1 -d:); } + set -e +} + +make_temp_files(){ + temps="A B C G H" + for i in $temps + do declare -g file$i=$(mktemp) + done +} + +remove_temp_files(){ + for i in $temps + do j=file$i + rm ${!j} + done +} + main -- cgit v1.2.1