#!/bin/sh # # Script to generate an HTML index of all C code from the current directory # downwards (skipping directories ending in ~). The header comment in each # file is listed, and each function's prototype and comment are given. A # list of "TODO:" comments is also generated. # # Outputs the HTML on standard output. # # If a parameter is given, it is the prefix to put before any "view file" # links, eg ".." to link to "../dir/file.c" instead of "dir/file.c". # # Skips any files containing the string !NOINDEX. # # Requires ctags and cproto. # command -v "ctags" >/dev/null 2>&1 || { echo "${0##*/}: ctags: command not found" 1>&2; exit 1; } command -v "cproto" >/dev/null 2>&1 || { echo "${0##*/}: cproto: command not found" 1>&2; exit 1; } linkPrefix=$1 test -n "${linkPrefix}" || linkPrefix="." # Add "/" to the link prefix, and empty it entirely if it ends up just "./". linkPrefix=$(echo "${linkPrefix}" | sed 's,/*$,,') test "$linkPrefix" = "." && linkPrefix="" || linkPrefix="${linkPrefix}/" # Convert the given string to HTML-escaped values (<, >, & escaped) on # stdout. # html_safe () { echo "$*" \ | sed -e 's|&|\&|g;s|<|\<|g;s|>|\>|g' } # Convert the given string to HTML-escaped values (<, >, & escaped) on # stdout, also adding a
to the end of each line. # html_safebr () { echo "$*" \ | sed -e 's|&|\&|g;s|<|\<|g;s|>|\>|g;s/$/
/' } allEligibleFiles=$( find . -name '*~' -prune -o -type f -name '*.c' \ -exec grep -FL '!NOINDEX' /dev/null '{}' ';' ) ctagsOutput=$( echo "${allEligibleFiles}" \ | ctags -nRf- -L- --c-types=f \ | sed 's/ .\// /;s/;" .*$//' ) sourceFiles=$(echo "${ctagsOutput}" | cut -d ' ' -f 2 | sort | uniq) echo '' echo 'Source Code Index' echo '' echo '

Source Code Index

' echo '

' echo '

File Listing

' echo '

' for sourceFile in ${sourceFiles}; do sourceDir="${sourceFile##*/}" test "${sourceDir}" = "${sourceFile}" && sourceDir="." functionPrototypes=$( cproto -f1 -I. -Isrc/include -I"${sourceDir}" "${sourceFile}" 2>/dev/null \ | sed -n 's/^.*[ *]\([^ *(]*\)(.*$/\1/p' ) fileHeaderComment=$( sed -n -e '1,/\*\//{/\/\*/,/\*\//{s/^[\/ *]//;s/^\*[\/]*//;p;};}' \ < "${sourceFile}" ) fileShortDescription=$(echo "${fileHeaderComment}" | sed -n '1,/^ *$/{/^ *[^ ]*/p;}') fileLongDescription=$(echo "${fileHeaderComment}" | sed '1,/^ *$/d') echo '


' echo '

' echo '' echo '' echo '' echo '
' echo ''"${sourceFile}"' - '"$(html_safe "${fileShortDescription}")"'

' echo '

[View File]

' echo '

' html_safebr "${fileLongDescription}" echo '

' if [ -n "${functionPrototypes}" ]; then echo '

Functions defined:

' echo '

' fi echo '

[' echo 'Top |' echo 'To Do |' echo 'Functions ]

' done echo '

Function Listing

' echo '

' # shellcheck disable=SC2034 echo "${ctagsOutput}" | while read -r functionName sourceFile sourceLineNo restOfLine; do functionPrototype=$( sed -n "${sourceLineNo},/{/p" < "${sourceFile}" \ | tr '\n' ' ' \ | tr -d '{' ) lastCommentOpenLineNo=$(sed -n '1,'"${sourceLineNo}"'{/\/\*/=;}' < "${sourceFile}" | sed -n '$p') test -n "${lastCommentOpenLineNo}" || lastCommentOpenLineNo=1 lastCommentCloseLineNo=$(sed -n '1,'"${sourceLineNo}"'{/}/=;}' < "${sourceFile}" | sed -n '$p') test -n "${lastCommentCloseLineNo}" || lastCommentCloseLineNo=1 functionHeaderComment=$( sed -n -e \ "${lastCommentOpenLineNo},"'/\*\//{h;s/^[\/ *]//;s/^\*[\/]*//;p;x;/\*\//q;}' \ < "${sourceFile}" ) test "${lastCommentOpenLineNo}" -le "${lastCommentCloseLineNo}" && functionHeaderComment="" echo '


' echo '

' echo ''"${functionName}"'' \ '['"${sourceFile}"']' echo '

' echo '

'"$(html_safe "${functionPrototype}")"'

' echo '

' html_safebr "${functionHeaderComment}" echo '

' echo '

[' echo 'Top |' echo 'To Do |' echo 'Files ]

' done echo '

To Do Listing

' echo '