#
# Makefile for the automation of LaTeX document processing
#
# Usage:  make [target]
# The following targets are understood:
#	dvi		generate dvi output (latex default target)
#	pdf             generate pdf output (pdflatex default target)
#	ps		generate postscript
#	clean		erase all intermediate files
#	realclean	erase all but the source files
#
# To do:
#	-recursively process \include{} and \input{} commands for .tex
#	dependancies
#	-do the same for \bibliography{} commands
#	-add metapost processing
#

#
# Document information (provided by top-level Makefile)
#
# LATEX
#	The name of the latex compiler to use.  If the program name is,
#	specifically, "pdflatex" then the .pdf will be the default target
#	rather than the .dvi.  Note that at present there is no way to ask
#	for one or the other without switching the contents of this
#	variable.
#
# DOCUMENT
#	(required) The root name for all files.
#
# GRAPHIC_FILES
#	Any graphic files the document depends on, for example any .eps or
#	.pdf files included with \includegraphics{}.  The output is rebuilt
#	if any of these files change but otherwise they play no role in the
#	build process.
#
# XFIG_FILES
#	Thes Makefile rules allow your LaTeX document to include xfig .fig
#	files directly.  Each .fig file is converted to a graphic format
#	suitable for inclusion by the LaTeX processor, for example
#	postscript or pdf.  This is accomplished by processing the .fig
#	file with fig2dev and producing two output files:  a graphics
#	version of the .fig file and a LaTeX source file containing the
#	commands needed to import that graphics file.  In your own LaTeX
#	document, you will need to include this .tex source file.  For
#	example, if you have an xfig file called diagram.fig, you should
#	set "XFIG_FILES = diagram.fig" in your Makefile and place the
#	command "\include{diagram.fig}" in your LaTeX document where you
#	would like the image placed.  When your document is processed, the
#	xfig file will be converted to a, for example, postscript file
#	called diagram.fig.ps and a LaTeX source file called
#	diagram.fig.tex.  The \include{} command in your LaTeX source reads
#	in the .fig.tex file (the .tex extension is assumed by the command)
#	which in turn contains the commands to import the graphics file.
#
#	As an added bonus, any text objects in the xfig document that have
#	their "special" flag set will be removed from the document before
#	it is converted to a graphics format.  Their contents are added to
#	the LaTeX source file along with the commands needed to overlay
#	them in the correct places on the figure.  In this way, you can use
#	LaTeX to typset the text of your xfig figure.  This has the
#	advantage of having the text rendered in the same font as the rest
#	of your document and also allows you to make use of all of LaTeX's
#	typsetting facilities.  Note that in your xfig document you should
#	set the pen colour of the "special" text to "Default" in order to
#	prevent \color commands from being issued, otherwise you will need
#	to include the LaTeX package "color".
#
#	If you get error messages about "unknown graphics format" related
#	to the .fig.ps or .fig.pdf intermediate graphics file then you must
#	issue the \DeclareGraphicsRule{.fig.ps}{eps}{.fig.ps}{} command or
#	the \DeclareGraphicsRule{.fig.pdf}{pdf}{.fig.pdf}{} command in your
#	document's preamble.  See the grfguide.ps graphics package
#	documentation for more information.
#
# BIB_FILES
#	$(DOCUMENT).tex will be automatically searched for all .bib files
#	specified via \bibliography{} commands.  Use this variable to
#	override the automatic search and manually specify the .bib files.
#	Reasons for wanting to override the automatics:  (i) scanning a
#	large document can be time-consuming and can be skipped by entering
#	the info yourself (ii) the algorithm may be broken for your
#	document.
#
# BSTINPUTS
# BIBINPUTS
#	The contents of these variables override the system default search
#	paths for bibtex.  If you are using a custom bibliographic style,
#	you may need to set BSTINPUTS to the directory in which the .bst
#	file resides.  If your .bib databases cannot be found, then you
#	will need to set BIBINPUTS to a colon-separated list of the
#	directories in which they reside.
#
# DVIPS_FLAGS
#	Flags to pass to dvips.  It might be necessary to include the -K
#	flag if you are having trouble getting mpage to handle documents
#	that contain EPS figures generated by certain applications.
#


