about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatryk Niedźwiedziński <pniedzwiedzinski19@gmail.com>2021-06-15 23:30:05 +0200
committerPatryk Niedźwiedziński <pniedzwiedzinski19@gmail.com>2021-06-15 23:30:05 +0200
commitd831434e95c6a3b33a8af04e630d34f078d26e4f (patch)
tree93965830662798a4c8674634110eac88bdb3a6ab
downloadspiewnik-d831434e95c6a3b33a8af04e630d34f078d26e4f.tar.gz
spiewnik-d831434e95c6a3b33a8af04e630d34f078d26e4f.zip
Init
-rw-r--r--.gitignore7
-rw-r--r--README.md16
-rw-r--r--all.do1
-rwxr-xr-xbin/redo116
-rwxr-xr-xbin/redo-always20
-rwxr-xr-xbin/redo-dot63
-rwxr-xr-xbin/redo-ifchange540
-rwxr-xr-xbin/redo-ifcreate35
-rwxr-xr-xbin/redo-ood30
-rwxr-xr-xbin/redo-sources27
-rwxr-xr-xbin/redo-stamp29
-rwxr-xr-xbin/redo-targets25
-rwxr-xr-xbin/redo-whichdo79
-rw-r--r--clean.do1
-rw-r--r--index.ms.do8
-rw-r--r--man/man1/redo-always.192
-rw-r--r--man/man1/redo-dot.173
-rw-r--r--man/man1/redo-ifchange.1159
-rw-r--r--man/man1/redo-ifcreate.194
-rw-r--r--man/man1/redo-ood.143
-rw-r--r--man/man1/redo-sources.149
-rw-r--r--man/man1/redo-stamp.191
-rw-r--r--man/man1/redo-targets.145
-rw-r--r--man/man1/redo-whichdo.1127
-rw-r--r--man/man1/redo.1226
-rw-r--r--piosenki/1-juz-rozpalilo-sie-ognisko.txt40
-rw-r--r--piosenki/2-plonie-ognisko-i-szumia-knieje.txt60
-rw-r--r--piosenki/3-wspominajka.txt39
-rw-r--r--piosenki/czuwajcie.txt48
-rw-r--r--piosenki/kantyczka-z-lotu-ptaka.txt126
-rw-r--r--piosenki/maly_oboz.txt47
-rw-r--r--piosenki/wedrowanie.txt93
-rw-r--r--piosenki/zielony-mundur.txt70
-rw-r--r--piosenki/zielony-plomien.txt45
-rw-r--r--source.tmac5
-rw-r--r--spiewnik.idx.do3
-rw-r--r--spiewnik.ms66
-rw-r--r--spiewnik.pdf.do2
-rw-r--r--spiewnik.ps.do2
-rw-r--r--tmac.toc48
40 files changed, 2690 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..daacf49
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+.redo
+spiewnik.pdf
+spiewnik.ps
+spiewnik.idx
+spiewnik.preidx
+index.ms
+piosenki/*.ms
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e629fc7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,16 @@
+# spiewnik
+
+## Render
+
+Zainstaluj neatroff
+
+```
+export PATH="$PWD/bin:$PATH"
+redo
+```
+
+## Edytowanie
+
+Główny plik `spiewnik.ms` - ustawienia strony, marginesów, czcionki i pierwszej strony
+Wszystkie pliki `*.do` - opisują kroki do wykonania aby wyrenderować PDF
+Piosenki w `piosenki/*.txt` - Pliki z tekstami piosenek
diff --git a/all.do b/all.do
new file mode 100644
index 0000000..c88d595
--- /dev/null
+++ b/all.do
@@ -0,0 +1 @@
+redo-ifchange spiewnik.pdf
diff --git a/bin/redo b/bin/redo
new file mode 100755
index 0000000..0c76a18
--- /dev/null
+++ b/bin/redo
@@ -0,0 +1,116 @@
+#!/bin/sh -eu
+# redo – bourne shell implementation of DJB redo
+# Copyright © 2014-2021  Nils Dagsson Moskopp (erlehmann)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
+# steigern. Gelegentlich packe ich sogar einen handfesten Buffer
+# Overflow oder eine Format String Vulnerability zwischen die anderen
+# Codezeilen und schreibe das auch nicht dran.
+
+: \
+ "${REDO_JOBS_MAX:=1}" \
+ "${REDO_MKDIR:=$(command -v mkdir)}" \
+ "${REDO_RM:=$(command -v rm) -f}" \
+ "${REDO_RMDIR:=$(command -v rmdir)}" \
+ "${REDO_TMP_DIR:=$(mktemp -d /tmp/redo.XXXXXXX)}" \
+
+export \
+ REDO_JOBS_MAX \
+ REDO_MKDIR \
+ REDO_RM \
+ REDO_RMDIR \
+ REDO_TMP_DIR \
+
+while [ $# != 0 ]; do
+ case "${1}" in
+  '-d'|'--debug')
+   export REDO_DEBUG='1'
+  ;;
+  '--debug-jobs')
+   export REDO_DEBUG_JOBS='1'
+  ;;
+  '--debug-locks')
+   export REDO_DEBUG_LOCKS='1'
+  ;;
+  '-h'|'--help')
+   printf >&2 \
+"Usage: redo [OPTIONS] [TARGETS...]
+
+  -d, --debug          print dependency checks as they happen
+      --debug-jobs     print messages about job management
+      --debug-locks    print messages about file locking
+  -h, --help           print usage instructions and exit
+  -j [n], --jobs [n]   execute at most [n] dofiles in parallel
+      --version        print version information and exit
+  -x, --xtrace         print commands as they are executed (variables expanded)
+
+Report bugs to <nils+redo@dieweltistgarnichtso.net>.
+"
+   exit 0
+  ;;
+  '-j'|'--jobs')
+   shift; REDO_JOBS_MAX=${1}
+  ;;
+  '--version')
+   printf >&2 \
+"redo 4.0.4
+Copyright © 2014-2021 Nils Dagsson Moskopp (erlehmann)
+
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+"
+   exit 0
+  ;;
+  '-x'|'--xtrace')
+   export REDO_XTRACE='1'
+  ;;
+  *)
+   REDO_HAS_TARGETS='1'
+   export REDO_TARGET=''
+   # If this is build directory, create .redo database directory.
+   case "${REDO_BASE:-}" in
+    '')
+     export REDO_DEPTH=""
+     export REDO_PID="${PPID}"
+     export REDO_BASE="${PWD}"
+     export REDO_DIR="$REDO_BASE/.redo"
+     [ -d "$REDO_DIR" ] || LANG=C "${REDO_MKDIR}" -p "$REDO_DIR"
+   esac
+   break
+  ;;
+ esac
+ shift
+done
+
+[ "${REDO_HAS_TARGETS:-}" = "1" ] || exec redo all
+
+case "${REDO_JOBS_PIPE:-}" in
+ '')
+  export REDO_JOBS_PIPE="${REDO_TMP_DIR}"/jobs_pipe
+  mkfifo "${REDO_JOBS_PIPE}"
+  exec 9<> "${REDO_JOBS_PIPE}"
+  >&9 seq $(( REDO_JOBS_MAX - 1 )) &
+ ;;
+esac
+
+set +e
+redo-ifchange "$@"
+EXITCODE=${?}
+set -e
+
+wait
+
+case ${#REDO_DEPTH} in
+ 0)
+  LANG=C ${REDO_RM} "${REDO_JOBS_PIPE}"
+  LANG=C ${REDO_RMDIR} "${REDO_TMP_DIR}"
+ ;;
+esac
+
+exit "${EXITCODE}"
diff --git a/bin/redo-always b/bin/redo-always
new file mode 100755
index 0000000..f6b088a
--- /dev/null
+++ b/bin/redo-always
@@ -0,0 +1,20 @@
+#!/bin/sh
+# redo-always – bourne shell implementation of DJB redo
+# Copyright © 2014-2016  Nils Dagsson Moskopp (erlehmann)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
+# steigern. Gelegentlich packe ich sogar einen handfesten Buffer
+# Overflow oder eine Format String Vulnerability zwischen die anderen
+# Codezeilen und schreibe das auch nicht dran.
+
+set -eu
+
+# The following code adds a dependency that is impossible to satisfy.
+LANG=C mkdir -p $(LANG=C dirname "$REDO_DIR/$REDO_TARGET".dependencies_ne.tmp)
+printf '%s\t%s\t%s\n' "/dev/null" "0" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  -" >> \
+ "$REDO_DIR"/"$REDO_TARGET".dependencies.tmp
diff --git a/bin/redo-dot b/bin/redo-dot
new file mode 100755
index 0000000..5526f67
--- /dev/null
+++ b/bin/redo-dot
@@ -0,0 +1,63 @@
+#!/bin/sh
+# redo-dot – bourne shell implementation of DJB redo
+# Copyright © 2018  Nils Dagsson Moskopp (erlehmann)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
+# steigern. Gelegentlich packe ich sogar einen handfesten Buffer
+# Overflow oder eine Format String Vulnerability zwischen die anderen
+# Codezeilen und schreibe das auch nicht dran.
+
+# Prints redo dependencies in dot(1) format. Usage is similar to this:
+# redo-dot |sed s%"$(pwd)"/%%g >deps.dot; dot deps.dot -Tpng >deps.png
+
+[ -d .redo ] || exit 1
+
+pattern=${1:-*}
+
+match() case "${1}" in
+ ${pattern}) : ;;
+ *) ! : ;;
+esac
+
+_escape() {
+ printf '%s' "$1" | sed 's/\\/\\\\/g;s/\"/\\\"/g'
+}
+
+IFS='
+	'
+cat <<EOF
+digraph redo {
+concentrate=true;rankdir=LR;ranksep=2;splines=polyline
+node[shape=rectangle]
+EOF
+printf 'subgraph dependencies { edge[style=solid,minlen=2]\n'
+for depfile in $(find .redo -name '*.dependencies'); do
+ while read -r dependency ctime md5sum; do
+  file="${depfile%.dependencies}"; file="${file#.redo}"
+  match "${file}" || match "${dependency}" || continue
+  case "$ctime" in
+   0) printf '"%s" [style=bold]\n' "$(_escape "${file}")"; break ;;
+   *) printf '"%s" -> "%s"\n' "$(_escape "${file}")" "$(_escape "${dependency}")" ;;
+  esac
+ done <"$depfile"
+done
+printf '}\nsubgraph dependencies_ne { edge[style=dotted,minlen=1]\n'
+for depfile in $(find .redo -name '*.dependencies_ne'); do
+ while read -r dependency_ne; do
+  file="${depfile%.dependencies_ne}"; file="${file#.redo}";
+  match "${file}" || match "${dependency_ne}" || continue
+  printf '"%s" -> "%s"\n' "$(_escape "${file}")" "$(_escape "${dependency_ne}")"
+ done <"$depfile"
+done
+printf '}\n'
+for stampfile in $(find .redo -name '*.stamp'); do
+ file="${stampfile%.stamp}"; file="${file#.redo}"
+ match "${file}" || continue
+ printf '"%s" [style=dashed]\n' "$(_escape "${file}")"
+done
+printf '}\n'
diff --git a/bin/redo-ifchange b/bin/redo-ifchange
new file mode 100755
index 0000000..2dad8ec
--- /dev/null
+++ b/bin/redo-ifchange
@@ -0,0 +1,540 @@
+#!/bin/sh -u
+# redo-ifchange – bourne shell implementation of DJB redo
+# Copyright © 2014-2021  Nils Dagsson Moskopp (erlehmann)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
+# steigern. Gelegentlich packe ich sogar einen handfesten Buffer
+# Overflow oder eine Format String Vulnerability zwischen die anderen
+# Codezeilen und schreibe das auch nicht dran.
+
+: \
+ "${REDO_JOBS_MAX:=1}" \
+ "${REDO_MKDIR:=$(command -v mkdir)}" \
+ "${REDO_MV:=$(command -v mv)}" \
+ "${REDO_RM:=$(command -v rm) -f}" \
+ "${REDO_RMDIR:=$(command -v rmdir)}" \
+ "${REDO_SLEEP:=$(command -v sleep)}" \
+ "${REDO_TMP_DIR:=$(mktemp -d /tmp/redo.XXXXXXX)}" \
+ "${REDO_LOCKS_DIR:=${REDO_TMP_DIR}/locks}" \
+ "${REDO_CANARY:=${REDO_TMP_DIR}/canary}"
+
+export \
+ REDO_JOBS_MAX \
+ REDO_MKDIR \
+ REDO_MV \
+ REDO_RM \
+ REDO_RMDIR \
+ REDO_SLEEP \
+ REDO_TMP_DIR \
+ REDO_LOCKS_DIR \
+ REDO_CANARY
+
+case ${REDO_STAT:-} in
+ '')
+  if (LANG=C stat -c%Y "$0" >/dev/null 2>&1); then
+   REDO_STAT=$(command -v stat)
+  elif (LANG=C gstat -c%Y "$0" >/dev/null 2>&1); then
+   REDO_STAT=$(command -v gstat)
+  else
+   >&2 printf 'redo needs BusyBox stat(1), GNU stat(1) or gstat(1).
+'
+   exit 1
+  fi
+esac
+export REDO_STAT
+
+case ${REDO_MD5SUM:-} in
+ '')
+  if command -v md5sum >/dev/null && [ "$(LANG=C : | md5sum)" = "d41d8cd98f00b204e9800998ecf8427e  -" ]; then
+   REDO_MD5SUM=$(command -v md5sum)
+  elif command -v gmd5sum >/dev/null && [ "$(LANG=C : | gmd5sum)" = "d41d8cd98f00b204e9800998ecf8427e  -" ]; then
+   REDO_MD5SUM=$(command -v gmd5sum)
+  elif command -v openssl >/dev/null && [ "$(LANG=C : | openssl md5 -r)" = "d41d8cd98f00b204e9800998ecf8427e *stdin" ]; then
+   REDO_MD5SUM="$(command -v openssl) md5 -r"
+  elif command -v md5 >/dev/null && [ "$(LANG=C : | md5)" = "d41d8cd98f00b204e9800998ecf8427e" ]; then
+   REDO_MD5SUM="$(command -v md5)"
+  else
+   >&2 printf 'redo needs BusyBox md5sum(1), GNU md5sum(1) or gmd5sum(1), openssl(1) or md5(1).
+'
+   exit 1
+  fi
+esac
+export REDO_MD5SUM
+
+: \
+ "${REDO_BOLD:=}" \
+ "${REDO_PLAIN:=}" \
+ "${REDO_COLOR_SUCCESS:=}" \
+ "${REDO_COLOR_FAILURE:=}"
+
+case "${TERM:-dumb}" in
+ 'dumb')
+ ;;
+ *)
+  if LANG=C tty -s; then
+   : \
+    "${REDO_BOLD:=$(printf '\033[1m')}" \
+    "${REDO_PLAIN:=$(printf '\033[m')}" \
+    "${REDO_COLOR_SUCCESS:=$(printf '\033[36m')}" \
+    "${REDO_COLOR_FAILURE:=$(printf '\033[33m')}"
+  fi
+ ;;
+esac
+export \
+ REDO_BOLD \
+ REDO_PLAIN \
+ REDO_COLOR_SUCCESS \
+ REDO_COLOR_FAILURE
+
+_echo_debug_message() {
+ printf '%s' "$@" >&2
+}
+
+case ${REDO_DEBUG:-} in
+ 1) ;;
+ *) alias _echo_debug_message=:
+esac
+
+_echo_debug_jobs_message() {
+ printf '%s' "$@" >&2
+}
+
+case ${REDO_DEBUG_JOBS:-} in
+ 1) ;;
+ *) alias _echo_debug_jobs_message=:
+esac
+
+_echo_debug_locks_message() {
+ printf '%s' "$@" >&2
+}
+
+case ${REDO_DEBUG_LOCKS:-} in
+ 1) ;;
+ *) alias _echo_debug_locks_message=:
+esac
+
+_exit_if_canary_dead() {
+ if [ -e "${REDO_CANARY:-}" ]; then
+ printf "${REDO_COLOR_FAILURE}redo %s${REDO_BOLD}%s: canary detected, aborting.${REDO_PLAIN}\n" \
+  "${REDO_DEPTH:-}" "${target#$REDO_BASE/}" >&2
+  exit 1
+ fi
+}
+
+_kill_canary() {
+ [ -n "${REDO_CANARY:-}" ] && \
+  : >"${REDO_CANARY}"
+}
+
+_exit_sigint() {
+ printf "${REDO_COLOR_FAILURE}redo %s${REDO_BOLD}%s: received SIGINT.${REDO_PLAIN}\n" \
+  "${REDO_DEPTH:-}" "${target#$REDO_BASE/}" >&2
+ _kill_canary
+ exit 1
+}
+
+trap _exit_sigint INT
+
+_add_dependency() {
+ parent=$1 dependency=$2
+ # Do not record circular dependencies.
+ [ "$parent" = "$dependency" ] && exit 1
+ local base; _dirsplit "$parent"
+ [ -d "$REDO_DIR/$dir" ] || LANG=C "${REDO_MKDIR}" -p "$REDO_DIR/$dir"
+ ctime_md5sum=$(
+  LANG=C $REDO_STAT -c%Y "$dependency"
+  LANG=C $REDO_MD5SUM < "$dependency"
+ )
+ ctime=${ctime_md5sum%%'
+'*}
+ md5sum=${ctime_md5sum#*'
+'}
+ printf "%s\t${ctime}\t${md5sum}\n" "${dependency}" >> \
+  "$REDO_DIR"/"$parent".dependencies.tmp
+ local base; _dirsplit "$dependency"
+ [ -d "$REDO_DIR/$dir" ] || LANG=C "${REDO_MKDIR}" -p "$REDO_DIR/$dir"
+ printf "${md5sum}\n" >"$REDO_DIR/$dependency".md5sum
+}
+
+_lock_acquire() {
+ lock_name=${1}
+ lock_dir="${REDO_LOCKS_DIR}${lock_name}"
+ lock_tries=1
+ lock_wait_total=0
+ while LANG=C "${REDO_MKDIR}" -p "${lock_dir%/*}" && ! LANG=C "${REDO_MKDIR}" "${lock_dir}" >/dev/null 2>&1; do
+  _exit_if_canary_dead
+  _echo_debug_locks_message "wait for lock	ppid: ${PPID}	tried: ${lock_tries}	waited: >${lock_wait_total}s	locked: ${lock_name}	target: ${REDO_TARGET}
+"
+  lock_wait=$(( PPID % ( REDO_JOBS_MAX + 1 ) + 1 )).$(( REDO_JOBS_MAX - 1 ))
+  _jobs_count_decrease "lock sleep"
+  LANG=C "${REDO_SLEEP}" "${lock_wait}"
+  _jobs_count_increase "lock awake"
+  lock_tries=$(( lock_tries + 1 ))
+  lock_wait_total=$(( lock_wait_total + ${lock_wait%.*} ))
+ done
+ _echo_debug_locks_message "acquired lock	ppid: ${PPID}	tried: ${lock_tries}	waited: >${lock_wait_total}s	locked: ${lock_name}	target: ${REDO_TARGET}
+"
+}
+
+_lock_release() {
+ lock_name=${1}
+ lock_dir="${REDO_LOCKS_DIR}${lock_name}"
+ _echo_debug_locks_message "release tried	ppid: ${PPID}	tried: 1	waited: ~0s	locked: ${lock_name}	target: ${REDO_TARGET}
+"
+ LANG=C [ -d "${lock_dir}" ] && ${REDO_RMDIR} -p "${lock_dir}" >/dev/null 2>&1
+ _echo_debug_locks_message "released lock	ppid: ${PPID}	tried: 1	waited: ~0s	locked: ${lock_name}	target: ${REDO_TARGET}
+"
+}
+
+_jobs_count_increase() {
+ _echo_debug_jobs_message "job awaiting	reason: ${1}
+"
+ <&9 read -r _
+ _echo_debug_jobs_message "job starting	reason: ${1}
+"
+}
+
+_jobs_count_decrease() {
+ _echo_debug_jobs_message "job finished	reason: ${1}
+"
+ >&9 echo
+}
+
+case ${REDO_JOBS_MAX} in
+ 1)
+  alias \
+   _jobs_count_increase=: \
+   _jobs_count_decrease=:
+ ;;
+esac
+
+_dependencies_ne_uptodate() {
+ target=$1
+ # If no non-existence dependencies exist, they are by definition up to date.
+ if [ ! -s "$REDO_DIR/$target".dependencies_ne ]; then
+  _echo_debug_message "${target#$REDO_BASE/} has no non-existence dependencies.
+"
+  rv=0
+  return
+ fi
+ _echo_debug_message "${target#$REDO_BASE/} non-existence dependency check:
+"
+ exec 3< "$REDO_DIR/$target".dependencies_ne
+ while read -r dependency_ne <&3; do
+  _echo_debug_message "	${dependency_ne#$REDO_BASE/} should not exist "
+  # If a non-existence dependency exists, it is out of date.
+  # Dependencies, e.g. on default.do files may also be out of date.
+  # Naive implementation: Pretend target is not up to date and rebuild.
+  if [ -e "$dependency_ne" ]; then
+   _echo_debug_message "and exists.
+"
+   rv=1
+   return
+  fi
+  _echo_debug_message "and does not.
+"
+ done
+ exec 3>&-
+ _echo_debug_message "${target#$REDO_BASE/} non-existence dependencies up to date.
+"
+ rv=0
+ return
+}
+
+_target_uptodate() {
+ target=$1
+ # If a target is a top-level target, it is not up to date.
+ case "$REDO_TARGET" in
+  '') return 1
+ esac
+ # If a target does not exist, it is not up to date.
+ if [ ! -e "$target" ]; then
+  _echo_debug_message "$target does not exist.
+"
+  return 1
+ fi
+ [ ! -e "$REDO_DIR/$target".md5sum ] && return 1
+ _echo_debug_message "${target#$REDO_BASE/} ctime "
+ ctime_stored_actual="$(LANG=C $REDO_STAT -c%Y "$REDO_DIR/$target".md5sum "$target")"
+ ctime_stored=${ctime_stored_actual%%'
+'*}
+ ctime_actual=${ctime_stored_actual#*'
+'}
+ # faster [ $ctime_stored -ge $ctime_actual ]
+ case $(( ctime_stored - ctime_actual )) in
+  -*) ;;
+  *)
+   _echo_debug_message "unchanged.
+"
+   return 0
+  ;;
+ esac
+ _echo_debug_message "changed.
+"
+ _echo_debug_message "$target md5sum "
+ read -r md5sum_stored <"$REDO_DIR/$target".md5sum
+ IFS=' ' md5sum_actual="$(LANG=C $REDO_MD5SUM < "$target")"
+ IFS='
+	'
+ case $md5sum_stored in
+  $md5sum_actual)
+   _echo_debug_message "unchanged.
+"
+   # If stored md5sum of target matches actual md5sum, but stored
+   # ctime does not, redo needs to update stored ctime of target.
+   : >>"$REDO_DIR/$target".md5sum
+   return 0
+  esac
+ _echo_debug_message "changed.
+"
+ return 1
+}
+
+_dependencies_from_depfile() {
+ while read -r dependency ctime_stored md5sum_stored; do
+  printf "%s\n" "${dependency}"
+ done
+}
+
+_dependencies_uptodate() {
+ target=$1
+ target_depfile="$REDO_DIR/$target".dependencies
+ # If no dependencies exist, they are by definition up to date.
+ if [ ! -e "$target_depfile" ]; then
+  _echo_debug_message "	${target#$REDO_BASE/} has no dependencies.
+"
+  return 0
+ fi
+ _echo_debug_message "${target#$REDO_BASE/} dependency check:
+"
+ # If any dependency does not exist, the target is out of date.
+ IFS='
+	'
+ LANG=C $REDO_STAT -c%Y $(_dependencies_from_depfile <"$target_depfile") > \
+  "$target_depfile".ctimes 2>&- || return 1
+ exec 3< "$target_depfile".ctimes
+ exec 4< "$target_depfile"
+ while read -r ctime_actual <&3 && read -r dependency ctime_stored md5sum_stored <&4; do
+  # If a dependency of a dependency is out of date, the dependency is out of date.
+  if ( ! _dependencies_uptodate "$dependency" ); then
+   return 1
+  fi
+  # If the ctime of a dependency did not change, the dependency is up to date.
+  _echo_debug_message "	${dependency#$REDO_BASE/} ctime "
+  case $ctime_stored in
+   $ctime_actual)
+    _echo_debug_message "unchanged.
+"
+    continue
+  esac
+  # If the md5sum of a dependency did not change, the dependency is up to date.
+  _echo_debug_message "changed.
+	$dependency md5sum "
+  OLDIFS=$IFS
+  IFS=' ' md5sum_actual="$(LANG=C $REDO_MD5SUM < "$dependency")"
+  IFS=$OLDIFS
+  case $md5sum_stored in
+   $md5sum_actual)
+    _echo_debug_message "unchanged.
+"
+    continue
+  esac
+  # if both ctime and md5sum did change, the dependency is out of date.
+  _echo_debug_message "changed.
+"
+  return 1
+ done
+ exec 4>&-
+ exec 3>&-
+ _echo_debug_message "${target#$REDO_BASE/} dependencies up to date.
+"
+ # If a non-existence dependency is out of date, the target is out of date.
+ _dependencies_ne_uptodate "$target"
+ return $rv
+}
+
+_dirsplit() {
+ base=${1##*/}
+ dir=${1%"$base"}
+}
+
+_do() {
+ local dir="$1" target="$2" tmp="$3"
+ target_abspath="${PWD%/}/$target"
+ target_relpath="${target_abspath#$REDO_BASE/}"
+ # If target is not up to date or its dependencies are not up to date, build it.
+ if (
+  ! _target_uptodate "$target_abspath" || \
+  ! _dependencies_uptodate "$target_abspath"
+ ); then
+  dofile_abspath=$(
+   LANG=C redo-whichdo "${target_abspath}" \
+    |LANG=C xargs -0 \
+      sh -cu '
+dofile=${0}
+for arg; do dofile=${arg}; done
+test -e "${dofile}" && printf "%s" "${dofile}"
+'
+   )
+  ext=
+  case ${dofile_abspath} in
+   *default.*.do)
+    ext=${dofile_abspath%.do}
+    ext=.${ext#*default.}
+   ;;
+  esac
+  base=${target%$ext}
+  if [ -z "$dofile_abspath" ]; then
+   # If .do file does not exist and target exists, it is a source file.
+   if [ -e "$target_abspath" ]; then
+    _add_dependency "$REDO_TARGET" "$target_abspath"
+    # Remove dependencies and non-existence dependencies that the
+    # target file might have had. When a target that was built by
+    # redo has its dofile removed, it becomes a source file and
+    # should not be rebuilt constantly due to a missing dofile.
+    [ -e "$REDO_DIR/$target_abspath".dependencies ] && \
+     LANG=C $REDO_RM "$REDO_DIR/$target_abspath".dependencies >&2
+    [ -e "$REDO_DIR/$target_abspath".dependencies_ne ] && \
+     LANG=C $REDO_RM "$REDO_DIR/$target_abspath".dependencies_ne >&2
+    return 0
+   # If .do file does not exist and target does not exist, stop.
+   else
+    printf "${REDO_COLOR_FAILURE}redo %s${REDO_BOLD}%s: no .do file.${REDO_PLAIN}\n" \
+     "${REDO_DEPTH:-}" "${target_abspath#$REDO_BASE/}" >&2
+    exit 1
+   fi
+  fi
+  : ${REDO_DEPTH:=}
+  case ${#REDO_DEPTH} in
+   200)
+    printf "${REDO_COLOR_FAILURE}redo %s${REDO_BOLD}%s: Maximum recursion depth exceeded.${REDO_PLAIN}\n" \
+     "${REDO_DEPTH:-}" "${target_abspath#$REDO_BASE/}" >&2
+    exit 1
+  esac
+  printf '%sredo %s%s%s%s\n' \
+   "${REDO_COLOR_SUCCESS}" "$REDO_DEPTH" "${REDO_BOLD}" "$target_relpath" "${REDO_PLAIN}" >&2
+  ( _run_dofile "$target" "${base##*/}" "$tmp.tmp" )
+  rv="$?"
+  # Add non existing .do file to non-existence dependencies so
+  # target is built when .do file in question is created.
+  LANG=C redo-whichdo "${target}" \
+   |LANG=C REDO_TARGET=${target_abspath} xargs -0 redo-ifcreate 2>/dev/null
+  # Add .do file to dependencies so target is built when .do file changes.
+  _add_dependency "$target_abspath" "${dofile_abspath}"
+  # Exit code 123 conveys that target was considered up to date at runtime.
+  case ${rv} in
+   0) ;;
+   123)
+    LANG=C $REDO_RM ./"$tmp.tmp" ./"$tmp.tmp2"
+   ;;
+   *)
+    LANG=C $REDO_RM ./"$tmp.tmp" ./"$tmp.tmp2"
+    printf "${REDO_COLOR_FAILURE}redo %s${REDO_BOLD}%s: got exit code %s.${REDO_PLAIN}\n" \
+     "$REDO_DEPTH" "${target_abspath#$REDO_BASE/}" "$rv" >&2
+    exit 1
+   ;;
+  esac
+  if [ -s "$tmp.tmp" ]; then
+   LANG=C "$REDO_MV" ./"$tmp.tmp" ./"$target" 2>&-
+  elif [ -s "$tmp.tmp2" ]; then
+   LANG=C "$REDO_MV" ./"$tmp.tmp2" ./"$target" 2>&-
+  fi
+  [ -e "$tmp.tmp2" ] && LANG=C $REDO_RM ./"$tmp.tmp2"
+  # After build is finished, update dependencies.
+  : >> "$REDO_DIR/$target_abspath".dependencies.tmp
+  : >> "$REDO_DIR/$target_abspath".dependencies_ne.tmp
+  LANG=C "$REDO_MV" "$REDO_DIR/$target_abspath".dependencies.tmp \
+   "$REDO_DIR/$target_abspath".dependencies >&2
+  LANG=C "$REDO_MV" "$REDO_DIR/$target_abspath".dependencies_ne.tmp \
+   "$REDO_DIR/$target_abspath".dependencies_ne >&2
+ fi
+ # Some do files (like all.do) do not usually generate output.
+ if [ -e "$target_abspath" ]; then
+  # Record dependency on parent target.
+  if [ -n "$REDO_TARGET" ]; then
+   _add_dependency "$REDO_TARGET" "$target_abspath"
+  else
+   local base; _dirsplit "$target_abspath"
+   [ -d "$REDO_DIR/$dir" ] || LANG=C "${REDO_MKDIR}" -p "$REDO_DIR/$dir"
+   LANG=C $REDO_MD5SUM <"$target_abspath" > \
+    "$REDO_DIR/$target_abspath".md5sum
+  fi
+ fi
+ _exit_if_canary_dead
+}
+
+_run_dofile() {
+ export REDO_DEPTH="$REDO_DEPTH  "
+ export REDO_TARGET="$PWD"/"$target"
+ local line1
+ set -e
+ read -r line1 <"${dofile_abspath}" || true
+ cmd=${line1#"#!"}
+ # If the first line of a do file does not have a hashbang (#!), use /bin/sh.
+ if [ "$cmd" = "$line1" ] || [ "$cmd" = "/bin/sh" ]; then
+  if [ "${REDO_XTRACE:-}" = "1" ]; then
+   cmd="/bin/sh -ex"
+  else
+   cmd="/bin/sh -e"
+  fi
+ fi
+ $cmd "${dofile_abspath}" "$@" >"$tmp.tmp2"
+}
+
+set +e
+if [ -n "${1:-}" ]; then
+ jobs_pids=""
+ _jobs_count_decrease "redo ${REDO_TARGET#${REDO_BASE}/}"
+ for target; do
+  # If relative path to target is given, convert to absolute absolute path.
+  case "$target" in
+   /*) ;;
+   *)  target="$PWD"/"$target" >&2
+  esac
+  _dirsplit "$target"
+  if [ "${REDO_JOBS_MAX}" -gt "1" ]; then
+    _exit_if_canary_dead
+    _jobs_count_increase "redo ${dir#$REDO_BASE/}${base}"
+    if [ -e "${target}" ] && ! [ -w "${target}" ]; then
+     # An existing file that can not be written to is a dependency. It
+     # does not have to be locked, as redo will never be able to write
+     # to it. No dofile is executed, but job count is still increased.
+     (
+      ( cd "$dir" && _do "$dir" "$base" "$base" )
+      [ "$?" = 0 ] || ( _kill_canary; exit 1 )
+      _jobs_count_decrease "done ${dir#$REDO_BASE/}${base}"
+     ) &
+     jobs_pids="${jobs_pids} $!"
+    else
+     # Any other target may require locks and dofile execution or not.
+     (
+      lock_name="${dir}${base}"
+      _lock_acquire "${lock_name}"
+      ( cd "$dir" && _do "$dir" "$base" "$base" )
+      [ "$?" = 0 ] || ( _kill_canary; exit 1 )
+      _lock_release "${lock_name}"
+      _jobs_count_decrease "done ${dir#$REDO_BASE/}${base}"
+     ) &
+     jobs_pids="${jobs_pids} $!"
+    fi
+  else
+   ( cd "$dir" && _do "$dir" "$base" "$base" )
+   [ "$?" = 0 ] || exit 1
+  fi
+ done
+ for pid in ${jobs_pids}; do
+  wait ${pid}
+  [ "$?" = 0 ] || exit 1
+ done
+ _exit_if_canary_dead
+
+ # This operation may briefly increase jobs count over the given
+ # maximum. This is not a bug, but a measure to prevent a hang of
+ # redo-ifchange before exit, which blocks a parent indefinitely.
+ _jobs_count_increase "done ${REDO_TARGET}" &
+fi
diff --git a/bin/redo-ifcreate b/bin/redo-ifcreate
new file mode 100755
index 0000000..5365044
--- /dev/null
+++ b/bin/redo-ifcreate
@@ -0,0 +1,35 @@
+#!/bin/sh -eu
+# redo-ifcreate – bourne shell implementation of DJB redo
+# Copyright © 2014-2019  Nils Dagsson Moskopp (erlehmann)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
+# steigern. Gelegentlich packe ich sogar einen handfesten Buffer
+# Overflow oder eine Format String Vulnerability zwischen die anderen
+# Codezeilen und schreibe das auch nicht dran.
+
+# redo-ifcreate takes a list of non-existent files (sources) and adds
+# them as non-existence dependencies to the current target (the one
+# calling redo-ifcreate). If a non-existence dependency of a target
+# exists, the target will be rebuilt.
+
+for filename; do
+ # BusyBox v.1.19.3 outputs nothing for “readlink -f” on a nonexistent
+ # file, which means that redo-ifcreate can not canonicalize filenames.
+ case "${filename}" in
+  /*) dependency_ne="${filename}" ;;
+  *) dependency_ne="${PWD%/}/${filename}" ;;
+ esac
+ if [ ! -e "${dependency_ne}" ]; then
+  mkdir -p $(LANG=C dirname "${REDO_DIR}/${REDO_TARGET}".dependencies_ne.tmp)
+  printf '%s\n' "${dependency_ne}" >> "${REDO_DIR}/${REDO_TARGET}".dependencies_ne.tmp
+ else
+  printf "%sredo-ifcreate: %s exists.%s\n" "${REDO_COLOR_FAILURE}" "$dependency_ne" "${REDO_PLAIN}" >&2
+  exit 1
+  fi
+done
+exit 0
diff --git a/bin/redo-ood b/bin/redo-ood
new file mode 100755
index 0000000..22f5f43
--- /dev/null
+++ b/bin/redo-ood
@@ -0,0 +1,30 @@
+#!/bin/sh -eu
+# redo-ood – bourne shell implementation of DJB redo
+# Copyright © 2014-2021  Nils Dagsson Moskopp (erlehmann)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
+# steigern. Gelegentlich packe ich sogar einen handfesten Buffer
+# Overflow oder eine Format String Vulnerability zwischen die anderen
+# Codezeilen und schreibe das auch nicht dran.
+
+# Prints a list of all redo target files that are out of date.
+. "$(which redo-ifchange)"
+
+IFS='
+	'
+for depfile in $(find .redo -name '*.dependencies'); do
+ file="${depfile%.dependencies}"; file="${file#.redo}"
+ export REDO_BASE="$(pwd)"
+ export REDO_DIR="$REDO_BASE/.redo"
+ export REDO_TARGET='dummy_target'
+ if ( ! _target_uptodate "$file" || ! _dependencies_uptodate "$file" ); then
+  if [ -e "$file" ]; then
+   echo "$file"
+  fi
+ fi
+done
diff --git a/bin/redo-sources b/bin/redo-sources
new file mode 100755
index 0000000..02c82b7
--- /dev/null
+++ b/bin/redo-sources
@@ -0,0 +1,27 @@
+#!/bin/sh
+# redo-sources – bourne shell implementation of DJB redo
+# Copyright © 2014  Nils Dagsson Moskopp (erlehmann)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
+# steigern. Gelegentlich packe ich sogar einen handfesten Buffer
+# Overflow oder eine Format String Vulnerability zwischen die anderen
+# Codezeilen und schreibe das auch nicht dran.
+
+# Prints a list of all redo source files that exist. A source file is
+# a file that was listed as a dependency using redo-ifchange, but is
+# not itself a target. A target file is a file that redo can build.
+
+IFS='
+	'
+for filename in $(find .redo -name '*.dependencies'); do
+ while read -r dependency ctime md5sum; do
+  if [ -e "$dependency" ] && [ ! -e ".redo/$dependency.dependencies" ] ; then
+   echo "$dependency"
+  fi
+ done <"$filename"
+done | sort | uniq
diff --git a/bin/redo-stamp b/bin/redo-stamp
new file mode 100755
index 0000000..8705765
--- /dev/null
+++ b/bin/redo-stamp
@@ -0,0 +1,29 @@
+#!/bin/sh
+# redo-stamp – bourne shell implementation of DJB redo
+# Copyright © 2014-2017  Nils Dagsson Moskopp (erlehmann)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
+# steigern. Gelegentlich packe ich sogar einen handfesten Buffer
+# Overflow oder eine Format String Vulnerability zwischen die anderen
+# Codezeilen und schreibe das auch nicht dran.
+
+stamp_new=$(md5sum)
+stamp_old=$(cat "$REDO_DIR/$REDO_TARGET".stamp 2>/dev/null)
+if [ "$stamp_new" != "$stamp_old" ]; then
+ path="$REDO_DIR/$REDO_TARGET"
+ dir=${path%/*}
+ [ ! -d "$dir" ] && mkdir -p "$dir"
+ printf '%s' "$stamp_new" > "$REDO_DIR/$REDO_TARGET".stamp
+ redo-ifchange "$REDO_DIR/$REDO_TARGET".stamp
+ exit 0
+fi
+if [ -e "$REDO_TARGET" ]; then
+ # Exit code 123 conveys that target was considered uptodate at runtime.
+ exit 123
+ # FIXME: redo-stamp may not be the only dependency mechanism
+fi
diff --git a/bin/redo-targets b/bin/redo-targets
new file mode 100755
index 0000000..9ae47ed
--- /dev/null
+++ b/bin/redo-targets
@@ -0,0 +1,25 @@
+#!/bin/sh
+# redo-targets – bourne shell implementation of DJB redo
+# Copyright © 2014  Nils Dagsson Moskopp (erlehmann)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
+# steigern. Gelegentlich packe ich sogar einen handfesten Buffer
+# Overflow oder eine Format String Vulnerability zwischen die anderen
+# Codezeilen und schreibe das auch nicht dran.
+
+# Prints a list of all redo target files that exist. A target file is
+# a file that redo can build.
+
+IFS='
+	'
+for depfile in $(find .redo -name '*.dependencies'); do
+ file="${depfile%.dependencies}"; file="${file#.redo}"
+ if [ -e "$file" ]; then
+  echo "$file"
+ fi
+done
diff --git a/bin/redo-whichdo b/bin/redo-whichdo
new file mode 100755
index 0000000..fa3a4ca
--- /dev/null
+++ b/bin/redo-whichdo
@@ -0,0 +1,79 @@
+#!/bin/sh -eu
+# redo-whichdo – bourne shell implementation of DJB redo
+# Copyright © 2018-2019  Nils Dagsson Moskopp (erlehmann)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
+# steigern. Gelegentlich packe ich sogar einen handfesten Buffer
+# Overflow oder eine Format String Vulnerability zwischen die anderen
+# Codezeilen und schreibe das auch nicht dran.
+
+case ${SEPARATOR:-} in
+ '') [ -t 1 ] && SEPARATOR='\n' || SEPARATOR='\0'
+esac
+
+alias print_filename="printf -- '%s${SEPARATOR}'"
+
+find_default_dofile() {
+ target_abspath=${1}
+ target_basename=${target_abspath##*/}
+ target_dirname=${target_abspath%"${target_basename}"}
+ dofile_candidate=default.${target_basename}.do
+ while :; do
+  dofile_candidate=default.${dofile_candidate#default.*.}
+  dofile_candidate_abspath="${PWD%/}/${dofile_candidate}"
+  case "${dofile_candidate_abspath}" in
+   "${target_abspath}")
+    # A file named “default.do” can not be its own dofile.
+   ;;
+   *)
+    print_filename "${dofile_candidate_abspath}"
+   ;;
+  esac
+
+  [ -f "${dofile_candidate}" ] || [ "${dofile_candidate}" = "default.do" ] && break
+ done
+}
+
+find_dofile() {
+ # BusyBox v.1.19.3 outputs nothing for “readlink -f” on a nonexistent
+ # file, which means that redo-whichdo can not canonicalize filenames.
+ case "${1}" in
+  /*) target_abspath="${1}" ;;
+  *) target_abspath="${PWD%/}/${1}" ;;
+ esac
+ target_basename=${target_abspath##*/}
+ target_dirname=${target_abspath%"${target_basename}"}
+
+ # Skip printing first guess for path names with the prefix “default”
+ # to prevent duplicate output.
+ case "${target_basename}" in
+  default)
+  ;;
+  default.*)
+  ;;
+  *)
+   dofile_candidate="$target_abspath".do
+   print_filename "${dofile_candidate}"
+   [ -f "${dofile_candidate}" ] && return
+  ;;
+ esac
+
+ cd "${target_dirname}"
+
+ while :; do
+  find_default_dofile "${target_abspath}"
+  [ -f "${dofile_candidate}" ] || [ "${PWD}" = "/" ] && break
+  cd ..
+ done
+
+ [ -f "${PWD%/}/${dofile_candidate}" ] || exit 1
+}
+
+for target; do
+ find_dofile "${target}"
+done
diff --git a/clean.do b/clean.do
new file mode 100644
index 0000000..2fa15eb
--- /dev/null
+++ b/clean.do
@@ -0,0 +1 @@
+rm -f spiewnik.pdf spiewnik.ps spiewnik.idx spiewnik.preidx index.ms
diff --git a/index.ms.do b/index.ms.do
new file mode 100644
index 0000000..97609f7
--- /dev/null
+++ b/index.ms.do
@@ -0,0 +1,8 @@
+redo-ifchange $(find piosenki -type f -name '*.txt')
+
+cat source.tmac > index.ms
+for f in `find piosenki -type f -name '*.txt' | sort`; do
+  filename=$(basename $f .txt)
+  cp $f piosenki/$filename.ms
+  echo .SOURCE piosenki/$filename.ms >> index.ms
+done
diff --git a/man/man1/redo-always.1 b/man/man1/redo-always.1
new file mode 100644
index 0000000..709ade6
--- /dev/null
+++ b/man/man1/redo-always.1
@@ -0,0 +1,92 @@
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH REDO-ALWAYS 1
+.SH NAME
+redo-always \- mark the current
+.I redo
+target as always needing to be rebuilt
+.SH SYNOPSIS
+.B redo-always
+.SH DESCRIPTION
+.IR redo(1)
+is a tool for building files and for rebuilding them if any of their dependencies have changed.
+.IR redo-always ,
+when invoked from a dofile, adds a dependency on the current target that is impossible to satisfy. The target will always be rebuilt if given as an argument to
+.IR redo-ifchange(1) .
+.SH EXAMPLES
+.PP
+Consider the following three dofiles
+.IR all.do ,
+.IR b.do
+and
+.IR c.do :
+.TP
+.I all.do
+.br
+#!/bin/sh
+.br
+redo-ifchange b
+.TP
+.I b.do
+.br
+#!/bin/sh
+.br
+redo-ifchange c
+.br
+sleep 1
+.br
+date +%s
+.TP
+.I c.do
+.br
+#!/bin/sh
+.br
+redo-always
+.br
+date +%s
+.PP
+Invoking
+.IR redo(1)
+in a directory with these three files will build a file named
+.I c
+containing a timestamp and a file named
+.I b
+containing a timestamp that is at least one second later. Both
+.I b
+and
+.I c
+will always be rebuilt when
+.IR redo(1)
+is invoked, as the default target
+.I all
+depends on
+.I b
+which in turn depends on
+.I c
+which has an impossible to satisfy dependency.
+.SH HISTORY
+.I redo-always
+was designed by Avery Pennarun as part of his
+.I redo
+implementation and implemented by Nils Dagsson Moskopp.
+.SH AUTHOR
+.I redo-always
+and this man page were written by Nils Dagsson Moskopp.
+.SH COPYRIGHT
+Copyright © 2014-2016 Nils Dagsson Moskopp.
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
+.SH SEE ALSO
+.IR redo(1) ,
+.IR redo-dot(1) ,
+.IR redo-ifchange(1) ,
+.IR redo-ifcreate(1) ,
+.IR redo-ood(1) ,
+.IR redo-sources(1) ,
+.IR redo-stamp(1) ,
+.IR redo-targets(1)
+.SH BUGS
+.I redo-always
+may break if the target filename contains a tab or a newline.
diff --git a/man/man1/redo-dot.1 b/man/man1/redo-dot.1
new file mode 100644
index 0000000..33f77cf
--- /dev/null
+++ b/man/man1/redo-dot.1
@@ -0,0 +1,73 @@
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH REDO-DOT 1
+.SH NAME
+redo-dot \- print
+.I redo
+dependency graph for the current directory
+.SH SYNOPSIS
+.B redo-dot
+.RI [pattern]
+.SH DESCRIPTION
+.IR redo(1)
+is a tool for building files and for rebuilding them if any of their dependencies have changed.
+.I redo-dot
+prints the dependency graph for the current directory in the file format consumed by
+.IR dot(1)
+from the Graphviz layout programs. If the current working directory is not a
+.IR redo(1)
+build directory,
+.I redo-dot
+exits with a status code indicating failure.
+.PP
+In the dependency graph, targets and sources are represented by nodes, dependencies are represented by solid edges, and non-existence dependencies are represented by dotted edges. Targets that have impossible to satisfy dependencies have a bold outline. Targets that are rebuilt depending on input to
+.IR redo-stamp(1)
+have a dashed outline.
+.PP
+A pattern contains characters that match themselves and the meta-characters “!”, “*”, “?”, and “[”, which lose their special meanings if they are quoted. Asterisks (“*”) match any string of characters. Question marks (“?”) match any single character. Left brackets (“[”) and right brackets (“]”) indicate start and end of a character class. Character classes match any characters between brackets or a range of characters specified using a minus (“-”); to include literal minus, make it the first or last character. Exclamation marks (“!”) as the first character of any character class negates it.
+.SH EXAMPLES
+.TP
+.B redo-dot |dot -Tx11
+shows the full dependency graph in an X11 window using
+.IR dot(1).
+.TP
+.B redo-dot '*/stdio.h'
+outputs a dependency graph with only nodes that match the pattern
+.IR */stdio.h ,
+dependencies of nodes that match the pattern, and nodes that depend on nodes that match the pattern.
+.TP
+.B redo-dot |sed s%"$(pwd)"/%%g >deps.dot; dot deps.dot -Tpng >deps.png
+outputs the full dependency graph into a file named
+.IR deps.dot ,
+then generates a PNG (Portable Network Graphics) file named
+.IR deps.png
+from it using
+.IR dot(1) .
+The
+.IR sed(1)
+invocation removes the current working directory from the node names.
+.SH HISTORY
+.I redo-dot
+was designed and implemented by Nils Dagsson Moskopp.
+.SH AUTHOR
+.I redo-dot
+and this man page were written by Nils Dagsson Moskopp.
+.SH COPYRIGHT
+Copyright © 2015-2016 Nils Dagsson Moskopp.
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
+.SH SEE ALSO
+.IR sh(1) ,
+.IR redo(1) ,
+.IR redo-always(1) ,
+.IR redo-ifchange(1) ,
+.IR redo-ifcreate(1) ,
+.IR redo-ood(1) ,
+.IR redo-sources(1) ,
+.IR redo-stamp(1) ,
+.IR redo-targets(1)
+.SH BUGS
+.I redo-dot
+may break if the target filename contains a tab or newline character.
diff --git a/man/man1/redo-ifchange.1 b/man/man1/redo-ifchange.1
new file mode 100644
index 0000000..c787f32
--- /dev/null
+++ b/man/man1/redo-ifchange.1
@@ -0,0 +1,159 @@
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH REDO-IFCHANGE 1
+.SH NAME
+redo-ifchange \- rebuild target files when source files have changed
+.SH SYNOPSIS
+.B redo-ifchange
+.I target
+.RI [ target ]...
+.SH DESCRIPTION
+.IR redo(1)
+is a tool for building files and for rebuilding them if any of their dependencies have changed.
+.IR redo-ifchange ,
+when invoked from a dofile, adds dependencies of the current
+.IR redo(1)
+target on all files given as  arguments, (re)builds those files if necessary and rebuilds the current target if the files given as arguments have changed since the last build.
+.PP
+Internally
+.I redo-ifchange
+uses
+.IR stat(1)
+and
+.IR md5sum(1)
+or
+.IR openssl(1)
+or
+.IR md5(1)
+to determine if a file is out of date. If the ctime of a file did not change since the last build,
+.I redo-ifchange
+considers the file up to date. If the checksum of a file did not change,
+.I redo-ifchange
+updates the stored ctime and considers the file up to date. Otherwise,
+.I redo-ifchange
+considers the file out of date.
+.PP
+When
+.I redo(1)
+is invoked with the
+.B -j
+or
+.B --jobs
+option and an integer argument greater than 1,
+.I redo-ifchange(1)
+can build multiple targets in parallel. The integer argument specifies the maximum number of targets that
+.I redo-ifchange(1)
+is allowed to build in parallel.
+.PP
+.I redo-ifchange(1)
+processes started as a result of the same
+.I redo(1)
+invocation share knowledge of a temporary “canary” path.
+If any
+.I redo-ifchange(1)
+process exits with a status code indicating error or receives a
+.B SIGINT
+signal (interrupt from keyboard), it creates a file at the “canary” path. When
+.I redo-ifchange(1)
+notices such a “canary” file, it exits as soon as possible with a status code indicating error.
+.SH EXAMPLES
+.PP
+Consider the following four files
+.IR all.do ,
+.IR b.do ,
+.IR c
+and
+.IR d :
+.TP
+.I all.do
+.br
+#!/bin/sh
+.br
+redo-ifchange b
+.TP
+.I b.do
+.br
+#!/bin/sh
+.br
+redo-ifchange c d
+.br
+date +%s
+.TP
+.I c
+.br
+foo
+.TP
+.I d
+.br
+bar
+.PP
+Invoking
+.IR redo(1)
+in a directory with these files will build a file named
+.I b
+containing a timestamp. The next time
+.IR redo(1)
+is invoked, it will only rebuild
+.I b
+if the contents of
+.IR b ,
+.IR c
+or
+.IR d
+have changed since the last build. This can be verified by invoking 
+.IR redo(1) ,
+repeatedly and examining the timestamp in
+.IR b ,
+after each invocation, then changing the contents of
+.IR b ,
+.IR c
+or
+.IR d
+and invoking
+.IR redo(1)
+again.
+.SH HISTORY
+.I redo-ifchange
+was designed by D. J. Bernstein and implemented by Nils Dagsson Moskopp.
+.TP
+.URL https://cr.yp.to/redo/atomic.html "Rebuilding target files atomically" " by D. J. Bernstein"
+.SH AUTHOR
+.I redo-ifchange
+and this man page were written by Nils Dagsson Moskopp.
+.SH COPYRIGHT
+Copyright © 2014-2016 Nils Dagsson Moskopp.
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
+.SH SEE ALSO
+.IR redo(1) ,
+.IR redo-always(1) ,
+.IR redo-dot(1) ,
+.IR redo-ifcreate(1) ,
+.IR redo-ood(1) ,
+.IR redo-sources(1) ,
+.IR redo-stamp(1) ,
+.IR redo-targets(1) ,
+.IR signal(7)
+.SH BUGS
+.I redo-ifchange
+erroneously considers target files always out of date if their name contains a tab or a newline character.
+.PP
+On a computer with a
+.IR stat(1)
+implementation that does not accept the
+.B -c%Y
+option,
+.I redo-ifchange
+considers target files to be always out of date.
+.PP
+When building in parallel and sending a
+.B SIGINT
+signal (interrupt from keyboard) to a
+.I redo-ifchange(1)
+process, other
+.I redo-ifchange(1)
+processes started from the same
+.I redo(1)
+invocation might not immediately notice the existence of the “canary“ file and linger for a short time.
diff --git a/man/man1/redo-ifcreate.1 b/man/man1/redo-ifcreate.1
new file mode 100644
index 0000000..f7d803e
--- /dev/null
+++ b/man/man1/redo-ifcreate.1
@@ -0,0 +1,94 @@
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH REDO-IFCREATE 1
+.SH NAME
+redo-ifcreate \- rebuild target files when source files are created
+.SH SYNOPSIS
+.B redo-ifcreate
+.I target
+.RI [ target ]...
+.SH DESCRIPTION
+.IR redo(1)
+is a tool for building files and for rebuilding them if any of their dependencies have changed.
+.IR redo-ifcreate ,
+when invoked from a dofile, adds non-existence dependencies of the current
+.IR redo(1)
+target on all files given as arguments. This means that the current target will be rebuilt on invocation of
+.IR redo(1)
+if any of the files given as arguments to
+.IR redo-ifcreate
+exist. If an argument to
+.IR redo-ifcreate
+exists, it exits with a status code indicating failure.
+.SH EXAMPLES
+.PP
+Consider the following two files
+.IR all.do
+and
+.IR b.do :
+.TP
+.I all.do
+.br
+#!/bin/sh
+.br
+redo-ifchange b
+.TP
+.I b.do
+.br
+#!/bin/sh
+.br
+if [ ! -e c ]; then
+.br
+ redo-ifcreate c
+.br
+fi
+.br
+date +%s
+.PP
+Invoking
+.IR redo(1)
+in a directory with these files that does not contain a file named
+.I c
+will build a file named
+.I b
+containing a timestamp. The next time
+.IR redo(1)
+is invoked, it will only rebuild
+.I b
+if a file named
+.I c
+was created since the last build. This can be verified by invoking 
+.IR redo(1)
+repeatedly and examining the timestamp
+.IR b
+after each invocation, then creating a file named
+.IR c ,
+invoking
+.IR redo(1)
+again and examining the timestamp again.
+.SH HISTORY
+.I redo-ifcreate
+was designed by D. J. Bernstein and implemented by Nils Dagsson Moskopp.
+.TP
+.URL https://cr.yp.to/redo/honest-nonfile.html "Target files depend on nonexistent files" " by D. J. Bernstein"
+.SH AUTHOR
+.I redo-ifcreate
+and this man page were written by Nils Dagsson Moskopp.
+.SH COPYRIGHT
+Copyright © 2014-2016 Nils Dagsson Moskopp.
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to create and redistribute it. There is NO WARRANTY, to the extent permitted by law.
+.SH SEE ALSO
+.IR redo(1) ,
+.IR redo-always(1) ,
+.IR redo-dot(1) ,
+.IR redo-ifchange(1) ,
+.IR redo-ood(1) ,
+.IR redo-sources(1) ,
+.IR redo-stamp(1) ,
+.IR redo-targets(1)
+.SH BUGS
+.I redo-ifcreate
+may break if a source filename contains a tab or newline character.
diff --git a/man/man1/redo-ood.1 b/man/man1/redo-ood.1
new file mode 100644
index 0000000..7bd7f1c
--- /dev/null
+++ b/man/man1/redo-ood.1
@@ -0,0 +1,43 @@
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH REDO-OOD 1
+.SH NAME
+redo-ood \- print list of
+.I redo
+targets that are out of date
+.SH SYNOPSIS
+.B redo-ood
+.SH DESCRIPTION
+.IR redo(1)
+is a tool for building files and for rebuilding them if any of their dependencies have changed.
+.I redo-ood
+prints the list of redo targets in the current directory and its subdirectories that exist and are out of date, i.e. files that would be rebuilt if given as an argument to
+.IR redo-ifchange(1) .
+.PP
+Files that do not exist are not listed because they might not be targets anymore. For example, if you build a file and later remove it and change the build to no longer generate it, it will not be listed.
+.SH HISTORY
+.I redo-ood
+was designed by Avery Pennarun as part of his
+.I redo
+implementation and implemented by Nils Dagsson Moskopp.
+.SH AUTHOR
+.I redo-ood
+and this man page were written by Nils Dagsson Moskopp.
+.SH COPYRIGHT
+Copyright © 2014-2016 Nils Dagsson Moskopp.
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
+.SH SEE ALSO
+.IR redo(1) ,
+.IR redo-always(1) ,
+.IR redo-dot(1) ,
+.IR redo-ifchange(1) ,
+.IR redo-ifcreate(1) ,
+.IR redo-sources(1) ,
+.IR redo-stamp(1) ,
+.IR redo-targets(1)
+.SH BUGS
+.I redo-ood
+may break if the target filename contains a tab or a newline.
diff --git a/man/man1/redo-sources.1 b/man/man1/redo-sources.1
new file mode 100644
index 0000000..59dc56d
--- /dev/null
+++ b/man/man1/redo-sources.1
@@ -0,0 +1,49 @@
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH REDO-SOURCES 1
+.SH NAME
+redo-sources \- print list of
+.IR redo(1)
+sources
+.SH SYNOPSIS
+.B redo-sources
+.SH DESCRIPTION
+.IR redo(1)
+is a tool for building files and for rebuilding them if any of their dependencies have changed.
+.I redo-sources
+prints the list of
+.IR redo(1)
+sources in the current directory and its subdirectories that exist. A source is a file that has been listed as a dependency of another file using
+.IR redo-ifchange(1)
+but can not be built with
+.IR redo(1) .
+.PP
+Files that do not exist are not listed because they might not be sources anymore. For example, if you declare a dependency on a file using
+.IR redo-ifchange(1)
+and later remove the file and create a dofile to generate it, it will not be listed.
+.SH HISTORY
+.I redo-sources
+was designed by Avery Pennarun as part of his
+.I redo
+implementation and implemented by Nils Dagsson Moskopp.
+.SH AUTHOR
+.I redo-sources
+and this man page were written by Nils Dagsson Moskopp.
+.SH COPYRIGHT
+Copyright © 2014-2016 Nils Dagsson Moskopp.
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
+.SH SEE ALSO
+.IR redo(1) ,
+.IR redo-always(1) ,
+.IR redo-dot(1) ,
+.IR redo-ifchange(1) ,
+.IR redo-ifcreate(1) ,
+.IR redo-ood(1) ,
+.IR redo-stamp(1) ,
+.IR redo-targets(1)
+.SH BUGS
+.I redo-sources
+may break if the target filename contains a tab or a newline.
diff --git a/man/man1/redo-stamp.1 b/man/man1/redo-stamp.1
new file mode 100644
index 0000000..02be28f
--- /dev/null
+++ b/man/man1/redo-stamp.1
@@ -0,0 +1,91 @@
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH REDO-STAMP 1
+.SH NAME
+redo-stamp \- rebuild target files depending on data given on standard input
+.SH SYNOPSIS
+.RI [command]
+|
+.B redo-stamp
+.SH DESCRIPTION
+.IR redo(1)
+is a tool for building files and for rebuilding them if any of their dependencies have changed.
+.IR redo-stamp ,
+when invoked from a dofile, adds a dependency of the current
+.IR redo(1)
+target on the data given on standard input. If the data given on standard input to
+.IR redo-stamp
+has not changed since the last build, the current
+.IR redo(1)
+target is not rebuilt and marked as up to date. To ensure that
+.IR redo-stamp
+checks the current target's validity, one can use
+.IR redo-always(1)
+to mark the current target as always out of date.
+.SH EXAMPLES
+.PP
+Consider the following two files
+.IR all.do
+and
+.IR b.do :
+.TP
+.I all.do
+.br
+#!/bin/sh
+.br
+redo-ifchange b
+.TP
+.I b.do
+.br
+#!/bin/sh
+.br
+redo-always
+.br
+echo 'input a line of text:' >&2
+.br
+line | redo-stamp
+.br
+date +%s
+.PP
+Invoking
+.IR redo(1)
+in a directory with these files will build a file named
+.I b
+containing a timestamp. The next time
+.IR redo(1)
+is invoked, it will only rebuild
+.I b
+if the output of
+.IR line(1)
+changed since the last build. This can be verified by invoking 
+.IR redo(1)
+repeatedly and examining the timestamp
+.IR b
+after each invocation, then changing the input to
+.IR line(1) ,
+invoking
+.IR redo(1)
+again and examining the timestamp again.
+.SH HISTORY
+.I redo-stamp
+was designed by Avery Pennarun and implemented by Nils Dagsson Moskopp.
+.SH AUTHOR
+.I redo-stamp
+and this man page were written by Nils Dagsson Moskopp.
+.SH COPYRIGHT
+Copyright © 2014-2017 Nils Dagsson Moskopp.
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to create and redistribute it. There is NO WARRANTY, to the extent permitted by law.
+.SH SEE ALSO
+.IR redo(1) ,
+.IR redo-always(1) ,
+.IR redo-dot(1) ,
+.IR redo-ifchange(1) ,
+.IR redo-ifcreate(1) ,
+.IR redo-ood(1) ,
+.IR redo-sources(1) ,
+.IR redo-targets(1)
+.SH BUGS
+None so far.
diff --git a/man/man1/redo-targets.1 b/man/man1/redo-targets.1
new file mode 100644
index 0000000..dc8dcb8
--- /dev/null
+++ b/man/man1/redo-targets.1
@@ -0,0 +1,45 @@
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH REDO-TARGETS 1
+.SH NAME
+redo-targets \- print list of
+.IR redo(1)
+targets
+.SH SYNOPSIS
+.B redo-targets
+.SH DESCRIPTION
+.IR redo(1)
+is a tool for building files and for rebuilding them if any of their dependencies have changed.
+.I redo-targets
+prints the list of
+.IR redo(1)
+targets in the current directory and its subdirectories that exist, i.e. files that would be rebuilt if given as an argument to
+.IR redo-ifchange(1) .
+.PP
+Files that do not exist are not listed because they might not be targets anymore. For example, if you build a file and later remove it and change the build to no longer generate it, it will not be listed.
+.SH HISTORY
+.I redo-targets
+was designed by Avery Pennarun as part of his
+.IR redo(1)
+implementation and implemented by Nils Dagsson Moskopp.
+.SH AUTHOR
+.I redo-targets
+and this man page were written by Nils Dagsson Moskopp.
+.SH COPYRIGHT
+Copyright © 2014-2016 Nils Dagsson Moskopp.
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
+.SH SEE ALSO
+.IR redo(1) ,
+.IR redo-always(1) ,
+.IR redo-dot(1) ,
+.IR redo-ifchange(1) ,
+.IR redo-ifcreate(1) ,
+.IR redo-ood(1) ,
+.IR redo-sources(1) ,
+.IR redo-stamp(1)
+.SH BUGS
+.I redo-targets
+may break if the target filename contains a tab or a newline.
diff --git a/man/man1/redo-whichdo.1 b/man/man1/redo-whichdo.1
new file mode 100644
index 0000000..89b135b
--- /dev/null
+++ b/man/man1/redo-whichdo.1
@@ -0,0 +1,127 @@
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH REDO-WHICHDO 1
+.SH NAME
+redo-whichdo \- print search paths for dofiles to build a
+.I redo
+target
+.SH SYNOPSIS
+.B redo-whichdo
+.I target
+.SH DESCRIPTION
+.I redo(1)
+is a tool for building files and for rebuilding them if any of their dependencies have changed.
+.I redo-whichdo
+prints all dofiles that
+.I redo(1)
+will look for to build the target.
+If the exit code of
+.I redo-whichdo
+indicates success, the last filename is the filename of the dofile that
+.I redo(1)
+will actually use to build the target.
+.PP
+.I redo-whichdo
+prints the filename for a dofile that
+.I redo(1)
+could use to build the target.
+If the dofile exists,
+.I redo-whichdo
+exits with a status code indicating success.
+If the dofile does not exist,
+.I redo-whichdo
+either repeats the previous action with a fallback filename or exits with a status code indicating error if
+.I redo-whichdo
+can not find a dofile to build the target.
+.PP
+If standard output is a terminal,
+.I redo-whichdo
+separates filenames by newline characters. Otherwise,
+.I redo-whichdo
+separates filenames by null characters.
+Shell scripts that act on the output of
+.I redo-whichdo
+can pipe it to
+.I xargs(1)
+invoked with the
+.B -0
+option to handle the filenames.
+.SH EXAMPLES
+.PP
+Consider a root directory containing only the three dofiles
+.IR a.do ,
+.IR default.b.do ,
+.IR default.c.do ,
+and a folder
+.IR d .
+For the targets,
+.IR a ,
+.IR a.b ,
+and
+.IR a.b.c ,
+.IR d/a.b.c ,
+the output of
+.I redo-whichdo(1)
+would be these:
+.TP
+.I a
+.br
+/a.do
+.TP
+.I a.b
+.br
+/a.b.do
+.br
+/default.b.do
+.TP
+.I a.b.c
+.br
+/a.b.c.do
+.br
+/default.b.c.do
+.br
+/default.c.do
+.TP
+.I d/a.b.c
+.br
+/d/a.b.c.do
+.br
+/d/default.b.c.do
+.br
+/d/default.c.do
+.br
+/d/default.do
+.br
+/default.b.c.do
+.br
+/default.c.do
+.SH NOTES
+.PP
+A dofile used to build a target is a dependency of that target:
+If
+.I redo(1)
+determines that the dofile used to build a target has changed, the target will be rebuilt.
+.PP
+All non-existent dofiles searched for while building a target are non-existence dependencies of that target:
+If
+.I redo(1)
+finds that a previously searched for non-existent dofile exists, the target will be rebuilt.
+.SH HISTORY
+.I redo-whichdo
+was designed by Avery Pennarun and Nils Dagsson Moskopp as part of Avery Pennarun's
+.I redo
+implementation and independently implemented by Nils Dagsson Moskopp.
+.SH AUTHOR
+.I redo-whichdo
+and this man page were written by Nils Dagsson Moskopp.
+.SH COPYRIGHT
+Copyright © 2018-2019 Nils Dagsson Moskopp.
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
+.SH SEE ALSO
+.IR redo(1) ,
+.IR redo-ifchange(1) ,
+.IR redo-ifcreate(1) ,
+.IR redo-targets(1)
diff --git a/man/man1/redo.1 b/man/man1/redo.1
new file mode 100644
index 0000000..fe2b9e7
--- /dev/null
+++ b/man/man1/redo.1
@@ -0,0 +1,226 @@
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH REDO 1
+.SH NAME
+redo \- rebuild target files when source files have changed
+.SH SYNOPSIS
+.B redo
+.RB [ option ]
+.RI [ target ]...
+.SH DESCRIPTION
+.I redo
+is a tool for building files and for rebuilding them if any of their dependencies have changed. The build rules are contained in files with the extension .do that are called dofiles. Usually, dofiles are shell scripts executed by
+.IR sh(1) .
+.PP
+.I redo
+uses a simple algorithm to find dofiles: First it looks for the filename of the target with the suffix
+.IR .do ,
+then it looks for filenames consisting of
+.I default
+plus the target's filename extension plus
+.IR .do ,
+recursively removing the last component of the target's filename extension.
+.PP
+For example, if
+.I redo
+is asked to build a file called
+.B
+.IR example.x.y.z ,
+it will look for dofiles with the following filenames to build the file:
+.RS
+.PP
+example.x.y.z.do
+.PP
+default.x.y.z.do
+.PP
+default.y.z.do
+.PP
+default.z.do
+.PP
+default.do
+.RE
+.PP
+.I redo
+considers the first existing file found this way the dofile for the target and executes it. If
+.I redo
+is not given a target, it builds a target named
+.IR all .
+If
+.I redo
+can not find a dofile for a target, it exits with a status code indicating failure.
+.PP
+.I redo
+passes three arguments to a dofile that is executed:
+.TP
+.B $1
+is the name of the target.
+.TP
+.B $2
+is the basename of the target, i.e. the name of the target minus leading directory components and extensions. Note that the extension is determined from the dofile: A file
+.I
+example.a.b.c
+that is built with a dofile
+.I default.b.c.do
+will be considered to have the extension
+.IR b.c ,
+so
+.B $2
+will be set to
+.IR example.a .
+.TP
+.B $3
+is the name of a temporary file which replaces the target atomically after the dofile has exited successfully. Instead of writing to
+.BR $3 ,
+a dofile can also write to standard output.
+.PP
+If the current target should be rebuilt if other files change, this can be declared with
+.IR redo-ifchange(1) :
+When
+.IR redo-ifchange(1)
+is executed from a dofile,
+.I redo
+builds the targets given to
+.IR redo-ifchange(1)
+and will rebuild the current target on the next invocation of
+.I redo
+if any of the targets given to
+.IR redo-ifchange(1)
+have changed since the last build.
+.PP
+If the current target should be rebuilt if a file that does not exist at the time of the build exists, this can be declared with
+.IR redo-ifcreate(1) :
+When
+.IR redo-ifcreate(1)
+is executed from a dofile,
+.I redo
+will rebuild the current target on the next invocation of
+.I redo
+if any of the targets given to
+.IR redo-ifcreate(1)
+exist.
+.PP
+If the current target should be rebuilt if the output of a command changes, this can be declared with
+.IR redo-stamp(1) :
+When
+.IR redo-stamp(1)
+is executed from a dofile and given data on standard input,
+.I redo
+will rebuild the current target on the next invocation of
+.I redo
+if the the output of the command that piped data to it changes.
+.PP
+If the current target should always be rebuilt, this can be declared with
+.IR redo-always(1) :
+When
+.IR redo-always(1)
+is executed from a dofile,
+.I redo
+will rebuild the current target on the next invocation of
+.IR redo .
+.SH OPTIONS
+If the
+.B -d
+or
+.B --debug
+option is given,
+.I redo
+prints information about all dependency checks.
+.PP
+If the
+.B -h
+or
+.B --help
+option is given,
+.I redo
+prints a short notice about its command line options.
+.PP
+If the
+.B -j
+or
+.B --jobs
+option is given followed by an integer, an invocation of
+.I redo(1)
+or
+.I redo-ifchange(1)
+with multiple arguments builds targets in parallel. The integer argument specifies the maximum number of targets allowed to be built in parallel. Targets are locked, so if targets built in parallel share a dependency,
+.I redo(1)
+only builds it once, unless the dependency dofile uses
+.I redo-always(1)
+to rebuild every time,
+or the dependency becomes out of date during a build in some other way.
+.PP
+If the
+.B --version
+option is given,
+.I redo
+prints version information and exits.
+.PP
+If the
+.B -x
+or
+.B --xtrace
+option is given,
+.I redo
+prints commands inside dofiles as they are executed.
+.SH EXAMPLES
+.TP
+.B redo
+makes
+.I redo
+search for a dofile called
+.BR all.do ,
+which it executes to build the target
+.BR all .
+Usually, executing
+.B all.do
+will yield no output on standard output and
+.I redo
+will not create a file called
+.BR all .
+.TP
+.B redo example.x.y.z
+makes
+.I redo
+search for dofiles called
+.BR example.x.y.z.do ,
+.BR default.x.y.z.do ,
+.BR default.x.y.do ,
+.BR default.x.do ,
+.BR default.do .
+.I redo
+executes the first file that exists to build
+.BR example.x.y.z .
+.SH HISTORY
+.I redo
+was designed by D. J. Bernstein and implemented multiple times by Alan Grosskurth, Avery Pennarun, Jonathan de Boyne Pollard and Nils Dagsson Moskopp.
+.TP
+.URL http://cr.yp.to/redo.html "Rebuilding target files when source files have changed" " by D. J. Bernstein"
+.TP
+.URL http://grosskurth.ca/papers/mmath-thesis.pdf "Purely top-down software rebuilding" " by Alan Grosskurth"
+.TP
+.URL https://github.com/apenwarr/redo#readme "redo: a top-down software build system" " by Avery Pennarun"
+.TP
+.URL http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/introduction-to-redo.html "Introduction to redo" " by Jonathan de Boyne Pollard"
+.TP
+.URL http://news.dieweltistgarnichtso.net/bin/redo-sh.html "Redo implementation in Bourne Shell" " by Nils Dagsson Moskopp"
+.SH AUTHOR
+.I redo
+and this man page were written by Nils Dagsson Moskopp.
+.SH COPYRIGHT
+Copyright © 2014-2016 Nils Dagsson Moskopp.
+License AGPLv3+: GNU Affero GPL version 3 or later <http://www.gnu.org/licenses/agpl-3.0.html>.
+This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
+.SH SEE ALSO
+.IR redo-always(1) ,
+.IR redo-ifchange(1) ,
+.IR redo-ifcreate(1) ,
+.IR redo-ood(1) ,
+.IR redo-sources(1) ,
+.IR redo-stamp(1) ,
+.IR redo-targets(1)
+.SH BUGS
+This implementation of
+.I redo
+may break if the target filename contains a tab or newline.
diff --git a/piosenki/1-juz-rozpalilo-sie-ognisko.txt b/piosenki/1-juz-rozpalilo-sie-ognisko.txt
new file mode 100644
index 0000000..25861b4
--- /dev/null
+++ b/piosenki/1-juz-rozpalilo-sie-ognisko.txt
@@ -0,0 +1,40 @@
+.PIOSENKA "Już rozpaliło się ognisko"
+
+Już rozpaliło się ognisko
+
+Dając nam dobrej wróżby znak
+
+Siedliśmy przy nim wszyscy blisko
+
+Bo w całej Polsce siedzą tak
+
+
+.RS
+Siedzą harcerze przy płomieniach
+
+Ciepły blask ognia skupia ich
+
+Wszystko, co złe, to szuka cienia
+
+Do światła dobro garnie się
+.RE
+
+
+Mówiłeś, druhu komendancie,
+
+Że zaufanie do nas masz
+
+Że wierzysz w nasze szczere chęci
+
+Wszak ty harcerskie serca znasz
+
+
+.RS
+Warunki tylko warunkami
+
+Od dawna już słyszymy to
+
+Lecz my jesteśmy harcerzami
+
+I zwyciężymy wszelkie zło
+.RE
diff --git a/piosenki/2-plonie-ognisko-i-szumia-knieje.txt b/piosenki/2-plonie-ognisko-i-szumia-knieje.txt
new file mode 100644
index 0000000..a58fa58
--- /dev/null
+++ b/piosenki/2-plonie-ognisko-i-szumia-knieje.txt
@@ -0,0 +1,60 @@
+.PIOSENKA "Płonie ognisko i szumią knieje"
+
+Płonie ognisko i szumią knieje
+
+Drużynowy jest wśród nas.
+
+Opowiada starodawne dzieje,
+
+Bohaterski wskrzesza czas.
+
+
+.RS
+O rycerstwie spod kresowych stanic,
+
+O obrońcach naszych polskich granic,
+
+A ponad nami wiatr szumny wieje,
+
+I dębowy huczy las.
+.RE
+
+
+Już do odwrotu głos trąbki wzywa,
+
+Alarmując ze wszech stron.
+
+Wstaje wiara w ordynku szczęśliwa,
+
+Serca biją w zgodny ton.
+
+
+.RS
+Każda twarz się z uniesienia płoni,
+
+Każdy laskę krzepko dzierży w dłoni,
+
+A z młodzieńczej się piersi wyrywa,
+
+Pieśń potężna pieśń jak dzwon.
+.RE
+
+
+Zgasło ognisko i szumią knieje,
+
+Spojrzyj weń ostatni raz.
+
+Niech ci w duszy radośnie zanuci,
+
+Że na zawsze łączą nas:
+
+
+.RS
+Wspólne troski i radości życia,
+
+Serc harcerskich zjednoczone bicia.
+
+I ta przyjaźń najszczersza prawdziwa,
+
+Którą Bóg połączył nas.
+.RE
diff --git a/piosenki/3-wspominajka.txt b/piosenki/3-wspominajka.txt
new file mode 100644
index 0000000..4d0e52b
--- /dev/null
+++ b/piosenki/3-wspominajka.txt
@@ -0,0 +1,39 @@
+.PIOSENKA Wspominajka
+
+Już niedługo nie starczy palcy u rąk,
+
+by policzyć obozy, na których już byłeś.
+
+Chociaż myślisz, że to wystarczy,
+
+innym razem, że chciałbyś tak wciąż.
+
+Dzisiaj przyda się poczynić mały bilans tych,
+
+niezapomnianych dni...
+
+
+Mniejsza już o imiona jezior i wsi,
+
+każde z nich przypomina nastroje i twarze.
+
+Nie wiesz czemu pamiętasz motyla w słońcu,
+
+a nie to, jak wyglądały dni.
+
+Najpierw, gdy myślałes, że sznur szary najgorszy,
+
+potem, gdy chciałeś go mieć...
+
+
+Lata biegną prędko, aż zapiera dech,
+
+granatowa chusta już prawie jest biała.
+
+Kiedy wspólne zmęczenie dawało przyjaźń,
+
+chciałeś, by zawsze było tak.
+
+I ten cud wciąż trwa, że tak różni ludzie
+
+wciąż ze sobą chcą być...
diff --git a/piosenki/czuwajcie.txt b/piosenki/czuwajcie.txt
new file mode 100644
index 0000000..636de82
--- /dev/null
+++ b/piosenki/czuwajcie.txt
@@ -0,0 +1,48 @@
+.PIOSENKA Czuwajcie
+
+Strzegli obrońcy murów swego miasta
+
+codzień na murach przelewali krew
+
+stawali oko w oko z wrogiem ze słabością
+
+wróg był okrutny obiecał miastu rzeź
+
+Zbudź się żołnierzu wstań do stu kartaczy
+
+cóż że to trzecia twego czuwania noc
+
+jeżeli nie chcesz na płaczące dzieci patrzeć
+
+gotowy na odparcie wroga bądź
+
+
+.RS
+Czuwajcie w nocy czuwajcie w dzień
+
+nie dajcie wrogu bram miasta przejść
+
+czuwajcie we dnie czuwajcie w noc
+
+w naszym czuwaniu jest wielka moc
+.RE
+
+
+Dzisiaj patrząc na miasta stare mury
+
+szukasz na cegłach śladów krwawych dni
+
+myślisz czy byłbym tak dzielny jak żołnierz który
+
+broniąc wolności walczył nie szczędząc krwi
+
+Każdy ma swój warowny mur i miasto
+
+każdy z nas w coś wierzy czegoś chce
+
+broń mnie więc Boże bym którejś nocy nie zasnął
+
+gdy wróg pod murem mym przyczaji się
+
+
+.I "Ref: Czuwajcie..."
diff --git a/piosenki/kantyczka-z-lotu-ptaka.txt b/piosenki/kantyczka-z-lotu-ptaka.txt
new file mode 100644
index 0000000..c5885bb
--- /dev/null
+++ b/piosenki/kantyczka-z-lotu-ptaka.txt
@@ -0,0 +1,126 @@
+.PIOSENKA "Kantyczka z lotu ptaka"
+
+
+Patrz mój dobrotliwy Boże
+
+na swój ulubiony ludek,
+
+Jak wychodzi rano w zboże
+
+zginać harde karki z trudem.
+
+Patrz, jak schyla się nad pracą,
+
+jak pokornie klęski znosi
+
+I nie pyta - Po co? Za co?
+
+Czasem o coś Cię poprosi:
+
+
+Ujmij trochę łaski nieba!
+
+Daj spokoju w zamian, chleba!
+
+Innym udziel swej miłości!
+
+Nam - sprawiedliwości!
+
+
+Smuć się, Chryste Panie w chmurze
+
+widząc, jak się naród bawi,
+
+Znowu chciałby być przedmurzem
+
+i w pogańskiej krwi się pławić.
+
+Dymią kuźnie i warsztaty,
+
+lecz nie pracą a - skargami,
+
+Że nie taka, jak przed laty
+
+łaska Twoja nad hufcami:
+
+Siły grożą Ci nieczyste
+
+daj nam wsławić się, o Chryste!
+
+Kalwin, Litwin nam ubliża!
+
+Dźwigniem ciężar Krzyża!
+
+Załam ręce Matko Boska,
+
+upadają obyczaje,
+
+Nie pomogła modłom chłosta
+
+młodzież w szranki ciała staje.
+
+W nędzy gzi się krew gorąca
+
+bez sumienia, bez oddechu,
+
+Po czym z własnych trzewi strząsa
+
+niedojrzały owoc grzechu.
+
+
+
+Co zbawienie nam, czy piekło!
+
+Byle życie nie uciekło!
+
+Jeszcze będzie czas umierać!
+
+Żyjmy tu i teraz!
+
+
+
+Grzmijcie gniewem Wszyscy Święci,
+
+handel lud zalewa boży
+
+Obce kupce i klienci
+
+w złote wabią go obroże.
+
+Liczy chciwy Żyd i Niemiec
+
+dziś po ile polska czystość;
+
+Kupi dusze, kupi ziemie
+
+i zostawi pośmiewisko...
+
+
+
+Co nam hańba, gdy talary
+
+Mają lepszy kurs od wiary!
+
+Wymienimy na walutę
+
+Honor i pokutę!
+
+
+
+Jeden naród, tyle kwestii!
+
+Wszystkich naraz nie wysłuchasz!
+
+Zadumali się Niebiescy
+
+w imię Ojca, Syna, Ducha...
+
+
+
+Co nam hańba, gdy talary
+
+Mają lepszy kurs od wiary!
+
+Wymienimy na walutę
+
+Honor i pokutę!
diff --git a/piosenki/maly_oboz.txt b/piosenki/maly_oboz.txt
new file mode 100644
index 0000000..e90f4f6
--- /dev/null
+++ b/piosenki/maly_oboz.txt
@@ -0,0 +1,47 @@
+.PIOSENKA "Mały Obóz"
+
+.C C
+Kiedy razem ze skowronkiem
+.C Em
+powitamy nowy dzień
+
+.C C7
+Rosy z trawy się napijesz,
+.C F
+pierwszy słońca promień zjesz.
+
+.C Fm
+Potem wracać trzeba
+.C C
+będzie,
+.C Gm
+pożegnamy rzekę,
+.C D
+las.
+
+.C Dm
+Bądźcie zdrowi nasi bracia,
+.C G
+bądźcie zdrowi,
+.C G7
+na nas czas.
+
+
+.RS
+Ustawimy mały obóz, bramę zbudujemy z serc,
+
+A z tych dusz co tak gorące zbudujemy sobie piec.
+
+Rozpalimy mały ogień, a w tym ogniu będziesz piekł
+
+Naszą przyjaźń która łączy, która da ci to co chcesz.
+.RE
+
+
+My kiedyś powrócimy, nie za rok no to za dwa
+
+Więc dlaczego płacze rzeka, a więc czemu szumi las.
+
+Wszak przyjaźni naszej wielkiej nie rozłączy promień zła,
+
+Ona mocna jest bezczelnie, więc my wszyscy jeszcze raz.
diff --git a/piosenki/wedrowanie.txt b/piosenki/wedrowanie.txt
new file mode 100644
index 0000000..90ceec1
--- /dev/null
+++ b/piosenki/wedrowanie.txt
@@ -0,0 +1,93 @@
+.PIOSENKA Wędrowanie
+
+
+.C Am
+Rozwichrzone
+.C G
+nad głową
+.C E
+sosny
+.C Am
+rosochate,
+
+.C Am
+Biegną niebem
+.C G
+chmurki,
+.C E
+owieczki
+.C Am
+skrzydlate,
+
+.C C
+Senne oko
+.C F
+jeziora,
+.C G
+zda się,
+.C C
+na wpół
+.C E
+drzemie,
+
+.C Am
+Kolorowe
+.C Dm
+sady słodkie
+.C E
+niosą
+.C Am
+brzemię.
+
+
+.RS
+.C C
+A nam czegóż
+.C G
+to więcej
+.C C
+potrzeba?
+
+.C Am
+Po \(em
+.C E7
+wiedz
+.C Am
+nam!
+
+.C C
+Powiedz nam
+.C G
+lesie
+.C F
+i drogo
+.C C
+piaszczysta,
+
+.C Am
+Powiedz,
+.C E7
+powiedz,
+.C Am
+nam. (bis)
+.RE
+
+
+Połoniny zielone, przepastne doliny,
+
+Ukwiecone łąki, strojne jak dziewczyny,
+
+Płaczka wierzba przysiada na przydrożnym rowie,
+
+Matka żegnająca ruszających w drogę.
+
+
+.RS
+Przemierzamy drożyny jak wędrowne ptaki,
+
+Co na niebie kluczem wyznaczają szlaki.
+
+Dokąd, dokąd tak pędzisz, uskrzydlony bracie?
+
+Pędzisz nie bez celu, już we krwi to macie.
+.RE
diff --git a/piosenki/zielony-mundur.txt b/piosenki/zielony-mundur.txt
new file mode 100644
index 0000000..7d00f14
--- /dev/null
+++ b/piosenki/zielony-mundur.txt
@@ -0,0 +1,70 @@
+.PIOSENKA "Zielony mundur"
+
+Dawno minął czas tych dziecięcych zabaw,
+
+Z krótkich spodni już wyrósł każdy z nas.
+
+Chciałbyś jeszcze komuś zrobić jakiś kawał,
+
+Lecz coś Ci odpowie - ile ty masz lat...
+
+Znów pewnie wysłuchasz zbyt długie kazanie:
+
+O zdrowiu, o książkach - pomyśleć strach.
+
+O piciu, paleniu i złym zachowaniu,
+
+Posłuchasz, pomyślisz i westchniesz tak...
+
+
+.RS
+Ach, jak bardzo chciałbym mieć
+
+zielony mundur swój
+
+i plecak też, ze stelażem połamanym jak drut.
+.RE
+
+
+Byłeś jeszcze zuchem, gdy dostałeś mundur,
+
+Trochę później plecak - minął czasu szmat.
+
+Patrzysz - w kącie szafy. Cóż to? Ale heca !
+
+To Twój stary mundur, obraz tamtych lat...
+
+Gdy szedłeś przed siebie ze swoim plecakiem,
+
+Twą drogę wyznaczał kolorowy szlak.
+
+Z przygodą, piosenką i czapką na bakier,
+
+Odkrywał wciąż będziesz jakiś nowy świat...
+
+
+.RS
+Ach, jak bardzo...
+.RE
+
+
+Nie ma na co czekać, nie ma co rozważać.
+
+Po co dłużej zwlekać? Jaki problem masz?
+
+Ty wciąż jesteś młody - to świat się postarzał.
+
+Zrozumiesz to wszystko, gdy zatrzymasz czas...
+
+I pójdziesz przed siebie ze swoim plecakiem,
+
+Twą drogę wyznaczy kolorowy szlak.
+
+Z przygodą, piosenką i czapką na bakier,
+
+Odkrywał wciąż będziesz jakiś nowy świat...
+
+
+.RS
+Ach, jak bardzo...
+.RE
diff --git a/piosenki/zielony-plomien.txt b/piosenki/zielony-plomien.txt
new file mode 100644
index 0000000..77a441b
--- /dev/null
+++ b/piosenki/zielony-plomien.txt
@@ -0,0 +1,45 @@
+.PIOSENKA "Zielony płomień"
+
+.C Am
+W dąbrowy
+.C G
+gęstym listowiu
+.C Am
+\^\^\^błyska zielona skra
+
+Trzepoce z wiatrem jak płomień mundur harcerski nasz
+
+Czapka troszeczkę na bakier dusza rogata w niej
+
+Wiatr polny w uszach i ptaki w pachnących włosach drzew
+
+
+.RS
+Tam gdzie się kończy horyzont leży nieznany ląd
+
+Ziemia jest trochę garbata więc go nie widać stąd
+
+Kreską przebiega błękitną strzępioną pasmem gór
+
+Żeglują ku tej granicy białe okręty chmur
+.RE
+
+
+Gdzie niskie niebo usypia na rosochatych pniach
+
+Gdziekolwiek namiot rozpinam będzie kraina ta
+
+Zieleń o zmroku wilgotna z niebieską plamką dnia
+
+Cisza jak gwiazda ogromna w grzywie złocistych traw
+
+
+.RS
+W dąbrowy gęstym listowiu błyska zielona skra
+
+Trzepoce ogień zielony mundur harcerski nasz
+
+Czapka troszeczkę na bakier lecz nie poprawiaj jej
+
+Polny za uchem masz kwiatek duszy rogatej lżej
+.RE
diff --git a/source.tmac b/source.tmac
new file mode 100644
index 0000000..254d3e5
--- /dev/null
+++ b/source.tmac
@@ -0,0 +1,5 @@
+.de SOURCE
+.so \\$1
+.br
+.bp
+..
diff --git a/spiewnik.idx.do b/spiewnik.idx.do
new file mode 100644
index 0000000..9c662fb
--- /dev/null
+++ b/spiewnik.idx.do
@@ -0,0 +1,3 @@
+redo-ifchange index.ms
+cat spiewnik.ms | soin | pic | tbl | eqn | roff -mpost -ms 2> spiewnik.preidx > /dev/null
+cat spiewnik.preidx | grep '^INDEX' | sed 's/^INDEX//' > spiewnik.idx
diff --git a/spiewnik.ms b/spiewnik.ms
new file mode 100644
index 0000000..3af7db9
--- /dev/null
+++ b/spiewnik.ms
@@ -0,0 +1,66 @@
+.\" Page setup
+.pl 8.27i
+.ps 12
+.nr PS 12
+.vs 10
+.nr VS 10
+.ll 4.83i
+.nr LL 4.83i
+.po 0.5i
+.nr PO 0.5i
+.nr HM 0.5i
+.nr FM 0.8i
+.fp - R NimbusRoman-Regular
+.fp - B NimbusRoman-Bold
+.fp - I NimbusRoman-Italic
+.\" macros used for building the toc
+.so tmac.toc
+.ds toc.tl Spis treści
+.\" Change headings to work with toc
+.rn SH SH_
+.de SH
+.  ps +3
+.  B "\\$*"
+.  ps
+.	 toc.mark "\\$*"
+..
+.de blank
+.  nr blankreg +1
+.  sp 0.2
+.  if \\n[blankreg]>1 .sp 0.5
+..
+.blm blank
+.de C
+.  if \\n[blankreg] \{
+.    sp 0.6
+.    nr blankreg 0
+\}\c
+.I \v'-1.1em'\\$1\h'-\w'\\$1'u'\h'-42u'\v'1.1em'
+..
+.de PIOSENKA
+. SH "\\$*"
+..
+.
+.
+.
+.ds CH
+.ad c
+19 Poznańska Drużyna Harcerzy “Puszcza”
+.sp 16
+.ps +16
+Śpiewnik
+.ps
+.br
+.sp 32
+Obóz Spore 2021
+.br
+.ad b
+.bp
+.ds LF \v'-0.2i'\l'4.83i'
+.ds CF \v'1.5'%
+
+.so index.ms
+
+.\" This is an index that is generated on the first pass of this file
+.so spiewnik.idx
+.toc
diff --git a/spiewnik.pdf.do b/spiewnik.pdf.do
new file mode 100644
index 0000000..57eb4c5
--- /dev/null
+++ b/spiewnik.pdf.do
@@ -0,0 +1,2 @@
+redo-ifchange spiewnik.ps
+ps2pdf -dPDFSETTINGS=/prepress -dEmbedAllFonts=true spiewnik.ps spiewnik.pdf
diff --git a/spiewnik.ps.do b/spiewnik.ps.do
new file mode 100644
index 0000000..9cfba33
--- /dev/null
+++ b/spiewnik.ps.do
@@ -0,0 +1,2 @@
+redo-ifchange spiewnik.idx
+cat spiewnik.ms | soin | pic | tbl | eqn | roff -mpost -ms | post -pa5
diff --git a/tmac.toc b/tmac.toc
new file mode 100644
index 0000000..ca6e29a
--- /dev/null
+++ b/tmac.toc
@@ -0,0 +1,48 @@
+.\" generate toc
+.de toc.gen
+.	nr toc.i \\$1
+.	br
+.	mk
+.	nr toc.ll (\\n[.l]u-\w'\\*[toc.\\n[toc.i].name]')
+.	nr toc.ll (\\n[toc.ll]u-\w'\\n[toc.\\n[toc.i].num]')
+.	ad l
+.	post.url "#toc.\\n[toc.i]" "\\*[toc.\\n[toc.i].name]"
+\v'-0em'\l'\\n[toc.ll]u.'
+.	br
+.	rt
+.	ad r
+.	br
+\\n[toc.\\n[toc.i].num]
+.	nr toc.i +1
+.	if !(\\n[toc.i]=\\n[toc.total]) \{\
+.   sp 0.5
+.		toc.gen \\n[toc.i]
+.	\}
+..
+.\" add to toc
+.de toc.mark
+.	post.mark "\\$*"
+.	post.name "toc.\\n[toc.idx]"
+.	tm INDEX.ds toc.\\n[toc.idx].name \\$*
+.	tm INDEX.nr toc.\\n[toc.idx].num \\n[.%]
+.	nr toc.idx +1
+.	tm INDEX.nr toc.total \\n[toc.idx]
+.	tm INDEX.nr toc.init 1
+..
+.\" wraper for toc
+.de toc
+.	nr toc.oldad \\n(.j
+.	if \\n[toc.init] \{\
+.		sp
+.		ce
+.ft B
+.ps +2
+\\*[toc.tl]
+.ft R
+.sp 2
+.		toc.gen 0
+.	\}
+.	br
+.	ad \\n[toc.oldad]
+..
+.ds toc.tl TABLE OF CONTENTS