#----------------------------------------------------------------------------
#
# PostgreSQL documentation makefile
#
# doc/src/xml/Makefile
#
#----------------------------------------------------------------------------

# This makefile is for building and installing the documentation.
# When a release tarball is created, the documentation files are
# prepared using the distprep target.  In Git-based trees these files
# don't exist, unless explicitly built, so we skip the installation in
# that case.


# Make "html" the default target, since that is what most people tend
# to want to use.
html:

ALL_LINGUAS=$(shell [ -d $(srcdir)/../locale ] && ls $(srcdir)/../locale/)
NO_TEMP_INSTALL=yes

subdir = doc/src/xml
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global

XML2PO=$(top_srcdir)/doc/tools/xml2po/xml2po.py


all: html man

distprep: html distprep-man

missing := $(shell readlink -f $(missing))

ifndef DBTOEPUB
DBTOEPUB = $(missing) dbtoepub
endif

ifndef XMLLINT
XMLLINT = $(missing) xmllint
endif

ifndef XSLTPROC
XSLTPROC = $(missing) xsltproc
endif

override XSLTPROCFLAGS += --stringparam pg.version '$(VERSION)' --stringparam pg.productname '$(PACKAGE_NAME)'
XSLTPROCFLAGS_NOPROFILE := $(XSLTPROCFLAGS)
override XSLTPROCFLAGS += --stringparam profile.condition "default"
XSLT_PATH := --path $(srcdir) --path .

ifeq ($(STYLE),website)
XSLTPROC_HTML_FLAGS += --param website.stylesheet 1
endif

GENERATED_XML = version.ent \
	features-supported.xml features-unsupported.xml errcodes-table.xml