###############################################################################
#
#                                   Preamble
#
###############################################################################

DVI_FILE  := $(DOCUMENT).dvi
PDF_FILE  := $(DOCUMENT).pdf
PS_FILE   := $(DOCUMENT).ps
AUX_FILE  := $(DOCUMENT).aux
LOF_FILE  := $(shell ls $(DOCUMENT).lof 2>/dev/null)
LOT_FILE  := $(shell ls $(DOCUMENT).lot 2>/dev/null)
TOC_FILE  := $(shell ls $(DOCUMENT).toc 2>/dev/null)
IDX_FILE  := $(shell ls $(DOCUMENT).idx 2>/dev/null)
END_FILE  := $(shell ls $(DOCUMENT).end 2>/dev/null)
TEX_FILES := $(DOCUMENT).tex
OTHER_FILES := $(DOCUMENT).blg $(DOCUMENT).log $(DOCUMENT).out
INDEX_ARGS := -s mkidx.ist

# grab the contents of \bibliograph{} commands
ifeq ($(BIB_FILES),)
	BIB_FILES := $(shell for source in $(TEX_FILES) ; do sed -e '{' -e 'y/,/ /' -e 's?.*\\bibliography[{]\(.*\)[}].*?\1?' -e 't' -e 'd' -e '}' <$$source ; done)
	BIB_FILES := $(BIB_FILES:%=%.bib)
endif

ifneq ($(BIB_FILES),)
	BBL_FILE := $(DOCUMENT).bbl
endif
ifneq ($(IDX_FILE),)
	IND_FILE := $(DOCUMENT).ind
endif

# construct the names of auxiliary files related to xfig documents
XFIG_AUX = $(strip $(XFIG_FILES:%.fig=%.fig.aux))
XFIG_GFX = $(strip $(XFIG_FILES:%.fig=%.fig.pdf) $(XFIG_FILES:%.fig=%.fig.ps))
XFIG_TEX = $(strip $(XFIG_FILES:%.fig=%.fig.tex))

# latex will be run over and over and over again until the following files
# stop changing.
MONITOR_FILES := $(strip $(AUX_FILE) $(TOC_FILE) $(LOF_FILE) $(LOT_FILE) $(BBL_FILE) $(IND_FILE) $(END_FILE))

# the following files must be present or processing will fail
SOURCE_FILES := $(TEX_FILES) $(BIB_FILES) $(GRAPHIC_FILES) $(XFIG_FILES)


###############################################################################
#
#                                    Targets
#
###############################################################################

.PHONY : dvi pdf ps clean realclean check_for_sources

.SECONDARY : $(MONITOR_FILES) $(XFIG_AUX) $(XFIG_GFX) $(XFIG_TEX)

ifeq (,$(LATEX))
LATEX := latex
endif

ifeq ($(notdir $(LATEX)),pdflatex)
pdf : $(PDF_FILE)
else
dvi : $(DVI_FILE)
endif

ps : $(PS_FILE)

clean :
	-rm -f $(MONITOR_FILES)
	-rm -f $(MONITOR_FILES:%=%.old)
	-rm -f $(OTHER_FILES)
	-rm -f $(XFIG_AUX)
	-rm -f $(XFIG_GFX)
	-rm -f $(XFIG_TEX)

realclean : clean
	-rm -f $(DVI_FILE)
	-rm -f $(PDF_FILE)
	-rm -f $(PS_FILE)


###############################################################################
#
#                                   Macros
#
###############################################################################


###############################################################################
#
#                       Dependancies and Generation Rules
#
###############################################################################

