summaryrefslogtreecommitdiffstats
path: root/doxygen/build_man.sh
diff options
context:
space:
mode:
Diffstat (limited to 'doxygen/build_man.sh')
-rwxr-xr-xdoxygen/build_man.sh323
1 files changed, 323 insertions, 0 deletions
diff --git a/doxygen/build_man.sh b/doxygen/build_man.sh
new file mode 100755
index 0000000..7eab8fa
--- /dev/null
+++ b/doxygen/build_man.sh
@@ -0,0 +1,323 @@
+#!/bin/sh
+[ -n "$BASH" ] || exec bash -p $0 $@
+
+# 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).
+# Args: none or 2 being man7 page name & relative path of source with \mainpage
+
+declare -A renamed_page
+
+main(){
+ set -e
+ pushd man/man3 >/dev/null; rm -f _*
+ count_real_pages
+ rename_real_pages
+ make_symlinks
+ post_process $@
+}
+
+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)
+ do for j in $(ls -S | tail -n+$first_link)
+ do grep -E -q $i$ $j && break
+ done
+ mv -f $i $j
+ renamed_page[$i]=$j
+ done
+}
+
+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
+
+ # Fix rendering of verbatim "\n" (in code snippets)
+ sed -i 's/\\n/\\\\n/' $target
+
+ done
+
+ [ $# -ne 2 ] || make_man7 $@
+
+ remove_temp_files
+}
+
+make_man7(){
+ popd >/dev/null
+ target=$(grep -Ew INPUT doxygen.cfg | rev | cut -f1 -d' ' | rev)/$2
+ mypath=$(dirname $0)
+
+ # Build up temporary source in temp.c
+ # (doxygen only makes man pages from .c files).
+ mygrep \\\\mainpage $target
+ tail -n+$((linnum-1)) $target | head -n1 >temp.c
+ echo " * \\defgroup $1 $1 overview" >>temp.c
+ tail -n+$((linnum+1)) $target >$fileA
+ linnum=$(grep -En '\*/' $fileA | head -n1 | cut -d: -f1)
+ head -n$((linnum - 1)) $fileA >> temp.c
+
+ echo ' */' >> temp.c
+ cat >> temp.c <<////
+
+ /**
+ * @{
+ *
+ * $1 - DELETE_ME
+ */
+int $1(void)
+{
+ return 0;
+}
+/**
+ * @}
+ */
+////
+
+ # Create temporary doxygen config in fileC
+ cat /dev/null >$fileC
+ for i in \
+ PROJECT_NAME \
+ PROJECT_NUMBER \
+ ABBREVIATE_BRIEF \
+ FULL_PATH_NAMES \
+ TAB_SIZE \
+ OPTIMIZE_OUTPUT_FOR_C \
+ EXAMPLE_PATTERNS \
+ ALPHABETICAL_INDEX \
+ SEARCHENGINE \
+ GENERATE_LATEX \
+ ; do grep -Ew $i doxygen.cfg >>$fileC; done
+ cat >>$fileC <<////
+INPUT = temp.c
+GENERATE_HTML = NO
+GENERATE_MAN = YES
+MAN_EXTENSION = .7
+////
+
+ doxygen $fileC >/dev/null
+
+ # Remove SYNOPSIS line if there is one
+ target=man/man7/$1.7
+ mygrep "SH SYNOPSIS" $target
+ [ $linnum -eq 0 ] || delete_lines $linnum $((linnum+1))
+
+ # doxygen 1.8.9.1 and possibly newer run the first para into NAME
+ # (i.e. in this unusual group). There won't be a SYNOPSIS when this happens
+ if grep -Eq "overview$1" $target; then
+ head -n2 temp.c >$fileA
+ cat >>$fileA <<////
+ * \\manonly
+.PP
+.SH "Detailed Description"
+.PP
+\\endmanonly
+////
+ tail -n+3 temp.c >>$fileA
+ cat $fileA >temp.c
+ doxygen $fileC >/dev/null
+ fi
+
+ # Insert top-level "See also" of man7 page in all real man3 pages
+ for target in $(find man/man3 -type f)
+ do mygrep "Detailed Description" $target
+ [ $linnum -ne 0 ] || mygrep "Function Documentation" $target
+ [ $linnum -ne 0 ] || { echo "NO HEADER IN $target" >&2; continue; }
+ head -n$((linnum-1)) $target >$fileA
+ cat >>$fileA <<////
+.SH "See also"
+\\fB${1}\\fP(7)
+////
+ tail -n+$linnum $target >>$fileA
+ cp $fileA $target
+ done
+
+ rm temp.c
+}
+
+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 (\\fB)?[[:digit:]]*(\\fP)? 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
+ # A 1-line Detailed Description is also 3 lines long,
+ # but the 3rd line is not empty
+ i=$(($i -1))
+ [ $(tail -n+$i $target | head -n1 | wc -c) -le 2 ] || return 0
+ delete_lines $linnum $i
+}
+
+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 $@