ALLXML := $(wildcard $(srcdir)/*.xml $(srcdir)/ref/*.xml) $(GENERATED_XML)

##
## All XML present & valid
##
xml-stamp: postgres.xml $(ALLXML)
	$(XMLLINT) --noout --valid --path . $<
	touch $@

##
## Man pages
##

man distprep-man: man-stamp

%/man %/distprep-man: %/man-stamp
	@[ -d $(@D) ] && echo "Target $@ created."


man-stamp: postgres.xml xml-stamp
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) $(XSLTPROC_MAN_FLAGS) stylesheet-man.xsl $<
	touch $@

%/man-stamp: %/xml-l10n-stamp
	(cd $(@D); $(XSLTPROC) $(XSLTPROCFLAGS) $(XSLTPROC_MAN_FLAGS) stylesheet-man.xsl postgres.xml)
	touch $@


##
## HTML
##

# single-page HTML
postgres.html: postgres.xml xml-stamp
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) $(XSLTPROC_HTML_FLAGS) stylesheet-single.xsl $<

%/postgres.html: %/xml-l10n-stamp
	(cd $(@D); $(XSLTPROC) $(XSLTPROCFLAGS) $(XSLTPROC_HTML_FLAGS) stylesheet-single.xsl postgres.xml)

html: html-stamp

%/html: %/html-stamp
	@[ -d $(@D) ] && echo "Target $@ created."

html-stamp: postgres.xml xml-stamp
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) $(XSLTPROC_HTML_FLAGS) stylesheet.xsl $<
	cp $(srcdir)/stylesheet.css $(wildcard $(srcdir)/*.svg $(srcdir)/*.png) html/
	touch $@

%/html-stamp: %/xml-l10n-stamp
	(cd $(@D); $(XSLTPROC) $(XSLTPROCFLAGS) $(XSLTPROC_HTML_FLAGS) stylesheet.xsl postgres.xml)
	cp $(srcdir)/stylesheet.css $(wildcard $(srcdir)/*.svg $(srcdir)/*.png) $(@D)/html/
	touch $@

htmlhelp: postgres.xml xml-stamp
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) stylesheet-hh.xsl $<
	touch $@

%/htmlhelp: %/xml-l10n-stamp
	(cd $(@D); $(XSLTPROC) $(XSLTPROCFLAGS) stylesheet-hh.xsl postgres.xml)
	touch $@

# single-page text
postgres.txt: postgres.html
	$(LYNX) -force_html -dump -nolist $< > $@

%/postgres.txt: %/postgres.html
	$(LYNX) -force_html -dump -nolist $< > $@

# Technically, this should depend on Makefile.global, but then
# version.ent would need to be rebuilt after every configure run,
# even in distribution tarballs.  So this is cheating a bit, but it
# will achieve the goal of updating the version number when it
# changes.
version.ent: $(top_srcdir)/configure
	{ \
	  echo "<!ENTITY version \"$(VERSION)\">"; \
	  echo "<!ENTITY majorversion \"$(MAJORVERSION)\">"; \
	} > $@

features-supported.xml: $(top_srcdir)/src/backend/catalog/sql_feature_packages.txt $(top_srcdir)/src/backend/catalog/sql_features.txt
	$(PERL) $(srcdir)/mk_feature_tables.pl YES $^ > $@

features-unsupported.xml: $(top_srcdir)/src/backend/catalog/sql_feature_packages.txt $(top_srcdir)/src/backend/catalog/sql_features.txt
	$(PERL) $(srcdir)/mk_feature_tables.pl NO $^ > $@

errcodes-table.xml: $(top_srcdir)/src/backend/utils/errcodes.txt generate-errcodes-table.pl
	$(PERL) $(srcdir)/generate-errcodes-table.pl $< > $@


##
## Print
##

# TODO: Generate RTF?
# RTF to allow minor editing for hardcopy

# PostScript from TeX
postgres.ps:
	$(error Invalid target;  use postgres-A4.ps or postgres-US.ps as targets)

postgres.pdf:
	$(error Invalid target;  use postgres-A4-fop.pdf or postgres-US-fop.pdf as targets)

##
## Semi-automatic generation of some text files.
##

ICONV = iconv
LYNX = lynx

# The documentation may contain non-ASCII characters (mostly for
# contributor names), which lynx converts to the encoding determined
# by the current locale.  To get text output that is deterministic and
# easily readable by everyone, we make lynx produce LATIN1 and then
# convert that to ASCII with transliteration for the non-ASCII characters.
# Official releases were historically built on FreeBSD, which has limited
# locale support and is very picky about locale name spelling.  The
# below has been finely tuned to run on FreeBSD and Linux/glibc.
INSTALL: % : %.html
	$(PERL) -p -e 's/<H(1|2)$$/<H\1 align=center/g' $< | LC_ALL=en_US.ISO8859-1 $(LYNX) -force_html -dump -nolist -stdin | $(ICONV) -f latin1 -t us-ascii//TRANSLIT > $@

INSTALL.html: standalone-install.xml installation.xml version.ent
	$(XSLTPROC) $(XSLTPROCFLAGS_NOPROFILE) $(XSLT_PATH) --stringparam profile.condition "standalone" $(XSLTPROC_HTML_FLAGS) stylesheet-single.xsl standalone-install.xml

%/INSTALL.html: %/xml-l10n-stamp
	(cd $(@D); $(XSLTPROC) $(XSLTPROCFLAGS_NOPROFILE) --stringparam profile.condition "standalone" $(XSLTPROC_HTML_FLAGS) stylesheet-single.xsl standalone-install.xml)

%/INSTALL: %/INSTALL.html
	$(PERL) -p -e 's/<H(1|2)$$/<H\1 align=center/g' $< | LC_ALL=en_US.UTF-8 $(LYNX) -force_html -dump -nolist -stdin > $@


postgres-A4.fo.tmp: postgres.xml xml-stamp
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) --stringparam paper.type A4 -o $@ stylesheet-fo.xsl $<
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) -o $@.tmp pg-customize-fo.xsl $@
	mv $@.tmp $@

postgres-US.fo.tmp: postgres.xml xml-stamp
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) --stringparam paper.type USletter -o $@ stylesheet-fo.xsl $<
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) -o $@.tmp pg-customize-fo.xsl $@
	mv $@.tmp $@

%/postgres-A4.fo.tmp: %/xml-l10n-stamp
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) --stringparam paper.type A4 -o $@ $(@D)/stylesheet-fo.xsl $(@D)/postgres.xml
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) -o $@.tmp $(@D)/pg-customize-fo.xsl $@
	mv $@.tmp $@

%/postgres-US.fo.tmp: %/xml-l10n-stamp
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) --stringparam paper.type USletter -o $@ $(@D)/stylesheet-fo.xsl $(@D)/postgres.xml
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) -o $@.tmp $(@D)/pg-customize-fo.xsl $@
	mv $@.tmp $@

FOP = fop

# reformat FO output so that locations of errors are easier to find
%.fo: %.fo.tmp
	$(XMLLINT) --format --output $@ $^

.SECONDARY: postgres-A4.fo postgres-US.fo

%-fop.pdf: %.fo
	[ -f $(@D)/fop-config.xml ] && fopconfig="-c $(@D)/fop-config.xml"; \
	JAVA_ARGS=-Xmx4096m $(FOP) $$fopconfig -fo $< -pdf $@

# TODO: Optimize performance
epub: postgres.epub
postgres.epub: postgres.xml xml-stamp
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) -o $<.tmp profiling.xsl $<
	$(DBTOEPUB) -s stylesheet-epub.xsl -o $@ $<.tmp
	rm $<.tmp

%/epub: %/postgres.epub
%/postgres.epub: %/xml-l10n-stamp
	(cd $(@D); \
	$(XSLTPROC) $(XSLTPROCFLAGS) $(XSLT_PATH) -o postgres.xml.tmp profiling.xsl postgres.xml; \
	$(DBTOEPUB) -s stylesheet-epub.xsl -o postgres.epub postgres.xml.tmp; \
	rm postgres.xml.tmp)


##
## Experimental Texinfo targets
##

DB2X_TEXIXML = db2x_texixml
DB2X_XSLTPROC = db2x_xsltproc
MAKEINFO = makeinfo

%.texixml: %.xml
	$(DB2X_XSLTPROC) -s texi -g output-file=$(basename $@) $< -o $@

%.texi: %.texixml
	$(DB2X_TEXIXML) --encoding=iso-8859-1//TRANSLIT $< --to-stdout > $@

%.info: %.texi
	$(MAKEINFO) --enable-encoding --no-split --no-validate $< -o $@


##
## Check
##

# Quick syntax check without style processing
check: xml-stamp check-tabs

##
## Install
##

install: install-html

ifneq ($(PORTNAME), sco)
install: install-man
endif

installdirs:
	$(MKDIR_P) '$(DESTDIR)$(htmldir)'/html $(addprefix '$(DESTDIR)$(mandir)'/man, 1 3 $(sqlmansectnum))
	for lngdir in $(ALL_LINGUAS); do if [ "$(call vpathsearch,$$lngdir)" ]; then $(MKDIR_P) $(addprefix '$(DESTDIR)$(mandir)'/$$lngdir/man, 1 3 $(sqlmansectnum)); fi; done

# If the install used a man directory shared with other applications, this will remove all files.
uninstall:
	rm -rf '$(DESTDIR)$(htmldir)/html/'* $(addprefix  '$(DESTDIR)$(mandir)'/man, 1/* 3/* $(sqlmansectnum)/*)
	for lngdir in $(ALL_LINGUAS); do if [ "$(call vpathsearch,$$lngdir)" ]; then rm -rf "$(DESTDIR)$(mandir)/$$lngdir"/*; fi; done


## Install html

install-html: html installdirs
	for lngdir in . $(ALL_LINGUAS); do if [ "$(call vpathsearch,$$lngdir)" ]; then $(MKDIR_P) '$(DESTDIR)$(htmldir)'/html/$$lngdir && cp -R "$(call vpathsearch,$$lngdir/html)"/* '$(DESTDIR)$(htmldir)'/html/$$lngdir/; fi; done


## Install man

install-man: man installdirs

sqlmansect ?= 7
sqlmansectnum = $(shell expr X'$(sqlmansect)' : X'\([0-9]\)')

# Before we install the man pages, we massage the section numbers to
# follow the local conventions.
#
ifeq ($(sqlmansectnum),7)
install-man:
	for lngdir in . $(ALL_LINGUAS); do if [ "$(call vpathsearch,$$lngdir)" ]; then cp -R $(foreach dir,man1 man3 man7,$(call vpathsearch,$$lngdir/$(dir))) '$(DESTDIR)$(mandir)'/$$lngdir/; fi; done

else # sqlmansectnum != 7
fix_sqlmansectnum = sed -e '/^\.TH/s/"7"/"$(sqlmansect)"/' \
			-e 's/\\fR(7)/\\fR($(sqlmansectnum))/g' \
			-e '1s/^\.so man7/.so man$(sqlmansectnum)/g;1s/^\(\.so.*\)\.7$$/\1.$(sqlmansect)/g'

man: fixed-man-stamp

fixed-man-stamp: man-stamp
	for lngdir in . $(ALL_LINGUAS); do \
		if [ -z "$(call vpathsearch,$$lngdir)" ]; then continue; fi \
		$(MKDIR_P) $(addprefix $$lngdir/fixedman/,man1 man3 man$(sqlmansectnum)); \
		for file in $(call vpathsearch,$$lngdir/man1)/*.1; do $(fix_sqlmansectnum) $$file >$$lngdir/fixedman/man1/`basename $$file` || exit; done; \
		for file in $(call vpathsearch,$$lngdir/man3)/*.3; do $(fix_sqlmansectnum) $$file >$$lngdir/fixedman/man3/`basename $$file` || exit; done; \
		for file in $(call vpathsearch,$$lngdir/man7)/*.7; do $(fix_sqlmansectnum) $$file >$$lngdir/fixedman/man$(sqlmansectnum)/`basename $$file | sed s/\.7$$/.$(sqlmansect)/` || exit; done; \
	done

install-man:
	for lngdir in . $(ALL_LINGUAS); do [ -d $$lngdir ] && cp -R $(foreach dir,man1 man3 man$(sqlmansectnum),$$lngdir/fixedman/$(dir)) '$(DESTDIR)$(mandir)'/$$lngdir/ ;done

clean: clean-man
.PHONY: clean-man
clean-man:
	rm -rf fixedman/ fixed-man-stamp

endif # sqlmansectnum != 7

# tabs are harmless, but it is best to avoid them in XML files
check-tabs:
	@( ! grep '	' $(wildcard $(srcdir)/*.xml $(srcdir)/ref/*.xml $(srcdir)/*.xsl) ) || (echo "Tabs appear in XML files" 1>&2;  exit 1)

pot: pot-stamp

# Generate .pot files in doc/locale/
pot-stamp: $(GENERATED_XML) $(XML2PO)
	@rm -rf ../../locale/
	@$(MKDIR_P) ../../locale ../../locale/ref
	@$(MKDIR_P) ./tmp/xml ./tmp/xml/ref
	@for file in $(srcdir)/*.xml $(srcdir)/ref/*.xml; do \
		if [ ! -f "$$file" ]; then continue; fi; \
		rfile=$${file#$(srcdir)/}; \
		case $$rfile in \
			standalone-install.xml | filelist.xml | ref/allfiles.xml ) \
				continue; \
				;; \
			postgres.xml ) \
				cp $$file ./tmp/xml/; \
				;; \
			*) \
				echo '<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"><section>' | cat - $$file > ./tmp/xml/$$rfile; \
				echo '</section>' >> ./tmp/xml/$$rfile; \
				;; \
		esac; \
		xml2po=`readlink -f $(XML2PO)`; \
		(cd ./tmp/xml; $$xml2po -k $$rfile) > ../../locale/$${rfile%.xml}.pot; \
	done
	rm -rf ./tmp/
	touch $@

%/xml-l10n-stamp: $(ALLXML) | $(XML2PO)
	@echo making XML for language $(@D);
	@if [ ! -d $(srcdir)/../locale/$(@D) ]; then echo "$(srcdir)/../locale/$(@D) not found"; exit 1; fi;
	@rm -rf ./$(@D);
	$(MKDIR_P) $(@D) $(@D)/ref;:
	$(MKDIR_P) ./tmp/xml ./tmp/xml/ref;
	@for file in $^; do \
		rfile="$${file##*/xml/}";\
		rfile="$${rfile##*\./}";\
		poname="$(srcdir)/../locale/$(@D)/$${rfile%.xml}.po"; \
		if [ -f $$poname ]; then \
			if [ X"$$rfile" = X"postgres.xml" ]; then \
				cp $$file ./tmp/xml/; \
			else \
				echo '<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"><section>' | cat - $$file > ./tmp/xml/$$rfile; \
				echo '</section>' >> ./tmp/xml/$$rfile; \
			fi; \
			$(XML2PO) -k -l $(@D) -p $$poname ./tmp/xml/$$rfile > $(@D)/$$rfile; \
			$(PERL) -i -pe 's/&zwsp;/&#8203;/g' $(@D)/$$rfile; \
			if [ X"$$rfile" = X"postgres.xml" ]; then \
				echo 'Parameter entities are lost with libxml: http://www.perlmonks.org/?node_id=831711' >/dev/null; \
				echo 'So we need to preserve original DOCTYPE declaration' >/dev/null; \
				header=`$(PERL) -0777 -pe 's/^(.*?)<book.*$$/$$1/gms' ./tmp/xml/$$rfile`; \
				$(PERL) -0777 -pe 's/^(.*?)(<book.*$$)/$$2/gms' $(@D)/$$rfile >./tmp/xml/$$rfile; \
				echo "$$header" | cat - ./tmp/xml/$$rfile > $(@D)/$$rfile; \
			else \
				$(PERL) -0777 -i -pe 's/(<\?xml[^>]+>\s*)?<!DOCTYPE[^>]+>\s*<section>\s*//g;' -pe 's/<\/section>\s*$$//g;' $(@D)/$$rfile; \
			fi; \
			echo $$poname; \
		else \
			if [ X"$$file" = X"standalone-install.xml" ]; then \
				$(PERL) -pe 's/(<book[^>]*)/$$1 lang="$(@D)"/' $$file > $(@D)/$$rfile; \
			else \
				cp $$file $(@D)/$$rfile; \
			fi; \
		fi; \
	done;
	@for file in $(srcdir)/*.xsl; do if [ ! -f ./`basename $$file` ]; then cp $$file ./; fi; done
	@cp $(srcdir)/*.xsl $(wildcard $(srcdir)/*.svg $(srcdir)/*.png) $(@D)/
	@cp -r $(srcdir)/stylesheets $(@D)/
	@cp $(srcdir)/../locale/$(@D)/*.xsl $(srcdir)/../locale/$(@D)/*.svg $(srcdir)/../locale/$(@D)/*.png $(@D)/ || true;
	@cp $(srcdir)/../locale/$(@D)/*.xml $(@D)/ || true;
	@for patch in ../locale/$(@D)/*.patch; do if [ -f $$patch ]; then cat $$patch | (cd $(@D); patch -p5 --no-backup-if-mismatch); fi; done
	$(XMLLINT) --noout --valid $(@D)/postgres.xml;
	@rm -rf ./tmp;
	touch $@

.PHONY: update-po
update-po:
	@for lngdir in $(ALL_LINGUAS); do \
		(cd $(srcdir)/../locale/$$lngdir; \
		for po in *.po ref/*.po; do \
			if [ ! -f "$$po" ]; then continue; fi; \
			pot="../../../locale/$$po"t; \
			msgmerge --backup=none --width=79 --update $$po $$pot; \
		done; \
		); \
	done

##
## Clean
##

# This allows removing some files from the distribution tarballs while
# keeping the dependencies satisfied.
.SECONDARY: $(GENERATED_XML) HTML.index
.SECONDARY: INSTALL.html
.PRECIOUS: %/xml-l10n-stamp %/man-stamp %/html-stamp

clean:
# text --- these are shipped, but not in this directory
	rm -f INSTALL
	rm -f INSTALL.html
# single-page output
	rm -f postgres.html postgres.txt
# print
	rm -f *.rtf *.dvi *.aux *.log *.ps *.pdf *.out *.fot
# index
	rm -f HTML.index $(GENERATED_XML)
# XSLT
	rm -f postgres.xmltmp htmlhelp.hhp toc.hhc index.hhk *.fo *.fo.tmp
# EPUB
	rm -f postgres.epub
# Texinfo
	rm -f *.texixml *.texi *.info db2texi.refs

distclean: clean

maintainer-clean: distclean
# HTML
	rm -fr html/ html-stamp
# man
	rm -rf man1/ man3/ man7/ man-stamp
# pot
	rm -rf ../../locale/ pot-stamp
# xml
	rm xml-stamp; for lngdir in $(ALL_LINGUAS); do rm -rf $$lngdir; done
