#!/bin/sh -e

PROG=$(basename $0)

usage ()
{
	cat << HELP
Usage: $PROG [options]

Test driver for 'pwebmac.tex' in combination with various TeX engines.
Produce TeX output in DVI, PDF or HINT format from a set of C/WEB programs
included in the 'TeX Live' source tree.

Options are (--long options only with Linux-getopt):
	-c, --changes		Apply change file to C/WEB source
	-f, --files STRING	Process only subset of C/WEB programs
	-h, --help		Print this help message and exit
	-n, --new		Use 'pwebmac' instead of 'webmac'
	-o, --outdir ARG	Create tarballs in path ARG
	-p, --pdftocfront	Place TOC page at the front (PDF only)
	-t, --tex ARG		Use TeX variant ARG=[(hi|pdf|xe)]tex
	-v, --validpdf		Use correct number of entries in NOS node

Public domain.  Originally written by Andreas Scherer, 2020.
HELP
}

LONGOPTS=changes,files:,help,new,outdir:,pdftocfront,tex:,validpdf
SHRTOPTS=cf:hno:pt:v

CHANGES= # apply changefile to C/WEB source
FILESELECT=false # user-defined '--files' selection
NEW=false # '\input pwebmac' instead of '\input webmac' for PDF et al.
OUTDIR=. # path where the resulting tarballs are placed
PDFTOCFRONT=false # push table-of-contents to front of PDF output
TEX=tex # or 'pdftex' or 'xetex' or 'hitex' or 'luatex'
VALID=false # give 'pdftex' a chance to produce valid output

# Extra material -- unpublished
LOCALSTUFF=/opt/github/web

# Initial list of C/WEB sources to process, overridable with option '-f':
KNUTHWHERE=$(locate /bibtex.web)
if [ -z "$KNUTHWHERE" ]
then echo "$PROG: Can't locate the TeX Live source tree!" >&2; exit 1
fi
KNUTHWARE=$(dirname $KNUTHWHERE)

FILES="$KNUTHWARE/*.web pdftex.web xetex.web twill"
WEBINPUTS=$KNUTHWARE//:

FILES="$FILES common ctangle cweave ctwill refsort twinx ctie tie hitex \
	mp mpost mpmath mpmathbinary mpmathdecimal mpmathdouble mpstrings tfmin"
CWEBINPUTS=$KNUTHWARE//:

KNUTHWHERE=$(locate /glue.web)
if [ -n "$KNUTHWHERE" ]
then
	FILES="$FILES $KNUTHWHERE"
	WEBINPUTS=$(dirname $KNUTHWHERE):$KNUTHWARE//:
fi

export WEBINPUTS CWEBINPUTS

getopt -T >/dev/null && true # keep going

if [ $? -eq 4 ] # Check for Linux-getopt with extensions
then OPTS=$(getopt -n $PROG -o $SHRTOPTS -l $LONGOPTS -- "$@")
else OPTS=$(getopt $SHRTOPTS $*)
fi

if [ $? -eq 0 ] # Check return code from getopt
then eval set -- $OPTS
else echo "Failed to parse options." >&2; exit 1
fi

while true
do
	case "$1" in
		-c | --changes ) CHANGES="-changes"; shift ;;
		-f | --files ) FILES="$2"; FILESELECT=true; shift 2 ;;
		-h | --help ) usage; exit 0 ;;
		-n | --new ) NEW=true; shift ;;
		-o | --outdir ) OUTDIR="$2"; shift 2 ;;
		-p | --pdftocfront ) PDFTOCFRONT=true; shift ;;
		-t | --tex ) TEX=$2; shift 2 ;;
		-v | --validpdf ) VALID=true; shift ;;
		-- ) shift; break ;;
		* ) usage; exit 1 ;;
	esac
done

