#!/bin/sh # TODO: libmanpage.sh and manpages.sh duplicate a lot of logic set -e export LC_ALL=C SECTIONS="1 2 3 4 5 6 7 8 9" RELEASES="current nightly" if [ -z ${URL+x} ]; then URL=https://sortix.org/man/ fi if [ -z ${NIGHTLY_RELEASE_SITE+x} ]; then NIGHTLY_RELEASE_SITE=https://pub.sortix.org/sortix/release fi if [ -z ${SITE+x} ]; then SITE=../ fi if [ -z ${SUBDIR+x} ]; then SUBDIR=man fi if [ -z ${OFFICIAL+x} ]; then OFFICIAL="$SITE" fi if [ -z ${TEMPLATE+x} ]; then TEMPLATE="$SITE" fi if [ -z ${RELEASE+x} ]; then RELEASE="current" fi if [ -z ${RELEASE_STRING+x} ]; then if [ "$RELEASE" = current ]; then RELEASE_STRING="Sortix" else RELEASE_STRING="Sortix $RELEASE" fi fi if [ ! -e "ports.list" ]; then echo "$0: No ports.list in the current directory" >&2 exit 1 fi backwards() { echo "$1" | tr -cd / | sed 's,/,../,g' } tositeofficial() { BACKWARDS=$(backwards "$1") case "$OFFICIAL" in http*) echo "$OFFICIAL" ;; *) echo "$BACKWARDS$OFFICIAL" ;; esac } tositeroot() { echo "$(backwards "$1")$SITE" } frontpage() { tositeofficial "$1" | sed 's/^$/./g' } begin_html() { cat "$TEMPLATE/header.html" | sed "s|@title@|$1|g" } header() { cat << EOF

$1

EOF } section() { cat << EOF

$1

EOF } bp() { echo "

" } ep() { echo "

" } link() { cat << EOF $2$3
EOF } end_html() { cat "$TEMPLATE/footer.html" } finalize_html_stdout() { sed -e "s,@root@,$(tositeroot "$1"),g" \ -e "s,@official@,$(tositeofficial "$1"),g" \ -e "s,@frontpage@,$(frontpage "$1"),g" \ -e "s,@year@,$(date +%Y),g" } finalize_html() { if [ "$VERBOSE" = 1 ]; then echo "$1" >&2 fi finalize_html_stdout "$1" > "$1" } section_name() { case "$1" in 1) echo "General Commands Manual";; 2) echo "System Calls Manual";; 3) echo "Library Functions Manual";; 4) echo "Device Drivers Manual";; 5) echo "File Formats Manual";; 6) echo "Games Manual";; 7) echo "Miscellaneous Information Manual";; 8) echo "System Manager's Manual";; 9) echo "Kernel Developer's Manual";; esac } # TODO: If the header name contains %, or such, should it be escaped? Maybe that # is not actually needed. Probably should. Happens in mdoc(7). # %25 is the escaped % sign. # TODO: https://sortix.org/man/man7/man.7.html#br and https://sortix.org/man/man7/man.7.html#BR is a collision, dammit. # TODO: This doesn't work for headers in manual pages like addr2line(1) that # doesn't use mdoc, so the sections don't have id attributes. selflink() { python3 -c ' import re import sys id_map = {} first_pass = [] for line in sys.stdin.readlines(): result = "" while True: match = re.search("(.*?)]*)\")?>(.*?)(.*)", line, flags=re.DOTALL) if match is None: result += line break lead = match.group(1) hl = match.group(2) oldid = match.group(4) h = match.group(5) rest = match.group(6) id = h.lower().replace(" ", "-"); if oldid is not None: id_map[oldid] = id result += lead + "" + h + "" line = rest first_pass.append(result) for line in first_pass: result = "" while True: match = re.search("(.*?)]*)\">(.*?)(.*)", line, flags=re.DOTALL) if match is None: result += line break lead = match.group(1) id = match.group(2) text = match.group(3) rest = match.group(4) if id in id_map: id = id_map[id] result += lead + "" + text + "" line = rest print(result, end="") ' } see_other_releases() { if [ "$2" = true ]; then echo '
' else bp echo "View in release:" fi for OTHER_RELEASE in $RELEASES; do if [ "$RELEASE" = "$OTHER_RELEASE" ]; then OTHER_RELEASE_URL=$(backwards "$1")"$1" elif [ "$OTHER_RELEASE" = nightly ] || [ "$OTHER_RELEASE" = volatile ]; then OTHER_RELEASE_URL="$NIGHTLY_RELEASE_SITE/$OTHER_RELEASE/man/$1" elif [ "$OTHER_RELEASE" = current ]; then OTHER_RELEASE_URL=$(tositeofficial "$1")"man/$1" else OTHER_RELEASE_URL=$(tositeofficial "$1")"release/$OTHER_RELEASE/man/$1" fi if [ "$OTHER_RELEASE" = "$RELEASE" ]; then printf ' %s' "$OTHER_RELEASE_URL" "$OTHER_RELEASE" else printf ' %s' "$OTHER_RELEASE_URL" "$OTHER_RELEASE" fi done if [ "$2" = true ]; then echo '
' else ep fi } see_stable() { if [ "$2" = true ]; then see_other_releases "$@" fi case "$RELEASE" in current) if [ "$2" != true ]; then see_other_releases "$@" fi ;; *dev* | nightly | volatile) if [ "$2" = true ]; then header "$RELEASE_STRING manual" else see_other_releases "$@" fi bp cat << EOF This manual documents $RELEASE_STRING, a development build that has not been officially released. You can instead view this document in the latest official manual. EOF ep ;; *) if [ "$2" = true ]; then header "$RELEASE_STRING manual" else see_other_releases "$@" fi bp cat << EOF This manual documents $RELEASE_STRING. You can instead view this document in the latest official manual. EOF ep ;; esac } undocumented_see_also() { (cat && echo "../man1/man.1.html") | sort | (while read FILE; do NAME=$(expr x"$FILE" : x'.*/\([^/]*\)\.[0-9]\.html$') SECTION=$(expr x"$FILE" : x'.*\.\([0-9]\)\.html$') printf ".Xr $NAME $SECTION /" done) | sed -e 's| /$|\\|' -e 's|/|,\\|g' | tr '/' ',' | tr '\\' '\n' } echo "generating index" (begin_html "$RELEASE_STRING manual page index" header "$RELEASE_STRING manual page index" see_stable "" section "Introductory manual pages" "introductory" bp link "man7/installation.7.html" "installation(7)" link "man7/upgrade.7.html" "upgrade(7)" link "man7/user-guide.7.html" "user-guide(7)" link "man7/development.7.html" "development(7)" link "man7/cross-development.7.html" "cross-development(7)" if [ -f "man7/following-development.7" ]; then link "man7/following-development.7.html" "following-development(7)" fi if [ -f "man7/porting.7" ]; then link "man7/porting.7.html" "porting(7)" fi ep section "Sortix manual pages" "system" bp link "system.html" "System manual pages" for section in $SECTIONS; do link "system.html#$section" "System Section $section - $(section_name $section)" done section "All manual pages" "all" link "all.html" "All manual pages" for section in $SECTIONS; do link "man$section/" "Section $section - $(section_name $section)" done ep section "Ports manual pages" "ports" bp cat ports.list | sort | while read port; do if [ -s "$port.list" ]; then link "$port.html" "$port" else link "$port.html" "$port" " (no manual pages)" fi done ep end_html) | finalize_html index.html (echo system && cat ports.list) | while read port; do echo "generating index for $port" (if [ "$port" = system ]; then prettyport="System"; else prettyport=$port; fi begin_html "$prettyport manual pages" && header "$prettyport manual pages" && see_stable "$port.html" section_not_begun=true for section in $SECTIONS; do section_not_begun=true mkdir -p "man$section" grep -E "^/share/man/man$section/.*\.$section$" "$port.list" | sort | while read manpage; do if $section_not_begun; then section "Section $section - $(section_name $section)" "$section" bp section_not_begun=false fi manpage=$(basename -- "$manpage") name=$(echo "$manpage" | sed "s/\.$section$//") link "man$section/$manpage.html" "$name($section)" if [ "x$port" = xsystem ]; then mandoc -Tlint "man$section/$manpage" 1>&2 || true fi done if ! $section_not_begun; then ep fi done if [ ! -s "$port.list" ]; then echo "

