399 lines
10 KiB
Bash
Executable file
399 lines
10 KiB
Bash
Executable file
#!/bin/sh
|
|
set -e
|
|
|
|
export LC_ALL=C
|
|
SECTIONS="1 2 3 4 5 6 7 8 9"
|
|
if [ -z ${SORTIX_SITE_OFFICIAL+x} ]; then
|
|
SORTIX_SITE_OFFICIAL="https://sortix.org/"
|
|
fi
|
|
if [ -z ${SORTIX_RELEASE_SITE+x} ]; then
|
|
SORTIX_RELEASE_SITE="https://pub.sortix.org/sortix/release"
|
|
fi
|
|
if [ -z ${MANHTML_TO_SITE_ROOT+x} ]; then
|
|
MANHTML_TO_SITE_ROOT=.
|
|
fi
|
|
if [ -z ${MANHTML_TEMPLATE+x} ]; then
|
|
MANHTML_TEMPLATE="$(dirname -- "$(realpath -- "$(which -- "$0")")")"
|
|
fi
|
|
if [ -z ${MANHTML_RELEASES+x} ]; then
|
|
MANHTML_RELEASES="current nightly"
|
|
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 [ $# -lt 1 ]; then
|
|
echo "Usage: $0 mandir $#" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -e "$1/ports.list" ]; then
|
|
echo "$0: No ports.list in $1" >&2
|
|
exit 1
|
|
fi
|
|
|
|
cd "$1"
|
|
|
|
backwards() {
|
|
echo "$1" | tr -cd / | sed 's,/,../,g'
|
|
}
|
|
|
|
tositeofficial() {
|
|
BACKWARDS=$(backwards "$1")
|
|
case "$SORTIX_SITE_OFFICIAL" in
|
|
http*) echo "$SORTIX_SITE_OFFICIAL" ;;
|
|
*) echo "$BACKWARDS$SORTIX_SITE_OFFICIAL" ;;
|
|
esac
|
|
}
|
|
|
|
tositeroot() {
|
|
echo "$(backwards "$1")$MANHTML_TO_SITE_ROOT"
|
|
}
|
|
|
|
frontpage() {
|
|
tositeofficial "$1" | sed 's/^$/./g'
|
|
}
|
|
|
|
begin_html() {
|
|
cat "$MANHTML_TEMPLATE/header.html" | sed "s|@title@|$1|g"
|
|
}
|
|
|
|
header() {
|
|
cat << EOF
|
|
<h1>$1</h1>
|
|
EOF
|
|
}
|
|
|
|
section() {
|
|
cat << EOF
|
|
<h2 id="$2"><a href="#$2">$1</a></h2>
|
|
EOF
|
|
}
|
|
|
|
bp() {
|
|
echo "<p>"
|
|
}
|
|
|
|
ep() {
|
|
echo "</p>"
|
|
}
|
|
|
|
link() {
|
|
cat << EOF
|
|
<a href="$1">$2</a>$3<br />
|
|
EOF
|
|
}
|
|
|
|
end_html() {
|
|
cat "$MANHTML_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: This doesn't work for headers in manual pages like addr2line(1) that
|
|
# doesn't use mdoc(7), 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("(.*?)<h(.)( id=\"([^\">]*)\")?>(.*?)</h.>(.*)", 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(" ", "-").replace("%", "%25");
|
|
if oldid is not None:
|
|
id_map[oldid] = id
|
|
result += lead + "<h" + hl + " id=\"" + id + "\"><a href=\"#" + id + "\">" + h + "</a></h" + hl + ">"
|
|
line = rest
|
|
first_pass.append(result)
|
|
for line in first_pass:
|
|
result = ""
|
|
while True:
|
|
match = re.search("(.*?)<a class=\"link-sec\" href=\"#([^\">]*)\">(.*?)</a>(.*)", 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 + "<a class=\"link-sec\" href=\"#" + id + "\">" + text + "</a>"
|
|
line = rest
|
|
print(result, end="")
|
|
'
|
|
}
|
|
|
|
see_other_releases() {
|
|
if [ "$2" = true ]; then
|
|
echo '<div style="text-align: right; float: right;">'
|
|
else
|
|
bp
|
|
echo "View in release:"
|
|
fi
|
|
for OTHER_RELEASE in $MANHTML_RELEASES; do
|
|
if [ "$RELEASE" = "$OTHER_RELEASE" ]; then
|
|
OTHER_RELEASE_URL=$(backwards "$1")"$1"
|
|
elif [ "$OTHER_RELEASE" = current ]; then
|
|
OTHER_RELEASE_URL=$(tositeofficial "$1")"man/$1"
|
|
elif echo "$OTHER_RELEASE" | grep -Eq '^[0-9]+.[0-9]+$'; then
|
|
OTHER_RELEASE_URL=$(tositeofficial "$1")"release/$OTHER_RELEASE/man/$1"
|
|
else
|
|
OTHER_RELEASE_URL="$SORTIX_RELEASE_SITE/$OTHER_RELEASE/man/$1"
|
|
fi
|
|
if [ "$OTHER_RELEASE" = "$RELEASE" ]; then
|
|
printf ' <b><a href="%s">%s</a></b>' "$OTHER_RELEASE_URL" "$OTHER_RELEASE"
|
|
else
|
|
printf ' <a href="%s">%s</a>' "$OTHER_RELEASE_URL" "$OTHER_RELEASE"
|
|
fi
|
|
done
|
|
if [ "$2" = true ]; then
|
|
echo '</div>'
|
|
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
|
|
<a href="@official@man/$1">this document in the latest official manual</a>.
|
|
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
|
|
<a href="@official@man/$1">this document in the latest official manual</a>.
|
|
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 manhtml 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 manhtml 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 "<p>$prettyport contains no manual pages.</p>"
|
|
fi
|
|
end_html) | finalize_html $port.html
|
|
done
|
|
|
|
for section in $SECTIONS; do
|
|
echo "Generating manhtml 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 "<p>Section $section contains no manual pages.</p>"
|
|
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 manhtml $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 "Generating undocumented manhtml for $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 -F -- "../$manpage.html" . |
|
|
grep -E '\.html$' |
|
|
undocumented_see_also) |
|
|
mandoc -Thtml -Oman=../man%S/%N.%S.html | selflink
|
|
end_html) | finalize_html "$manpage.html"
|
|
fi
|
|
done
|
|
|
|
echo "Generating manhtml 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
|