CWEAVE="cweave -f +lX +bph"
CTWILL="ctwill -f +lpdf +bph"
HITEX="hitex --compress"
PAX="pax -wvzf"
PDF=pdf # default extension for 'knuth-pdf'
SED_I="sed -i" # non-GNU-sed requires an extra '' argument for '-i' option.
WEAVE=weave
XETEX=xetex

case "$TEX" in
	hitex ) # HINT format
		CTWILL="$CTWILL +P"
		TEX="$HITEX"
		PDF=hnt # default extension for 'knuth-hint'
		PDFTOCFRONT=false # use 'hintview -h' to start with TOC page
		VALID=false ;; # HiTeX has no command-line option '--shell-escape'

	pdftex | luatex ) # actually only necessary for 'pwebmac.tex'
		VALID=true ;;

	* ) # plain TeX and XeTeX use different approaches
		[ tex = "$TEX" ] && XETEX="$XETEX --no-pdf"
			# XeTeX's extended DVI format
		VALID=false ;;
esac

# Valid PDF output from 'pdftex' and 'luatex': In 'pwebmac.tex' set '\countD'
# to the actual number of @<named modules@>, not the number of all sections.
if $VALID && { [ pdftex = "$TEX" ] || [ luatex = "$TEX" ]; }
then
	NEW=true # PDF output requires 'pwebmac.tex'
	TEX="$TEX --shell-escape"
fi

# Use alternative TeX macros more suited for PDF output.
[ -n "$CHANGES" ] && NEW=true
$NEW && WEAVE="$WEAVE -p"

# Loop over WEB and CWEB programs we want to get formatted
for f in $FILES
do
	f=$(basename $f .web)

	case $f in
		pdftex ) # Fix several 'Overfull \hbox'es
			tie -m $f.web $f.web $LOCALSTUFF/$f.ch ;;

		mp | mpost | mpmath* | mpstrings | tfmin )
			# Beautifications for MetaPost
			tie -m $f.w $f.w $LOCALSTUFF/$f.ch ;;

		weave | twill )
			if [ "$HITEX" = "$TEX" ] # Fix non-constant factor
			then
				cp $KNUTHWARE/weave.web .
				$SED_I weave.web -e 's/\\the\\hsize/460pt/'
			fi ;;
	esac

	if [ -n "$CHANGES" ]
	then
		case $f in
			# These are changes in and of themselves
			ctwill | twill | glue | hitex | mp | mpost | \
				mpmath* | mpstrings | tfmin ) continue ;;

			# CWEB programs have individual changefiles
			common ) $CWEAVE $f comm-w2c ;;
			ctangle ) $CWEAVE $f ctang-w2c ;;
			cweave ) $CWEAVE $f cweav-w2c ;;
			refsort | twinx ) $CWEAVE $f $f ;;
			ctie ) $CWEAVE $f $f-k ;;
			tie ) $CWEAVE $f $f-w2c ;;

			# main WEB programs have complex change files
			tex | mf | pdftex | xetex )
				WEBINPUTS=.:$KNUTHWARE/../../Work//:$WEBINPUTS: \
				$WEAVE $f $f-final ;;

			# all other WEB codes have singular changefiles
			* ) $WEAVE $f $f ;;
		esac

		# only document changed modules/sections
		$SED_I $f.tex -e '/\\let\\maybe/s/\\iftrue/\\iffalse/'
	else # -z $CHANGES
		case $f in
			ctwill ) # apply tons of editorial changes to 'ctwill.w'
				[ "$HITEX" = "$TEX" ] &&
					ctie -m $f.w cweave.w $f-w2c.ch $f-hint.ch ||
					ctie -m $f.w cweave.w $f-w2c.ch $f-mini.ch
				$CTWILL $f # prime the pump
				$CTWILL $f ;; # get decent answers

			c* | refsort | twinx | tie ) $CWEAVE $f ;;
			hitex ) $CWEAVE $f || true ;; # lots of unused sections

			mp | mpost | mpmath* | mpstrings | tfmin )
				CWEBINPUTS=.: $CWEAVE $f ;;

			twill ) WEBINPUTS=.:$WEBINPUTS \
				tie -c $f.ch weave.web weave.ch weav-$f.ch
				WEBINPUTS=.:$WEBINPUTS $WEAVE weave $f $f ;;

			pdftex | weave ) WEBINPUTS=.:$WEBINPUTS $WEAVE $f ;;

			* ) $WEAVE $f ;;
		esac
	fi # $CHANGES

	# 'pwebmac' is for WEB only; do nothing for CWEB programs
	if $NEW && echo $f | grep -v -q -E \
		'^c|refsort|twinx|tie|hitex|^mp|tfmin'
	then
		# timestamp on table-of-contents page or the first page
		case $f in
			bibtex | patgen | tangle | weave | twill )
				$SED_I $f.tex -e 's/\\def\\title{/\\datecontentspage\n&/' ;; # }

			mf | tex | pdftex | xetex )
				# amend '\N' redefinition for PDF outlines in
				# Metafont and TeX (also pdfTeX and XeTeX)
				# 'pwebmac' defines headers differently
				cat > texmf-pdf.sed << 'FI'
