# SPDX-License-Identifier: 0BSD

SHELLCHECK ?= shellcheck
MANDOC ?= mandoc
AWK ?= awk
SED ?= sed
NOLOCREGEN ?=
OUTDIR ?= out/
OBJDIR ?= $(OUTDIR)obj/
CMDDIR ?= $(OUTDIR)cmd/
LOCDIR ?= $(OUTDIR)locale/
MANDIR ?= $(OUTDIR)man/
HTMLMANDIR ?= $(OUTDIR)man-html/
HTMLMAN_OUTSIDE_FORMAT ?= https://manpages.debian.org/bullseye/%N.%S

RATRUN_RUNNERDIR ?= /usr/libexec/

DATE_EPOCH := LC_ALL=C date $(shell date --date @0 > /dev/null 2>&1 && echo "--date @" || echo "-r ")
RATRUN_VERSION ?= $(shell git describe --always)
RATRUN_DATE ?= $(shell $(DATE_EPOCH)$(shell git log -1 --no-show-signature --format=%at) +"%B %e, %Y")


BINARIES := $(wildcard *.sh)
MANPAGES := $(wildcard *.[1-8])
MANLIBS  := $(wildcard *.0)
LOCALES  := $(wildcard *.po)

.PHONY : all binaries locales clean manpages htmlpages allpages
.SECONDARY:

all : binaries locales manpages htmlpages
allpages : manpages htmlpages
clean :
	rm -rf $(OUTDIR) $(OBJDIR)


rewrap_mandirs = $(patsubst %.8,man8/%.8,$(patsubst %.7,man7/%.7,$(patsubst %.6,man6/%.6,$(patsubst %.5,man5/%.5,$(patsubst %.4,man4/%.4,$(patsubst %.3,man3/%.3,$(patsubst %.2,man2/%.2,$(patsubst %.1,man1/%.1,$(patsubst %.0,man0/%.0,$(1))))))))))
binaries  : $(patsubst %.sh,%,$(patsubst %,$(CMDDIR)%,$(BINARIES)))
locales   : $(patsubst %.po,$(LOCDIR)%/LC_MESSAGES/ratrun.mo,$(LOCALES))
manpages  : $(patsubst %,$(MANDIR)%,$(call rewrap_mandirs,$(MANPAGES)))
htmlpages : $(patsubst %,$(HTMLMANDIR)%.html,$(call rewrap_mandirs,$(MANPAGES) index.0)) $(HTMLMANDIR)style.css

# msginit -l pl_PL.UTF-8 --no-wrap -i out/obj/ratrun.pot
# https://code.djangoproject.com/ticket/4734
$(OBJDIR)ratrun.pot : $(BINARIES)
	@mkdir -p $(OBJDIR)
	$(NOLOCREGEN)xgettext --from-code=UTF-8 -c -io- $^ | $(AWK) '/^#[:.]/,0' > $@
	$(NOLOCREGEN)$(foreach l,$(LOCALES),msgmerge --backup=off --no-wrap -Uiq $(l) $(OBJDIR)ratrun.pot &&) :