$prettyport contains no manual pages.

" fi end_html) | finalize_html $port.html done for section in $SECTIONS; do echo "generating index for section $section" mkdir -p "man$section" (begin_html "Section $section - $(section_name $section)" && header "Section $section - $(section_name $section)" && see_stable "man$section/" ls man$section | sort | grep -E "\.$section$" | while read manpage; do manpage=$(basename -- "$manpage") name=$(echo "$manpage" | sed "s/\.$section$//") link "$manpage.html" "$name($section)" done if ! ls man$section | grep -Eq "\.$section$"; then echo "

Section $section contains no manual pages.

" fi end_html) | finalize_html man$section/index.html done for section in $SECTIONS; do find man$section -type f | sort | grep -E "\.$section$" | while read manpage; do filename=$(basename -- "$manpage") name=$(expr "x$filename" : 'x\(.*\)\.[^.]*') echo generating $manpage (begin_html "$name($section)" see_stable "$manpage.html" true mandoc -Thtml -Ofragment,man=../man%S/%N.%S.html "$manpage" | selflink end_html) | finalize_html "$manpage.html" done done (find . -name '*.html' | while read FILE; do grep -Eoh 'href=\"../man[[:digit:]]/[^/]+\.html\"' "$FILE" || true done) | sort -u | grep -Eo 'man[[:digit:]]/[^/]+\.html' | sed 's/\.html$//' | while read manpage; do if ! [ -e "$manpage" ]; then echo undocumented: $manpage filename=$(basename -- "$manpage") name=$(expr "x$filename" : 'x\(.*\)\.[^.]*') NAME=$(echo "$filename" | tr '[:lower:]' '[:upper:]') section=$(expr "x$manpage" : 'x.*\.\([^.]*\)') (begin_html "$name($section)" see_stable "$manpage.html" true (cat man7/undocumented.7 | grep -Ev '^\.Xr man 1$' | sed -e "s/UNDOCUMENTED/$NAME/g" -e "s/undocumented/$name/g" && grep -rl --include='*.html' -- "../$manpage.html" . | undocumented_see_also) | mandoc -Thtml -Oman=../man%S/%N.%S.html | selflink end_html) | finalize_html "$manpage.html" fi done echo "generating index for all" (begin_html "All manual pages for Sortix" header "All manual pages for Sortix" see_stable "all.html" for section in $SECTIONS; do section "Section $section" "$section" bp ls man$section | sort | grep -E "\.$section$" | while read manpage; do name=$(echo "$manpage" | sed "s/\.$section$//") link "man$section/$manpage.html" "$name($section)" done ep done end_html) | finalize_html all.html