s/\\outer\\def\\N.*{/&%/
s/\\def\\rhead\({.*}\)/\\gtitle=\1\\MN#1.\\vfill\\eject/
s/\\def\\title{/\\datethis\n\\emergencystretch=.1\\hsize\n&/
FI
				# active links in PDF outlines/bookmarks
				cat > texmf-pdf.patch1 << FI
  \ifpdf{\makeoutlinetoks{[#2] #3}\outlinedone}\fi
FI
				cat >> texmf-pdf.sed << 'FI'
/\\outer\\def\\N/r texmf-pdf.patch1
s/{\\the\\pageno}/&{\\the\\toksE}/
FI
				cat > texmf-pdf.patch2 << FI
  \ifpdflua\relax\else
  \ifpdf\special{pdf: outline 0 << /Title (\the\toksE) /Dest
    [ @thispage /FitH @ypos ] >>}\fi\fi
FI
				cat >> texmf-pdf.sed << 'FI'
/\\edef\\next/r texmf-pdf.patch2
FI
				$SED_I $f.tex -f texmf-pdf.sed
				rm -f texmf-pdf.* ;;

			* ) $SED_I $f.tex -e '/\\def\\botofcontents/d' \
				-e 's/  \\centerline{\(\\hsize\)/\\def\\covernote{\1/' \
				-e 's/\(Publishing Company.}}\)}/\1\n\\datecontentspage/' \
				-e 's/\(Mathematical Society.}}\)}/\1\n\\datecontentspage/' ;;
		esac
	fi # $NEW

	# special treatment for individual C/WEB programs
	case $f in
		# replace former convention to indicate "not a title
		# page" to include page headers for table-of-contents;
		# purge conflict between bibtex.web and webmac.tex
		# 'E' no longer free to be active character
		# fix table-of-contents page for bibtex
		# FIX: don't wait for Oren Patashnik.
		bibtex ) $SED_I $f.tex -e 's/\\def\\titlepage{F}/\\titletrue/'
			[ -z "$CHANGES" ] && $SED_I $f.tex -e "71,78d" ;;

		# FIX: GFtoDVI uses 'Metafont' in a module name;
		# this should appear correctly in the bookmarks, too.
		gftodvi ) $NEW && $SED_I $f.tex \
			-e 's/\\def\\(/\\ifpdf\\sanitizecommand\\MF{Metafont}\\fi\n\n&/' ;; # )

		# FIX: 'glue.web' obviously uses an old 'webmac.tex'.
		glue ) $SED_I $f.tex -e 's/titlefalse/titletrue/' \
			-e 's/\\def\\title{GLUE}/&\n\\pageno=\\contentspagenumber \\advance\\pageno by1\\relax/' ;;

		# FIX: Metafont uses '\over' in several module names;
		# this should appear correctly in the bookmarks, too.
		mf ) $NEW && $SED_I $f.tex \
			-e 's/\\def\\(/\\ifpdf\n\\sanitizecommand\\MF{Metafont}\n\\sanitizecommand\\over{\/}\n\\sanitizecommand\\langle{<}\n\\sanitizecommand\\rangle{>}\n\\fi\n\n&/' ;; # )

		# FIX: MFT uses '\pb' in several module names;
		# this should appear correctly in the bookmarks, too.
		mft ) $NEW && $SED_I $f.tex \
			-e 's/\\def\\pb.*/&\n\\ifpdf\\sanitizecommand\\pb{\|...\|}\\fi/' ;;

		# FIX: pdfTeX uses '\pdfTeX' in section names; these should
		# appear correctly in the bookmarks, too.
		pdftex ) $NEW && $SED_I $f.tex \
			-e 's/\\def\\pdfeTeX{pdf\\eTeX}/&\n\\ifpdf\n\\sanitizecommand\\pdfTeX{pdfTeX}\n\\sanitizecommand\\eTeX{e-TeX}\n\\sanitizecommand\\over{\/}\n\\fi/' ;;

		# FIX: weave uses '\max' in name of module 173; this should
		# appear correctly in the bookmarks, too.
		weave ) $NEW && $SED_I $f.tex \
			-e 's/\\def\\({}/\\ifpdf\\sanitizecommand\\max{max}\\fi\n&/' ;; # )

		# FIX: purge obsolete macros from XeTeX.
		# FIX: XeTeX uses '\pdfTeX' from section 114, which is not
		# changed and thus 'disappears'; repeat in preamble.
		# FIX: apply '\sanitizecommand' for bookmarks.
		xetex ) $SED_I $f.tex -e '/\\input xewebmac/d' \
			-e 's/\\let\\maybe/\\def\\pdfTeX{pdf\\TeX}\n&/'
			$NEW && $SED_I $f.tex \
				-e 's/\\def\\pdfTeX{pdf\\TeX}/&\n\\ifpdf\\sanitizecommand\\pdfTeX{pdfTeX}\\fi/' \
				-e 's/\\def\\eTeX/\\ifpdf\n\\sanitizecommand\\eTeX{e-TeX}\n\\sanitizecommand\\over{\/}\n\\fi\n&/' ;;

		# timestamp on table-of-contents page or the first page
		hitex | mp ) $SED_I $f.tex -e 's/\\def\\topofcontents/\\datethis\n\\emergencystretch=.1\\hsize\n&/' ;;
		common | ctangle | cweave | ctie | tie ) $SED_I $f.tex -e 's/\\def\\botofcontents/\\datethis\n&/' ;;
		mpost | mpmath* | mpstrings | tfmin ) $SED_I $f.tex -e 's/\\def\\title{/\\datecontentspage\n\n&/' ;; # }
	esac

	# shift table-of-contents pages to the front in PDF
	if $PDFTOCFRONT && echo $f | grep -v -q -E 'ctwill|hitex'
	then $SED_I $f.tex \
		-e '0,/\\N[1{]/s/\\N[1{]/\\input pdfwebtocfront\n\n&/'
	fi # $PDFTOCFRONT

	if [ -n "$CHANGES" ] || [ twill = "$f" ]
	then
		# We add an Editor's Note and the list of changed
		# sections on the ToC page.
		cp $LOCALSTUFF/editorsnote.tex .

		case $f in
			mf ) $SED_I $f.tex -e 's/\\datethis/\\input editorsnote.tex\n\\def&{\\def\\startsection{\\leftline{\\sc\\today\\ at \\hours}\n  \\medskip\\editorsnote\\readchanges\\bigskip\n  \\let\\startsection=\\stsec\\stsec}}\n&/' ;;

			# TeX and XeTeX grow significantly for TeX Live
			# so there's enough room on the last ToC page.
			pdftex | tex | xetex ) $SED_I $f.tex \
				-e '/\\datethis/d' \
				-e 's/\(\\def\\botofcontents\).*/\\input editorsnote.tex\n\1{\\hsize6.5in\\vskip 0pt plus 1filll\n  \\editorsnote\\readchanges\\medskip\\noindent\\sc\\today\\ at \\hours}/' \
				-e 's/\\input pdfwebtocfront/&\n\n\\def\\tocpages{2}/' ;;

			bibtex | patgen | tangle | weave | refsort | twinx ) $SED_I $f.tex -e 's/\\date.*/\\input editorsnote\n\\def\\covernote{\\vbox{\\editorsnote\\readchanges\\par}}\n\\datecontentspage/' ;;

			common | ctangle | cweave | ctie | tie ) $SED_I $f.tex \
				-e 's/\\def\\covernote/\\input editorsnote.tex\n&/' \
				-e 's/^}}/\\bigskip\\editorsnote\\readchanges\\par&/' ;;

			twill ) $SED_I $f.tex \
				-e 's/\\datecontentspage/\\input editorsnote.tex\n\\def\\covernote{\\vbox{\\editorsnote\\readchanges\\par}}\n&/' ;;

			* ) $SED_I $f.tex \
				-e 's/\\def\\title{/\\input editorsnote.tex\n&/' \
				-e 's/\\vbox{\\ninerm/&\\editorsnote\\readchanges\\medskip/' ;;
		esac
	fi # $CHANGES

	case $f in
		ctwill ) # gives two different outcomes
			if [ "$HITEX" = "$TEX" ] # sort mini-indexes
			then # directly in the TeX file
				( ctwill-proofsort < $f.tex ) 1<> $f.tex
			else # in the TeX-created .ref file
				$TEX $f
				ctwill-refsort < $f.ref > $f.sref
			fi
			$TEX $f ;;

		* ) # run TeX twice
			if $PDFTOCFRONT || [ -n "$CHANGES" ]
			then # only XeTeX can process XETEX.WEB
				[ xetex = $f ] && $XETEX $f || $TEX $f
			fi
			[ xetex = $f ] && $XETEX $f || $TEX $f ;;
	esac