# The d-v-o-s string starts at "BSD" (hence the "BSD General Commands Manual" default); we're not BSD, so hide it
# Can't put it at the very top, since man(1) only loads mdoc *after* the first mdoc macro (.Dd in our case)
$(OBJDIR)man/% : % $(MANLIBS)
	@mkdir -p $(@D) $(dir $(patsubst %,$(MANDIR)%,$(call rewrap_mandirs,$<)))
	$(AWK) '/^\.so / {print ".lf 1 " $$2; while((getline l < $$2) == 1) print l; print ".lf " NR+1 " " FILENAME; next}  {print}' $< | $(AWK) '$$0 == ".Dd" {$$2 = "$(RATRUN_DATE)"}  $$1 == ".Dt" { print ".ds doc-volume-operating-system" }  $$0 == ".Os" {$$2 = "ratrun"; $$3 = "$(RATRUN_VERSION)"}  {gsub(/@RATRUN_RUNNERDIR@/, "$(RATRUN_RUNNERDIR)"); sub(/^\^/, "\\(ha"); sub(/^~/, "\\(ti"); sub(/^`/, "\\`"); gsub(/[^\\]\^/, "&_BUT-HA_"); gsub(/[^\\]~/, "&_BUT-TI_"); gsub(/[^\\0-9]`/, "&_BUT-BACK_"); gsub(/\\\(~_BUT-TI_/, "\\(~"); gsub(/\\\[~_BUT-TI_/, "\\[~"); gsub(/\\\[=~_BUT-TI_]/, "\\[=~]"); gsub(/\^_BUT-HA_/, "\\(ha"); gsub(/~_BUT-TI_/, "\\(ti"); gsub(/`_BUT-BACK_/, "\\`"); print}' | tee $(patsubst %,$(MANDIR)%,$(call rewrap_mandirs,$<)) > $@
	! $(MANDOC) -Tlint $@ 2>&1 | grep -vF -e 'mandoc: outdated mandoc.db' -e 'STYLE: referenced manual not found' -e 'WARNING: cross reference to self' -e 'STYLE: useless macro: Tn' -e 'STYLE: input text line longer than 80 bytes:' -e 'STYLE: operating system explicitly specified: Os ratrun' -e 'ERROR: skipping insecure request: lf' -e 'ERROR: skipping unknown macro: .in'

# GNU Make needs an empty rule here so that it actually picks this up as an orderable rule, not a strict, unfulfillable, dependency
$(foreach l,1 2 3 4 5 6 7 8,$(MANDIR)man$(l)/%) : $(OBJDIR)man/%
	@

$(OBJDIR)man/index.0 : $(MANPAGES)
	@mkdir -p $(@D)
	{ \
		printf '%s\n' ".Dd $(RATRUN_DATE)" ".Dt INDEX 0" ".Os ratrun $(RATRUN_VERSION)" ".Sh NAME" ".Nm index" ".Nd ratrun $(RATRUN_VERSION) manual index" ".Sh CONTENTS" "." '.Bl -tag -compact'; \
		awk '/^\.Nm/ {match(FILENAME, /\..$$/); print ".It Xr " substr(FILENAME, 1, RSTART-1) " " substr(FILENAME, RSTART + 1); print}  /^\.Nd/ {sub(/\.Nd/, "\\(en"); print; nextfile}' $(shell printf "%s\n" $(call rewrap_mandirs,$^) | sort -n | cut -d/ -f2); \
		echo .El; \
	} > $@

# mandoc always evaluates n to true and t to false
$(foreach l,0 1 2 3 4 5 6 7 8,$(HTMLMANDIR)man$(l)/%.html) : $(OBJDIR)man/%
	@mkdir -p $(@D)
	$(SED) -e 's/^\(\.i[ef]\) n/\1 0/' $< | \
		$(MANDOC) -Thtml -Ostyle="../style.css",man="../man%S/%N.%S.html;$(HTMLMAN_OUTSIDE_FORMAT)" | \
		$(AWK) '/^<h[12]/ {in_syn = $$0 ~ /id="SYNOPSIS"/}  /^<br/ {if(in_syn) next}  {print}' | \
		$(SED) -Ee 's/ title=".."//g' -e 's/<a class="permalink" href="#([^"]*)"><span class="No" id="([^"]*)">/<a><span class="No">/g' > $@

$(HTMLMANDIR)style.css : mandoc-style.css
	@mkdir -p $(@D)
	cp $^ $@


$(CMDDIR)% : %.sh
	@mkdir -p $(@D)
	$(SED) '2a\
# ratrun $(RATRUN_VERSION) ($(RATRUN_DATE))' < $< > $@
	chmod +x $@
	$(SHELLCHECK) -xs sh $@

$(LOCDIR)%/LC_MESSAGES/ratrun.mo : %.po $(OBJDIR)ratrun.pot
	@mkdir -p $(@D)
	msgfmt -o $@ $<