#
# Check for the existance of all required source files
#

check_for_sources :
	@FOUNDALL=1 ; for source in $(SOURCE_FILES) ; do [ -f "$$source" ] || { echo "Error: cannot find source file: $$source" ; FOUNDALL=0 ; } ; done ; [ $$FOUNDALL == 1 ]

#
# Generate a postscript file from a .dvi file
#

%.ps : %.dvi
	dvips $(DVIPS_FLAGS) -o $@ $*

#
# Generate the .dvi (or .pdf) file by running LaTeX (or PDFLaTeX) until the
# auxiliary files listed in MONITOR_FILES stop changing.  Rather than just
# looping, make is re-run which allows any files that depend on the
# particular auxiliary files that changed to be updated as well.
#

define run-latex
	@function saveold () { for file ; do [ -f $${file} ] && cp -fp $${file} $${file}.old ; done ; true ; } ; \
	function restoreold () { for file ; do [ -f $${file}.old ] && mv -f $${file}.old $${file} ; done ; true ; } ; \
	function deleteold ()  { for file ; do rm -f $${file}.old ; done ; true ; } ; \
	function makeobsolete () { touch -r $$(ls *.old | tail -n 1) $${1} ; true ; } ; \
	function nochange () { for file ; do [ ! -f $${1} ] || cmp $${1} $${1}.old >/dev/null || return ; done ; true ; } ; \
	saveold $(MONITOR_FILES) ; \
	if $(LATEX) $* ; then \
	   if nochange $(MONITOR_FILES) ; then \
	      echo "$(MAKE): LaTeX auxiliary files did not change (processing is complete)" ; \
	      restoreold $(MONITOR_FILES) ; \
	   else \
	      echo "$(MAKE): LaTeX auxiliary files changed (further processing is required)" ; \
              echo "please wait..." ; sleep 2 ; \
	      makeobsolete $@ ; \
	      deleteold $(MONITOR_FILES) ; \
	      $(MAKE) --no-print-directory $@ ; \
	   fi ; \
	else \
	   echo ; \
	   false ; \
	fi
endef

$(DVI_FILE) : %.dvi : $(TEX_FILES) $(MONITOR_FILES) $(GRAPHIC_FILES) $(XFIG_TEX)
	$(run-latex)

$(PDF_FILE) : %.pdf : $(TEX_FILES) $(MONITOR_FILES) $(GRAPHIC_FILES) $(XFIG_TEX)
	$(run-latex)

#
# Generate a .bbl file from the .aux file.
#

%.bbl : %.aux $(BIB_FILES)
	BSTINPUTS="$(BSTINPUTS)" BIBINPUTS="$(BIBINPUTS)" bibtex $*

#
# Generate a .ind file from the .idx file.
#

%.ind : %.idx
	makeindex $(INDEX_ARGS) $<

#
# Generate a .aux or .idx file if it doesn't already exist.  The existance
# of these files is a prerequisite for the main document processing loop
# above so that's what we're doing here.  Note, however, that all .fig.tex
# files must be present in order for this first pass to succeed
#

%.aux %.idx : $(XFIG_TEX)
	$(LATEX) $*

#
# Distill xfig .fig files into .fig.tex and either .fig.pdf or .fig.ps
# compoents
#

ifeq ($(notdir $(LATEX)),pdflatex)
%.fig.tex : %.fig %.fig.pdf
	fig2dev -L pstex_t -p $*.fig.pdf <$< >$@
else
%.fig.tex : %.fig %.fig.ps
	fig2dev -L pstex_t -p $*.fig.ps <$< >$@
endif

%.fig.pdf : %.fig
	pushd $(dir $<) ; fig2dev -L pstex <$(nodir $<) | ps2pdf - - >$(nodir $@) ; popd

%.fig.ps : %.fig
	pushd $(dir $<) ; fig2dev -L pstex <$(notdir $<) >$(notdir $@) ; popd
