summaryrefslogtreecommitdiffstats
path: root/scripts/add_parens_for_own_funcs.sh
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/add_parens_for_own_funcs.sh')
-rwxr-xr-xscripts/add_parens_for_own_funcs.sh251
1 files changed, 251 insertions, 0 deletions
diff --git a/scripts/add_parens_for_own_funcs.sh b/scripts/add_parens_for_own_funcs.sh
new file mode 100755
index 0000000..1bf6d2a
--- /dev/null
+++ b/scripts/add_parens_for_own_funcs.sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# add_parens_for_own_funcs.sh
+#
+# This script is designed to fix inconsistencies in the use of
+# parentheses after function names in the manual pages.
+# It changes manual pages to add these parentheses.
+# The problem is how to determine what is a "function name".
+# The approach this script takes is the following:
+#
+# For each manual page named in the command line that contains
+# more than one line (i.e., skip man-page link files)
+# Create a set of names taken from the .SH section of the
+# page and from grepping all pages for names that
+# have .so links to this page
+# For each name obtained above
+# If we can find something that looks like a prototype on
+# the page, then
+# Try to substitute instances of that name on the page.
+# (instances are considered to be words formatted
+# using ^.[BI] or \f[BI]...\f[PR] -- this script
+# ignores unformatted instances of function names.)
+# fi
+# done
+# done
+#
+# The rationale of the above is that the most likely function names
+# that appear on a page are those that the manual page is describing.
+# It doesn't fix everything, but it catches many instances.
+# The rest will have to be done manually.
+#
+# This script is rather verbose because it provides a computer-assisted
+# solution, rather than one that is fully automated. When running it,
+# pipe the output through
+#
+# ... 2>&1 | less
+#
+# and take a good look at the output. In particular, you can scan
+# the output for *possible* problems by looking for the pattern: /^%%%/
+# The script's output should be enough to help you determine if the
+# problem is real or not.
+#
+# Suggested usage (in this case to fix pages in Section 2):
+#
+# cd man2
+# sh add_parens_for_own_funcs.sh *.2 2>&1 | tee changes.log | less
+#
+# Use the "-n" option for a dry run, in order to see what would be
+# done, without actually doing it.
+#
+# (And, yes, there are many ways that this script could probably be
+# made to work faster...)
+#
+######################################################################
+#
+# (C) Copyright 2005 & 2013, Michael Kerrisk
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details
+# (http://www.gnu.org/licenses/gpl-2.0.html).
+#
+#
+#
+
+file_base="tmp.$(basename $0)"
+
+work_dst_file="$file_base.dst"
+work_src_file="$file_base.src"
+
+matches_for_all_names="$file_base.all_match"
+matches_for_this_name="$file_base.this_match"
+
+all_files="$work_dst_file $work_src_file $matches_for_all_names \
+ $matches_for_this_name"
+
+rm -f $all_files
+
+# Command-line option processing
+
+really_do_it=1
+while getopts "n" optname; do
+ case "$optname" in
+ n) really_do_it=0;
+ ;;
+ *) echo "Unknown option: $OPTARG"
+ exit 1
+ ;;
+ esac
+done
+
+shift $(( $OPTIND - 1 ))
+
+# Only process files with > 1 line -- single-line files are link files
+
+for page in $(wc "$@" 2> /dev/null | awk '$1 > 1 {print $4}'| \
+ grep -v '^total'); do
+
+ echo ">>>>>>>>>>>>>>>>>>>>>>>>>" $page "<<<<<<<<<<<<<<<<<<<<<<<<<"
+ echo ">>>>>>>>>>>>>>>>>>>>>>>>>" $page "<<<<<<<<<<<<<<<<<<<<<<<<<" 1>&2
+
+ # Extract names that follow the ".SH NAME" directive -- these will
+ # be our guesses about function names to look for
+
+ sh_nlist=$(cat $page | \
+ awk 'BEGIN { p = 0 }
+ /^\.SH NAME/ { p = NR }
+ /^.SH/ && NR > p { p = 0 } # Stop at the next .SH directive
+ p > 0 && NR > p { print $0 } # These are the lines between
+ # the two .SH directives
+ ')
+ sh_nlist=$(echo $sh_nlist | sed -e 's/ *\\-.*//' -e 's/, */ /g')
+ echo "### .SH name list:" $sh_nlist
+
+ # Some pages like msgop.2 don't actually list the function names in
+ # the .SH section -- but we can try using link pages to give us
+ # another guess at the right function names to look for
+
+ so_nlist=$(grep -l "^\\.so.*/$(echo $page| \
+ sed -e 's/\.[1-8]$//')\\." $* | \
+ sed -e 's/\.[1-8]$//g')
+
+ echo "### .so name list:" $so_nlist
+
+ # Combine the two lists, eliminate duplicates
+
+ nlist=$(echo $sh_nlist $so_nlist | tr ' ' '\012' | sort -u)
+
+ maybechanged=0
+
+ cp $page $work_dst_file
+ rm -f $matches_for_all_names; # touch $matches_for_all_names
+
+ for rname in $nlist; do # try each name from out list for this page
+
+ # A very few names in .SH sections contain regexp characters!
+
+ name=$(echo $rname | sed -e 's/\*/\\*/g' -e 's/\./\\./g' \
+ -e 's/\[/\\[/g' -e 's/\+/\\+/g')
+
+ echo "########## trying $rname ##########"
+
+ rm -f $matches_for_this_name
+
+ grep "^.BR* $name *$" $page | \
+ >> $matches_for_this_name
+ grep "^.BR $name [^(\"]$" $page | \
+ >> $matches_for_this_name
+ grep '\\fB'"$name"'\\f[PR][ .,;:]' $page | \
+ >> $matches_for_this_name
+ grep '\\fB'"$name"'\\f[PR]$' $page | \
+ >> $matches_for_this_name
+
+ cat $matches_for_this_name | sed -e 's/^/### MATCH: /'
+ cat $matches_for_this_name >> $matches_for_all_names
+
+ # Only process a page if we can see something that looks
+ # like a function prototype for this name in the page
+
+ if grep -q "$name *(" $page || \
+ grep -q "$name\\\\f.[\\ ]*(" $page; then
+
+ # '.B name$'
+ # '.BR name [^("]*$
+ # (The use of [^"] in the above eliminates lines
+ # like: .BR func " and " func
+ # Those lines better be done manually.)
+ cp $work_dst_file $work_src_file
+ cat $work_src_file | \
+ sed \
+ -e "s/^.BR* $name *\$/.BR $name ()/" \
+ -e "/^.BR *$name [^(\"]*\$/s/^.BR *$name /.BR $name ()/" \
+ > $work_dst_file
+
+ # '\fBname\fP[ .,;:]'
+ # '\fBname\fP$'
+ cp $work_dst_file $work_src_file
+ cat $work_src_file | \
+ sed \
+ -e 's/\\fB'$name'\\fP /\\fB'$name'\\fP() /g' \
+ -e 's/\\fB'$name'\\fP\./\\fB'$name'\\fP()./g' \
+ -e 's/\\fB'$name'\\fP,/\\fB'$name'\\fP(),/g' \
+ -e 's/\\fB'$name'\\fP;/\\fB'$name'\\fP();/g' \
+ -e 's/\\fB'$name'\\fP:/\\fB'$name'\\fP():/g' \
+ -e 's/\\fB'$name'\\fP$/\\fB'$name'\\fP()/g' \
+ > $work_dst_file
+
+ # '\fBname\fR[ .,;:]'
+ # '\fBname\fR$'
+ cp $work_dst_file $work_src_file
+ cat $work_src_file | \
+ sed \
+ -e 's/\\fB'$name'\\fR /\\fB'$name'\\fR() /g' \
+ -e 's/\\fB'$name'\\fR\./\\fB'$name'\\fR()./g' \
+ -e 's/\\fB'$name'\\fR,/\\fB'$name'\\fR(),/g' \
+ -e 's/\\fB'$name'\\fR;/\\fB'$name'\\fR();/g' \
+ -e 's/\\fB'$name'\\fR:/\\fB'$name'\\fR():/g' \
+ -e 's/\\fB'$name'\\fR$/\\fB'$name'\\fR()/g' \
+ > $work_dst_file
+
+ maybechanged=1
+ else
+ echo "%%%%%%%%%% WARNING: NO PROTOTYPE MATCHES FOR: $name"
+ fi
+ done
+
+ # If the file was changed, then:
+ # show "diff -U" output to user;
+ # and count number of changed lines and compare it with what
+ # we expected, displaying a warning if it wasn't what was expected
+
+ if test $maybechanged -ne 0 && ! cmp -s $page $work_dst_file; then
+ diff -u $page $work_dst_file
+
+ made_matches=$(diff -U 0 $page $work_dst_file | grep '^\+[^+]' | \
+ wc -l | awk '{print $1}')
+
+ # The following line makes the changes -- comment it out if you
+ # just want to do a dry run to see what changes would be made.
+
+ if test $really_do_it -ne 0; then
+ cat $work_dst_file > $page
+ fi
+
+ else
+ echo "### NOTHING CHANGED"
+ made_matches=0
+ fi
+
+ min_match=$(cat $matches_for_all_names | \
+ sort -u | wc -l | awk '{print $1}')
+
+ echo "### Expected matches >= $min_match"
+ echo "### Made matches $made_matches"
+
+ if test $made_matches -lt $min_match; then
+ echo "%%%%%%%%%% WARNING: NOT ENOUGH MATCHES: " \
+ "$made_matches < $min_match"
+ fi
+
+done
+
+# clean up
+
+rm -f $all_files
+exit 0