done

# create tarballs w/o changes for publication
if ( $PDFTOCFRONT || [ "$HITEX" = "$TEX" ] ) && ! $FILESELECT
then
	if [ -z "$CHANGES" ]
	then
		export TEXINPUTS=.:$(kpsewhich --var-value=TEXMFDIST)//:$KNUTHWARE//
		touch pages.tex # let 'manmac' produce output at all

		$TEX -jobname=errorlog $LOCALSTUFF/Xerrorlog.tex
		for f in one two three four five six seven eight nine ten \
			eleven twelve
		do $TEX -jobname errata.$f errata.$f
		done
		$TEX errata
		$PAX "$OUTDIR/errata.tar.gz" -s ,^,errata/, err*.$PDF

		$PAX "$OUTDIR/hitex.tar.gz" -s ,^,hitex/, hitex.$PDF
		$PAX "$OUTDIR/mp.tar.gz" -s ,^,mp/, mp.$PDF mpost.$PDF

		# Finally, build the remaining documents
		# * TeX and Metafont test routines
		# * WEB and CWEB manuals
		rm -f trapman.tex webman.tex cwebman.tex

		# FIX: Prepare 'trapman' for automatic processing; several
		# input files are renamed in TeX Live (in fact, there are
		# additional files for MetaPost).
		# Prepare 'webman' with section links and bookmarks.
		for f in trapman webman
		do
			f=$(kpsewhich -engine tex $f)
			tie -m $(basename $f) $f $LOCALSTUFF/$(basename $f .tex).ch
		done

		# Prepare 'cwebman' with footnotes describing the extended CWEB.
		f=$(kpsewhich -engine tex cwebman)
		tie -m $(basename $f) $f $(basename $f .tex)-w2c.ch

		for f in tripman trapman webman cwebman
		do $TEX $f
		done

		$PAX "$OUTDIR/mf.tar.gz" -s ,^,mf/, mf.$PDF trapman.$PDF
		$PAX "$OUTDIR/tex.tar.gz" -s ,^,tex/, \
			glue.$PDF tex.$PDF tripman.$PDF
		$PAX "$OUTDIR/web.tar.gz" -s ,^,web/, \
			webman.$PDF tangle.$PDF weave.$PDF twill.$PDF
		$PAX "$OUTDIR/cweb.tar.gz" -s ,^,cweb/, \
			cwebman.$PDF common.$PDF ctangle.$PDF cweave.$PDF \
			ctwill.$PDF refsort.$PDF twinx.$PDF
	else # -n $CHANGES
		for f in *.$PDF
		do
			case $f in *$CHANGES.$PDF ) rm -f $f; continue ;; esac
			mv $f $(basename $f .$PDF)$CHANGES.$PDF
		done
		[ "$HITEX" = "$TEX" ] && mv -f xetex.pdf xetex$CHANGES.pdf
		$PAX "$OUTDIR/mf$CHANGES.tar.gz" -s ,^,mf/, mf$CHANGES.$PDF
		$PAX "$OUTDIR/tex$CHANGES.tar.gz" -s ,^,tex/, tex$CHANGES.$PDF
		$PAX "$OUTDIR/web$CHANGES.tar.gz" -s ,^,web/, \
			tangle$CHANGES.$PDF weave$CHANGES.$PDF
		$PAX "$OUTDIR/cweb$CHANGES.tar.gz" -s ,^,cweb/, \
			common$CHANGES.$PDF ctangle$CHANGES.$PDF \
			cweave$CHANGES.$PDF refsort$CHANGES.$PDF \
			twinx$CHANGES.$PDF
	fi # $CHANGES

	$PAX "$OUTDIR/etc$CHANGES.tar.gz" -s ,^,etc/, \
		vftovp$CHANGES.$PDF vptovf$CHANGES.$PDF
	$PAX "$OUTDIR/mfware$CHANGES.tar.gz" -s ,^,mfware/, \
		gftodvi$CHANGES.$PDF gftopk$CHANGES.$PDF \
		gftype$CHANGES.$PDF mft$CHANGES.$PDF
	$PAX "$OUTDIR/texware$CHANGES.tar.gz" -s ,^,texware/, \
		dvitype$CHANGES.$PDF pltotf$CHANGES.$PDF \
		pooltype$CHANGES.$PDF tftopl$CHANGES.$PDF
	$PAX "$OUTDIR/other$CHANGES.tar.gz" -s ,^,other/, \
		dvicopy$CHANGES.$PDF patgen$CHANGES.$PDF \
		pktogf$CHANGES.$PDF pktype$CHANGES.$PDF
	$PAX "$OUTDIR/xetex$CHANGES.tar.gz" -s ,^,xetex/, \
		xetex$CHANGES.pdf
	for f in bibtex pdftex ctie tie
	do $PAX "$OUTDIR/$f$CHANGES.tar.gz" -s ,^,$f/, $f$CHANGES.$PDF
	done

	# Notes to self:
	# (1) Create a user-friendly central entrypoint with
	#     (a) pandoc index.md -o index.pdf
	#     (b) pandoc index.md -o index.tex;
	#         pandoc index.tex -s -o index.html \
	#           --metadata title="C/WEB programs in TeX Live";
	#         rm index.tex
	# (2) Prepare a super-tarball from all the contents of these
	#     individual tarballs (42/53 and 34/54) with either of
	#     (a) pax -wzf knuth-pdf.tar.gz knuth-pdf
	#     (a') pax -wzf knuth-hint.tar.gz knuth-hint
	#     (b) zip -r knuth-pdf.zip knuth-pdf
	#     (b') zip -r knuth-hint.zip knuth-hint
fi

exit 0