%************************************************************************
%*									*
\section[mkworld-macros-GEN]{Mkworld CPP macros for the masses}
%*									*
%************************************************************************

%************************************************************************
%*									*
\subsection[mkworld-macros-depend]{Macros related to \tr{depend} std target}
%*									*
%************************************************************************

These \tr{*DependTarget} rules assume the relevant programs are in
their proper places.  They won't reach out and build them for you.

@CDependTarget@: generate rules to compute dependencies for all C files
in @deps@.
\begin{code}
#ifndef CDependTarget
#define CDependTarget(deps)					@@\
MkDependCNeededHere(depend)					@@\
								@@\
depend:: deps							@@\
	$(MKDEPENDC) $(MKDEPENDCFLAGS) -- $(CFLAGS) -- deps
#endif /* CDependTarget */
\end{code}

@HaskellDependTarget@: generate rules to compute dependencies for all
Haskell files in @deps@.
\begin{code}
#ifndef HaskellDependTarget
#define HaskellDependTarget(deps)				@@\
MkDependHSNeededHere(depend)					@@\
								@@\
depend:: deps							@@\
	$(MKDEPENDHS) $(MKDEPENDHSFLAGS) -- $(HCFLAGS) -- deps
#endif /* HaskellDependTarget */
\end{code}

@LitDependTarget@: generate rules to compute dependencies for the
specified ``literate root file''.
\begin{code}
#ifndef LitDependTarget
#define LitDependTarget(root,rootext)				@@\
								@@\
depend::							@@\
	$(MKDEPENDLIT) $(MKDEPENDLITFLAGS) root.rootext
#endif /* LitDependTarget */
\end{code}

%************************************************************************
%*									*
\subsection[mkworld-macros-all]{Macros related to \tr{all} std target}
%*									*
%************************************************************************

First, so easy ones.  @AllTarget()@ should be a part of most of these
to automatically add the target to the \tr{all} rule.

\begin{code}
#ifndef AllTarget
#define AllTarget(depends)				@@\
all:: depends
#endif
\end{code}

Make a link to a target.  Used when several targets use
the same object under different names.

\begin{code}
#ifndef LinkTarget
#define LinkTarget(target,linkto)			@@\
AllTarget(target)					@@\
ExtraStuffToClean(target)				@@\
target:: linkto						@@\
	RemoveTarget(target)				@@\
	${LN} linkto target
#endif
\end{code}

%************************************************************************
%*									*
\subsubsection[mkworld-macros-bld-pgms]{Compiling modules/files and linking programs}
%*									*
%************************************************************************

%************************************************************************
%*									*
\subsubsubsection{General macros}
%*									*
%************************************************************************

@BuildPgm@: generate rules to compile and link the
indicated program; since it does not use any default object files, it
may be used for multiple programs in the same @Jmakefile@.

This target is the general interface for building a single program
(perhaps one of many in the @Makefile@).

\begin{code}
#ifndef BuildPgm
#define BuildPgm(program,compiler,compileropts,objs,libs,deplibs)	@@\
AllTarget(program)							@@\
ExtraStuffToClean(program)						@@\
program:: objs deplibs							@@\
	RemoveTarget($@)						@@\
	compiler -o $@ compileropts $(LDOPTIONS) objs libs
#endif /* BuildPgm */
\end{code}
ToDo: not sure all ``compilers'' will like that -o above...

%************************************************************************
%*									*
\subsubsubsection{Compile C files, build C programs}
%*									*
%************************************************************************

These depend on suitable suffix rules existing.

\begin{code}
#ifndef BuildPgmFromCFiles
#define BuildPgmFromCFiles(program,objs,libs,deplibs)		@@\
BuildPgm(program,$(CC),$(CFLAGS),objs,libs,deplibs)
#endif

#ifndef BuildPgmFromOneCFile
#define BuildPgmFromOneCFile(program)				@@\
SRCS_C = program.c						@@\
OBJS_C = program.o						@@\
BuildPgm(program,$(CC),$(CFLAGS),$(OBJS_C),/**/,/**/)
#endif
\end{code}

This rule is formulated, esp \tr{*.tab.h} part, in case you have more
than one @YaccRunWithExpectMsg@ in a given directory.
\begin{code}
/*ToDo: cmp => $(CMP)*/

#ifndef YaccRunWithExpectMsg
#define YaccRunWithExpectMsg(srcfile,ss,rs)			@@\
srcfile.tab.c : srcfile.y					@@\
	$(RM) srcfile.tab.c srcfile.tab.h-SAVE y.tab.c y.tab.h y.output		@@\
	@if [ -f srcfile.tab.h ] ; then $(MV) -f srcfile.tab.h srcfile.tab.h-SAVE ; fi @@\
	@echo expect ss shift/reduce conflicts and rs reduce/reduce conflicts @@\
	$(YACC) $(YFLAGS) srcfile.y				@@\
	@if cmp -s srcfile.tab.h-SAVE y.tab.h ; then \		@@\
	    $(MV) -f srcfile.tab.h-SAVE srcfile.tab.h ; \	@@\
	else \							@@\
	    echo $(MV) -f y.tab.h srcfile.tab.h ; \		@@\
	    $(MV) -f y.tab.h srcfile.tab.h ; \			@@\
	    chmod 444 srcfile.tab.h ; \				@@\
	fi							@@\
	@$(RM) y.tab.h						@@\
	$(MV) y.tab.c srcfile.tab.c				@@\
	@chmod 444 srcfile.tab.c				@@\
								@@\
srcfile.tab.h : srcfile.tab.c					@@\
	@echo -n "" /* no-op */
#endif
\end{code}

%************************************************************************
%*									*
\subsubsubsection{Compile Haskell modules, build Haskell programs}
%*									*
%************************************************************************

Defined here...
\begin{description}
\item[@BuildPgmFromHaskellModules@:]

\item[@BuildPgmFromOneHaskellModule@:]

\item[@HaskellCompileWithSpecifiedFlags@:]
\item[@HaskellCompileWithExtraFlags@:]
\item[@HaskellCompileWithMoreHeapAndStack@:]
\item[@HaskellCompileWithMoreHeap@:]
\item[@HaskellCompile@:]
\end{description}

\begin{code}
#ifndef BuildPgmFromHaskellModules
#define BuildPgmFromHaskellModules(program,objs,libs,deplibs)	@@\
BuildPgm(program,$(HC),$(HCFLAGS),objs,libs,deplibs)
#endif

#ifndef BuildPgmFromOneHaskellModule
#define BuildPgmFromOneHaskellModule(program,module,isuf)	@@\
SRCS_HS = module.isuf						@@\
OBJS_HS = module.o						@@\
BuildPgm(program,$(HC),$(HCFLAGS),$(OBJS_HS),,)
#endif
\end{code}

First, we define just the body of a hs-to-o rule...
\begin{code}
#if HaveGlasgowHaskell == YES && UseGlasgowHaskell == YES

#define _body_HaskellCompileWithSpecifiedFlags(module_isuf,module,isuf,flags) @@\
	$(RM) $@						\
	HaskellCompilePreProcessing(module_isuf,module,isuf)	@@\
	$(HC) flags module_isuf -o module.o			\
	HaskellCompilePostProcessing(module_isuf,module,isuf)


#elif HaveChalmersHBC == YES && UseChalmersHBC == YES

#define _body_HaskellCompileWithSpecifiedFlags(module_isuf,module,isuf,flags) @@\
	@echo $(RM) $@; \					@@\
	$(RM) $@; \						\
	HaskellCompilePreProcessing(module_isuf,module,isuf)	@@\
	iface=`basename module_isuf .isuf`.hi ; \		@@\
	if [ -f $(@D)/$$iface ] ; then \			@@\
	    $(RM) $(@D)/$$iface-SAVE ; \			@@\
	    $(MV) -f $(@D)/$$iface $(@D)/$$iface-SAVE ; \	@@\
	fi ; \							@@\
	set +e; \						@@\
	echo $(HC) flags module_isuf -o module.o; \		@@\
	$(HC) flags module_isuf -o module.o; \			@@\
	if [ $$? -ne 0 ] ; then \				@@\
	    $(MV) -f $(@D)/$$iface-SAVE $(@D)/$$iface ; \	@@\
	    exit 1; \						@@\
	fi ; \							@@\
	if cmp -s $(@D)/$$iface-SAVE $(@D)/$$iface ; then \	@@\
	    $(MV) -f $(@D)/$$iface-SAVE $(@D)/$$iface ;  \	@@\
	else \							@@\
	    if [ -f $(@D)/$$iface-SAVE ] ; then \		@@\
		diff -c1 $(@D)/$$iface-SAVE $(@D)/$$iface ;  \	@@\
		$(RM) $(@D)/$$iface-SAVE ;  \			@@\
	    fi ; \						@@\
	fi							\
	HaskellCompilePostProcessing(module_isuf,module,isuf)
	
#else /* not GHC or HBC; presumably prototype Glasgow compiler (nhc) */

#define _body_HaskellCompileWithSpecifiedFlags(module_isuf,module,isuf,flags) @@\
	@echo $(RM) $@; \					@@\
	$(RM) $@; \						\
	HaskellCompilePreProcessing(module_isuf,module,isuf)	@@\
	iface=`basename module_isuf .isuf`.hi ; \		@@\
	if [ -f $(@D)/$$iface ] ; then \			@@\
	    $(RM) $(@D)/$$iface-SAVE ; \			@@\
	    $(MV) -f $(@D)/$$iface $(@D)/$$iface-SAVE ; \	@@\
	    cp -p $(@D)/$$iface-SAVE $(@D)/$$iface ; \		@@\
	    chmod u+w $(@D)/$$iface ; \				@@\
	fi ; \							@@\
	set +e; \						@@\
	echo $(HC) flags module_isuf -o module.o; \		@@\
	$(HC) flags module_isuf -o module.o; \			@@\
	if [ $$? -ne 0 ] ; then \				@@\
	    $(RM) STAT ; \					@@\
	    $(MV) -f $(@D)/$$iface-SAVE $(@D)/$$iface ; \	@@\
	    exit 1; \						@@\
	fi ; \							@@\
	if [ -f STAT ] ; then $(MV) STAT module.STAT ; fi ; \	@@\
	if [ \( $(@D) != '.' \) -a \( $(@D) != './' \) ] ; then \ @@\
	    iface=`basename module_isuf .isuf`.hi ; \		@@\
	    $(UPDATEIFACE) $$iface $(@D)/$$iface ; \		@@\
	    $(RM) $(@D)/$$iface-SAVE ; \			@@\
	fi							\
	HaskellCompilePostProcessing(module_isuf,module,isuf)

#endif /* ! ChalmersHBC or GHC */
\end{code}

The default for the ``pre-'' and/or ``post-processing'' part (possibly
swizzling around profiling/statistics files) is, of course, to do no
such thing.
\begin{code}
#ifndef HaskellCompilePreProcessing
#define HaskellCompilePreProcessing(module_isuf,module,isuf) /* nothing */
#endif /* ! HaskellCompilePreProcessing */

#ifndef HaskellCompilePostProcessing
#define HaskellCompilePostProcessing(module_isuf,module,isuf) /* nothing */
#endif /* ! HaskellCompilePostProcessing */
\end{code}

Now we just use the \tr{_body_*} thing above...
\begin{code}
#ifndef HaskellCompileWithSpecifiedFlags
#define HaskellCompileWithSpecifiedFlags(module,isuf,flags)	@@\
module.o : module.isuf						\
_body_HaskellCompileWithSpecifiedFlags(module.isuf,module,isuf,flags)
#endif /* HaskellCompileWithSpecifiedFlags */

#ifndef HaskellCompileWithExtraFlags
#define HaskellCompileWithExtraFlags(module,isuf,flags)		@@\
HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS) flags)
#endif /* HaskellCompileWithExtraFlags */

#ifndef HaskellCompile
#define HaskellCompile(module,isuf)				@@\
HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS))
#endif /* HaskellCompile */
\end{code}

Asking for extra heap: the amount requested is the SEMI-SPACE size;
the actual amount of heap memory used will be twice that.
\begin{code}
#ifndef HaskellCompileWithMoreHeapAndStack
#define HaskellCompileWithMoreHeapAndStack(module,isuf,heapsize,stksize) @@\
HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS) HaskellCompilerHeapSize(heapsize) HaskellCompilerStkSize(stksize))
#endif /* HaskellCompileWithMoreHeapAndStack */

#ifndef HaskellCompileWithMoreHeap
#define HaskellCompileWithMoreHeap(module,isuf,heapsize)	@@\
HaskellCompileWithSpecifiedFlags(module,isuf,-c $(HCFLAGS) HaskellCompilerHeapSize(heapsize))
#endif /* HaskellCompileWithMoreHeap */
\end{code}

But we need those per-compiler HeapSize/StkSize/RunCpp macros...
\begin{code}
#if HaveGlasgowHaskell == YES && UseGlasgowHaskell == YES
#define HaskellCompilerHeapSize(size) -Rmax-heapsize size
#define HaskellCompilerStkSize(size)  -Rmax-stksize size
#define HaskellCompilerRunCpp()	-cpp
#define HaskellEndRTSFlags()	/*none*/

#elif HaveChalmersHBC == YES && UseChalmersHBC == YES
#define HaskellCompilerHeapSize(size) CAT2(-H,size)
#define HaskellCompilerStkSize(size)  CAT2(-V,size)
#define HaskellCompilerRunCpp()	-M
#define HaskellEndRTSFlags()	-

#else /* not GHC or HBC; assume nhc */
#define HaskellCompilerHeapSize(size) CAT2(-H,size)
#define HaskellCompilerStkSize(size)  /*cant set stksize*/
#define HaskellCompilerRunCpp()	/*none*/
#define HaskellEndRTSFlags()	-

#endif /* not GHC or HBC */
\end{code}

%************************************************************************
%*									*
\subsubsection[mkworld-macros-scripts]{Processing scripts into ``executables''}
%*									*
%************************************************************************

\begin{code}
#ifndef ProgramScriptTarget
#if HasExecableScripts		/* can use #! */
#define ProgramScriptTarget(prog,dst,src,deplist)	@@\
AllTarget(dst)						@@\
ExtraStuffToClean(dst)					@@\
dst::  src deplist					@@\
	$(RM) $@					@@\
	echo "#!"prog > $@				@@\
	cat src >> $@					@@\
	chmod a+x $@
#else
#define ProgramScriptTarget(prog,dst,src,deplist)	@@\
AllTarget(dst)						@@\
ExtraStuffToClean(dst)					@@\
dst::  src deplist					@@\
	$(RM) $@					@@\
	echo \: > $@					@@\
	echo 'x=/tmp/xx$$$$' >> $@			@@\
	echo "cat > "'$$x'" << 'EOF'" >> $@		@@\
	cat src >> $@					@@\
	echo EOF >> $@					@@\
	echo prog '$$x' '$$@' >> $@			@@\
	echo $(RM) '$$x' >> $@				@@\
	chmod a+x $@
#endif /* HasExecableScripts */
#endif /* ProgramScriptTarget */
\end{code}

Create a target by running it through @msub@:
\begin{code}
#ifndef MsubTarget
#define MsubTarget(dst,src,flags,deplist)		@@\
AllTarget(dst)						@@\
ExtraStuffToClean(dst)					@@\
dst:: src deplist					@@\
	$(MSUB) flags src > dst
#endif
\end{code}

@MsubProgramScriptTarget@: generate rules to create a script for an
arbitrary program by running the input through @msub@.  If
@HasExecableScripts@ isn't @YES@, then make sure that the first line
begins with a colon and write the script into a temp file, have the
program execute that, and remove the temp file when done.  Ugly ugly
ugly...  @prog@ must be a full pathname...
\begin{code}
#ifndef MsubProgramScriptTarget
#if HasExecableScripts		/* can use #! */
#define MsubProgramScriptTarget(prog,dst,src,flags,deplist)	@@\
AllTarget(dst)							@@\
ExtraStuffToClean(dst)						@@\
dst::  src deplist						@@\
	$(RM) $@						@@\
	echo "#!"prog > $@					@@\
	${MSUB} flags src >> $@					@@\
	chmod a+x $@
#else
#define MsubProgramScriptTarget(prog,dst,src,flags,deplist)	@@\
AllTarget(dst)							@@\
ExtraStuffToClean(dst)						@@\
dst::  src deplist						@@\
	$(RM) $@						@@\
	echo \: > $@						@@\
	echo 'x=/tmp/xx$$$$' >> $@				@@\
	echo "cat > "'$$x'" << 'EOF'" >> $@			@@\
	${MSUB} flags src >> $@					@@\
	echo EOF >> $@						@@\
	echo prog '$$x' '$$@' >> $@				@@\
	echo $(RM) '$$x' >> $@					@@\
	chmod a+x $@
#endif /* HasExecableScripts */
#endif /* MsubProgramScriptTarget */
\end{code}

For an @msub@ target that really slurps things out of the
\tr{Makefile}, we delete it as part of \tr{make Makefile(s)}, so that
it will be re-made.
\begin{code}
#ifndef MsubMakefileDependentProgramScriptTarget
#define MsubMakefileDependentProgramScriptTarget(prog,dst,src,flags,deplist)	@@\
MsubProgramScriptTarget(prog,dst,src,flags,deplist)			@@\
									@@\
Makefile::								@@\
	$(RM) dst
#endif
\end{code}

\begin{code}
#ifndef MsubScriptTarget
#define MsubScriptTarget(dst,src,flags,deplist)				@@\
MsubProgramScriptTarget(${SHELL},dst,src,flags,deplist)
#endif
\end{code}

%************************************************************************
%*									*
\subsubsection[mkworld-macros-bld-libs]{Linking modules/files into libraries}
%*									*
%************************************************************************

@NormalLibraryTarget@: generate rules to create a library.

\begin{code}
#ifndef NormalLibraryTarget
#define NormalLibraryTarget(libname,objlist)	@@\
AllTarget(CAT2(lib,libname.a))			@@\
ExtraStuffToClean(CAT2(lib,libname.a))		@@\
CAT2(lib,libname.a):: objlist			@@\
	$(RM) $@				@@\
	$(AR) $@ objlist			@@\
	$(RANLIB) $@
#endif /* NormalLibraryTarget */
\end{code}

%************************************************************************
%*									*
\subsection[mkworld-macros-runtests]{Macros related to \tr{runtests} std target}
%*									*
%************************************************************************

Rules to do with standard @runtests@ target.

\begin{code}
#ifndef RuntestsTarget
#define RuntestsTarget(depends)			@@\
runtests:: CAT2(runtest_,depends)
#endif

#ifndef RunStdTestTimeCmd
#define RunStdTestTimeCmd /*none*/
#endif

#ifndef RunStdTest
#define RunStdTest(name,prog,teststuff)		@@\
RuntestsTarget(name)				@@\
CAT2(runtest_,name)::				@@\
	@RunStdTestTimeCmd $(RUNSTDTEST) prog $(RUNSTDTEST_FLAGS) teststuff
#endif /* RunStdTest */

#ifndef AsPartOfTest
#define AsPartOfTest(test,cmdline)		@@\
RuntestsTarget(test)				@@\
CAT2(runtest_,test)::				@@\
	cmdline
#endif /* AsPartOfTest */
\end{code}

%************************************************************************
%*									*
\subsection[mkworld-macros-install]{Macros related to \tr{install} std target}
%*									*
%************************************************************************

Run script through @msub@ with \tr{INSTALLING=1},
putting result in a tmp file (don't mess w/ the @dst@ file here);
install that tmp file in the right place.
\begin{code}
#ifndef InstallMsubbedScriptTarget
#if HasExecableScripts		/* can use #! */
#define InstallMsubbedScriptTarget(prog,dst,src,installdir)	@@\
dst-tmp:  src							@@\
	$(RM) $@						@@\
	echo "#!"prog > $@					@@\
	${MSUB} INSTALLING=1 src >> $@				@@\
	chmod a+x $@						@@\
								@@\
InstallTargetWithNameAndFlags(dst-tmp,installdir,dst,)		@@\
install::							@@\
	$(RM) dst-tmp
#else
#define InstallMsubbedScriptTarget(prog,dst,src,installdir)	@@\
dst-tmp:  src							@@\
	$(RM) $@						@@\
	echo \: > $@						@@\
	echo 'x=/tmp/xx$$$$' >> $@				@@\
	echo "cat > "'$$x'" << 'EOF'" >> $@			@@\
	${MSUB} INSTALLING=1 src >> $@				@@\
	echo EOF >> $@						@@\
	echo prog '$$x' '$$@' >> $@				@@\
	echo $(RM) '$$x' >> $@					@@\
	chmod a+x $@						@@\
								@@\
InstallTargetWithNameAndFlags(dst-tmp,installdir,dst,)		@@\
install::							@@\
	$(RM) dst-tmp
#endif /* HasExecableScripts */
#endif /* InstallMsubbedScriptTarget */

/*
	INSTALLATION RULES.  InstallTarget() should be a part of nearly
	all of these, to add the target to the "install" rule.
*/

#ifndef InstallTarget
#define InstallTarget(depends)					@@\
install:: CAT2(install_,depends)
#endif

#ifndef InstallDocTarget
#define InstallDocTarget(depends)				@@\
install_docs:: CAT2(install_doc_,depends)
#endif

/*
	Install a target specifying the flags to use.  Many of the following
	installation rules are instantiated as a particular expansion of this.
*/

#ifndef InstallTargetWithNameAndFlags
#define InstallTargetWithNameAndFlags(target,destdir,new_name,flags)	@@\
InstallTarget(new_name)							@@\
CAT2(install_,new_name):: target					@@\
	$(INSTALL) -c flags target destdir/new_name
#endif

#ifndef InstallTargetWithFlags
#define InstallTargetWithFlags(target,dest,flags)			@@\
InstallTargetWithNameAndFlags(target,dest,target,flags)
#endif

#ifndef InstallDocTargetWithFlags
#define InstallDocTargetWithFlags(src,presuff,target,postsuff,dest,flags) @@\
InstallDocTarget(CAT3(target,_,postsuff))				@@\
CAT4(install_doc_,target,_,postsuff):: src.presuff			@@\
	$(INSTALL) -c flags src.presuff dest/target.postsuff
#endif

/*
	Install a program
*/

#ifndef InstallBinaryTarget
#define InstallBinaryTarget(program,dest)				@@\
InstallTargetWithFlags(program,dest,$(INSTBINFLAGS))
#endif

/*	Install a setuid/setgid/etc program -- DELETED (partain)
*/

/*
	Install an executable script
*/

#ifndef InstallScriptTarget
#define InstallScriptTarget(script,dest)				@@\
InstallTargetWithFlags(script,dest,$(INSTSCRIPTFLAGS))
#endif

/*
	Install a library (platform-dependent)
*/

#ifndef InstallLibraryTarget
#define InstallLibraryTarget(libname,dest)				@@\
InstallTargetWithFlags(CAT2(lib,libname).a,dest,$(INSTLIBFLAGS))	@@\
	${RANLIB} dest/CAT2(lib,libname).a
#endif

/*
	Install an include file
*/

#ifndef InstallIncludeTarget
#define InstallIncludeTarget(file,dest)					@@\
InstallTargetWithFlags(file,dest,$(INSTINCFLAGS))
#endif

/*
	Install a non-executable or data file (these are equivalent)
*/

#ifndef InstallDataTarget
#define InstallDataTarget(file,dest)					@@\
InstallTargetWithFlags(file,dest,$(INSTDATAFLAGS))
#endif

/*
	Install a set of non-executable files

	DUMP THIS SOMETIME.
*/

#ifndef InstallMultNonExecTargets
#define InstallMultNonExecTargets(rule,targets,dest)			@@\
CAT2(install_,rule):: rule						@@\
	@case '${MFLAGS}' in *[ik]*) set +e;; esac; \			@@\
	for i in targets ;\						@@\
	do \								@@\
		echo $(INSTALL) -c $(INSTDATAFLAGS) $$i dest/$$i; \	@@\
		$(INSTALL) -c $(INSTDATAFLAGS) $$i dest/$$i; \		@@\
	done
#endif

/*
	Install a man page.

	THIS IS WRONG - rules in Jmakefiles don't have suffix!

	file srcsuffix destdir dstsuffix ???
*/

#ifndef InstallManPageTarget
#define InstallManPageTarget(file,destdir,suffix)			@@\
InstallDocTargetWithFlags(file,man,file,suffix,destdir,$(INSTMANFLAGS))
#endif

#ifndef InstallInfoFileTarget
#define InstallInfoFileTarget(src,target,destdir)			@@\
InstallDocTargetWithFlags(src,info,target,info,destdir,$(INSTMANFLAGS))
#endif

#ifndef InstallLinkTarget
#define InstallLinkTarget(target, linkto, dir)				@@\
InstallTarget(target)							@@\
CAT2(install_,target):: CAT2(install_,linkto)				@@\
	RemoveTarget(dir/target)					@@\
	${LN} dir/linkto dir/target
#endif

/*
	Fake install rules for things not installed anywhere
*/

#ifndef FakeInstallTarget
#define FakeInstallTarget(target)					@@\
InstallTarget(target)							@@\
CAT2(install_,target):: target						@@\
	@echo target is not installed anywhere.
#endif

#ifndef FakeInstallLibrary
#define FakeInstallLibrary(libname)					@@\
InstallTarget(CAT2(lib,libname).a)					@@\
CAT2(install_lib,libname).a:: CAT2(lib,libname).a			@@\
	@echo CAT2(lib,libname).a is not installed anywhere.
#endif
\end{code}

%************************************************************************
%*									*
\subsection[mkworld-macros-docs]{Macros related to \tr{docs} std target}
%*									*
%************************************************************************

Need rules just to make a man page or info file.

\begin{code}
#ifndef DocsTarget
#define DocsTarget(depends)						@@\
docs:: depends
#endif

/* putting the InfoStuffNeededHere in semi-presumes that
   LitDocRootTarget is only used once per directory (?)
*/
#ifndef LitDocRootTargetWithNamedOutput
#define LitDocRootTargetWithNamedOutput(rootroot,rootext,rootout)	@@\
DocsTarget(rootroot.info rootroot.dvi)					@@\
ExtraStuffToClean(rootroot.info rootroot.dvi rootroot.texi rootroot.tex) @@\
LitDependTarget(rootroot,rootext)					@@\
									@@\
rootroot.info:: rootroot.texi						@@\
	RemoveTarget($@)						@@\
	$(MAKEINFO) $(MAKEINFOFLAGS) rootroot.texi \			@@\
	&& $(POSTMAKEINFO) rootroot.info				@@\
									@@\
rootroot.dvi:: rootroot.tex						@@\
	RemoveTarget($@)						@@\
	$(LTX) rootroot.tex						@@\
									@@\
rootroot.texi: rootout.itxi						@@\
	RemoveTarget($@)						@@\
	$(LIT2TEXI) -S $(LIT2TEXIFLAGS) -N rootroot.info -o rootroot.texi rootout.itxi	@@\
									@@\
rootout.itxi: rootroot.rootext						@@\
	RemoveTarget($@)						@@\
	$(LIT2TEXI) -S -c $(LIT2TEXIFLAGS) -o rootout.itxi rootroot.rootext @@\
									@@\
rootroot.tex: rootout.itex						@@\
	RemoveTarget($@)						@@\
	$(LIT2LATEX) -S $(LIT2LATEXFLAGS) -o rootroot.tex rootout.itex	@@\
									@@\
rootout.itex: rootroot.rootext						@@\
	RemoveTarget($@)						@@\
	$(LIT2LATEX) -S -c $(LIT2LATEXFLAGS) -o rootout.itex rootroot.rootext
#endif /* LitDocRootTargetWithNamedOutput */

#ifndef LitDocRootTarget
#define LitDocRootTarget(rootroot,rootext) \
LitDocRootTargetWithNamedOutput(rootroot,rootext,rootroot)
#endif /* LitDocRootTarget */

#ifndef VerbatimAndTibTarget
#define VerbatimAndTibTarget(root)					@@\
VerbatimNeededHere(docs root.tex)					@@\
DocsTarget(root.dvi)							@@\
ExtraStuffToClean(root.dvi root.tex)
#endif /* VerbatimAndTibTarget */
\end{code}

%************************************************************************
%*									*
\subsection[mkworld-macros-install-docs]{Macros related to \tr{install_docs} std target}
%*									*
%************************************************************************

%************************************************************************
%*									*
\subsection[mkworld-macros-cleaning]{Macros related to \tr{clean} (and \tr{veryclean}) std targets}
%*									*
%************************************************************************

\begin{code}
#ifndef ExtraStuffToClean
#define ExtraStuffToClean(extra)					@@\
clean::									@@\
	$(RM) extra
#endif /* ExtraStuffToClean */

#ifndef ExtraStuffToBeVeryClean
#define ExtraStuffToBeVeryClean(extra)					@@\
veryclean::								@@\
	$(RM) extra
#endif /* ExtraStuffToBeVeryClean */

#ifndef RemoveTarget
#if RemoveTargetByMoving
#define RemoveTarget(program) \
$(RM) program; if [ -f program ]; then $(MV) program CAT2(program,~); fi
#else
#define RemoveTarget(program) $(RM) program
#endif /* ! RemoveTargetByMoving */
#endif /* RemoveTarget */
/*
 * CleanTarget - generate rules to remove any garbage files; the #* is here
 * instead of in the definition of CLEAN_CMD because System V would treat a
 * pound sign in the CLEAN_CMD variable as a comment.
 */
#ifndef CleanTarget
#define CleanTarget()							@@\
clean::									@@\
	$(CLEAN_CMD) \#*
#endif /* CleanTarget */

/*
 * VeryCleanTarget - generate rules for "make veryclean"; the idea is
 * that "make clean" does what "you almost always want" and "make
 * veryclean" removes ALL generated files.
 */
#ifndef VeryCleanTarget
#define VeryCleanTarget()						@@\
veryclean::								@@\
	$(CLEAN_CMD) \#*
#endif /* VeryCleanTarget */
\end{code}

%************************************************************************
%*									*
\subsection[mkworld-macros-tags]{Macros related to \tr{tags} std target}
%*									*
%************************************************************************

\begin{code}
/* this should normally precede <>TagsTarget commands */
/* those commands *append* to the TAGS file */
#ifndef ClearTagsFile
#define ClearTagsFile()							@@\
tags::									@@\
	$(RM) TAGS; touch TAGS
#endif

/*
 * CTagsTarget - generate rules to compute tags files for C source code.
 *	(specified as an arg)
 *	partain: we really expect "etags" to be used...
 */
#ifndef CTagsTarget
#define CTagsTarget(srcs)						@@\
tags::									@@\
	$(CTAGS) -a $(CTAGSFLAGS) srcs
#endif /* CTagsTarget */

/* Similarly for Perl and Haskell */
#ifndef PerlTagsTarget
#define PerlTagsTarget(srcs)						@@\
tags::									@@\
	$(PERLTAGS) $(PERLTAGSFLAGS) srcs
#endif /* PerlTagsTarget */

#ifndef HsTagsTarget
#define HsTagsTarget(srcs)						@@\
tags::									@@\
	$(HSTAGS) $(HSTAGSFLAGS) srcs
#endif /* HsTagsTarget */
\end{code}

%************************************************************************
%*									*
\subsection[mkworld-macros-Makefile]{Macros related to \tr{make Makefile}}
%*									*
%************************************************************************

@BuildMakefileTarget@: generate rules to build a \tr{Makefile} from a
\tr{Jmakefile} (and, in the past, any special jmake flags). This is
generally done automatically by the template or by any special
Jmakefiles.

\begin{code}
#ifndef BuildMakefileTarget
#define BuildMakefileTarget()						@@\
JmakeNeededHere(Makefile)						@@\
									@@\
Makefile:: $(MYJCONFIGFILES)						@@\
									@@\
Makefile::								@@\
	-@if [ -f Makefile ]; then \					@@\
		echo "	$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \ @@\
		$(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \	@@\
	else exit 0; fi							@@\
	$(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(TOP) -DCurDir=$(CURRENT_DIR) @@\
	$(JRESTOREDEPS)							@@\
	@if cmp -s Makefile Makefile.bak; then $(RM) Makefile.bak ; fi  @@\
	@chmod 444 Makefile						@@\
	@echo ==== The new Makefile is for\: ====			@@\
	@$(MAKE) whoami || \						@@\
	( echo 'Putting old Makefile back (see Makefile.bad)...' && \	@@\
	$(MV) Makefile Makefile.bad &&		\			@@\
	$(MV) Makefile.bak Makefile )					@@\
									@@\
whoami::								@@\
	@echo $(PROJECTNAME), version $(PROJECTVERSION)			@@\
	@echo project\: $(PROJECTLABEL)\; setup\: $(SETUPLABEL)		@@\
	@echo now building on a \`$(BUILDPLATFORM)\' host		@@\
	@echo hoping to run on a \`$(HOSTPLATFORM)\' host
#endif /* BuildMakefileTarget */
\end{code}

@MakefileTarget@: generate rules to build a normal \tr{Makefile}.
\begin{code}
#ifndef MakefileTarget
#define MakefileTarget()						@@\
BuildMakefileTarget()
#endif /* MakefileTarget */
\end{code}

%************************************************************************
%*									*
\subsection[mkworld-macros-MISC]{MISCELLANEOUS macros}
%*									*
%************************************************************************

\begin{code}
#ifndef GenerateOptionsMakeVars
#define GenerateOptionsMakeVars(PGM,THINGS,AllProjectsPgmThings,PlatformPgmThings,ProjectPgmThings,SetupPgmThings) @@\
CAT4(GLUED_,PGM,_,THINGS) = AllProjectsPgmThings PlatformPgmThings ProjectPgmThings SetupPgmThings $(CAT3(PGM,_,THINGS)) $(CAT4(EXTRA_,PGM,_,THINGS))
#endif
\end{code}


%************************************************************************
%*									*
\subsection[mkworld-macros-subdir]{Sub-directories: things for std targets...}
%*									*
%************************************************************************

\subsubsection{@NamedTargetSubdirs@}

Recursively make a series of steps.

\begin{code}
#ifndef NamedTargetSubdirs
#define NamedTargetSubdirs(name,dirs,verb,flags,subname)		@@\
name::									@@\
	@case '${MFLAGS}' in *[ik]*) set +e;; esac; \			@@\
	for i in dirs ;\						@@\
	do \								@@\
		(cd $$i ; echo verb "in $(CURRENT_DIR)/$$i..."; \	@@\
			$(MAKE) $(MFLAGS) flags subname); \		@@\
	done
#endif
\end{code}

\subsubsection{@NamedMakeSubdirs@}

Generate rules to do makes in the given subdirectories.  If you want
@CDEBUGFLAGS@ passed along to subdirectories, provide a line like the
following in the appropriate @Jmakefile@:

\begin{verbatim}
#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
\end{verbatim}

\begin{code}
#ifndef NamedMakeSubdirs
#define NamedMakeSubdirs(name,dirs) \
NamedTargetSubdirs(name,dirs,"making" name,PassCDebugFlags,all)
#endif /* NamedMakeSubdirs */
\end{code}

\subsubsection{@DependSubdirs@}

Generate rules to recursively compute dependencies as
part of the make depend step.

\begin{code}
#ifndef DependSubdirs
#define DependSubdirs(dirs) \
NamedTargetSubdirs(depend,dirs,"making dependencies",/**/,depend)
#endif /* DependSubdirs */
\end{code}



\subsubsection{@DoAllinSubdirs@}

Generate rules to recursively \tr{make all}.  The
\tr{...MakeVarsForAll...} things can be set to have certain
make-variable setting passed downwards.

\begin{code}
#ifndef ProjectMakeVarsForAllinSubdirs
#define ProjectMakeVarsForAllinSubdirs /*none*/
#endif

#ifndef SetupMakeVarsForAllinSubdirs
#define SetupMakeVarsForAllinSubdirs /*none*/
#endif

#ifndef DoAllinSubdirs
#define DoAllinSubdirs(dirs) \
NamedTargetSubdirs(all,dirs,"making all",ProjectMakeVarsForAllinSubdirs SetupMakeVarsForAllinSubdirs,all)
#endif /* DoAllinSubdirs */
\end{code}

\subsubsection{@DoDocsinSubdirs@}
Generate rules to recursively \tr{make docs}.
\begin{code}
#ifndef DoDocsinSubdirs
#define DoDocsinSubdirs(dirs) \
NamedTargetSubdirs(docs,dirs,"making docs",/*no make flags*/,docs)
#endif /* DoDocsinSubdirs */
\end{code}

\subsubsection{@RunTestsSubdirs@}

Generate rules to recursively \tr{make runtests}.

\begin{code}
#ifndef ProjectMakeVarsForRunTestsinSubdirs
#define ProjectMakeVarsForRunTestsinSubdirs /*none*/
#endif

#ifndef SetupMakeVarsForRunTestsinSubdirs
#define SetupMakeVarsForRunTestsinSubdirs /*none*/
#endif

#ifndef RunTestsSubdirs
#define RunTestsSubdirs(dirs) \
NamedTargetSubdirs(runtests,dirs,"running tests",ProjectMakeVarsForRunTestsinSubdirs SetupMakeVarsForRunTestsinSubdirs,runtests)
#endif /* RunTestsSubdirs */
\end{code}

\subsubsection{@InstallSubdirs@}
Generate rules to recursively \tr{make install}.
\begin{code}
#ifndef InstallSubdirs
#define InstallSubdirs(dirs) \
NamedTargetSubdirs(install,dirs,"installing",INSTROOT='$(INSTROOT)',install)
#endif /* InstallSubdirs */
\end{code}

\subsubsection{@InstallDocsSubdirs@}
Generate rules to recursively \tr{make install_docs}.
\begin{code}
#ifndef InstallDocsSubdirs
#define InstallDocsSubdirs(dirs) \
NamedTargetSubdirs(install_docs,dirs,"installing documentation",INSTROOT='$(INSTROOT)',install_docs)
#endif /* InstallDocsSubdirs */
\end{code}

\subsubsection{@CleanSubdirs@}
Generate rules to recursively \tr{make clean}.
\begin{code}
#ifndef NamedCleanSubdirs
#define NamedCleanSubdirs(name,dirs) \
NamedTargetSubdirs(name,dirs,"cleaning",RM='$(RM)',clean)
#endif /* NamedCleanSubdirs */

#ifndef CleanSubdirs
#define CleanSubdirs(dirs) \
NamedCleanSubdirs(clean,dirs)
#endif
\end{code}

\subsubsection{@VeryCleanSubdirs@}
Generate rules to recursively \tr{make veryclean}.
\begin{code}
#ifndef NamedVeryCleanSubdirs
#define NamedVeryCleanSubdirs(name,dirs) \
NamedTargetSubdirs(name,dirs,"being veryclean",RM='$(RM)',veryclean)
#endif /* NamedCleanSubdirs */

#ifndef VeryCleanSubdirs
#define VeryCleanSubdirs(dirs) \
NamedVeryCleanSubdirs(veryclean,dirs)
#endif
\end{code}

\subsubsection{@TagSubdirs@}
Generate rules to recursively \tr{make tags} (create TAGS files).
\begin{code}
#ifndef NamedTagSubdirs
#define NamedTagSubdirs(name,dirs) \
NamedTargetSubdirs(name,dirs,"making tags",,tags)
#endif /* TagSubdirs */

#ifndef TagSubdirs
#define TagSubdirs(dirs) \
NamedTagSubdirs(tags,dirs)
#endif
\end{code}

\subsubsection{@MakeMakeSubdirs@}

Generate rules to recursively recreate Makefiles as part of the
specified step in the build.	If @$(TOP)@ is set to an absolute
path, don't prepend the @../@ prefix.  This makes running things
outside of the source tree much easier.

\begin{code}
#ifndef MakeMakeSubdirs
#define MakeMakeSubdirs(dirs,target)					@@\
target::								@@\
	@case '${MFLAGS}' in *[ik]*) set +e;; esac; \			@@\
	for i in dirs ;\						@@\
	do \								@@\
		echo "making Makefiles in $(CURRENT_DIR)/$$i..."; \	@@\
		case "$$i" in \						@@\
		./?*/?*/?*/?*) newtop=../../../../ sub=subsubsubsub;; \ @@\
		./?*/?*/?*) newtop=../../../ sub=subsubsub;; \		@@\
		./?*/?*)    newtop=../../ sub=subsub;; \		@@\
		./?*)	    newtop=../ sub=sub;; \			@@\
		*/?*/?*/?*)    newtop=../../../../ sub=subsubsubsub;; \ @@\
		*/?*/?*)    newtop=../../../ sub=subsubsub;; \		@@\
		*/?*)	    newtop=../../ sub=subsub;; \		@@\
		*)	    newtop=../ sub=sub;; \			@@\
		esac; \							@@\
		case "$(TOP)" in \					@@\
		/?*) newtop=  upprefix=	 ;; \				@@\
		*) upprefix=../ ;; \					@@\
		esac; \							@@\
		$(MAKE) $${sub}dirMakefiles UPPREFIX=$$upprefix NEWTOP=$$newtop \		@@\
		MAKEFILE_SUBDIR=$$i NEW_CURRENT_DIR=$(CURRENT_DIR)/$$i;\ @@\
	done
#endif /* MakeMakeSubdirs */
\end{code}

\subsubsection{@MakeNsubdirMakefiles@}

Generate rules to create sub Makefiles.

\begin{code}
#ifndef MakeNsubdirMakefiles
#define MakeNsubdirMakefiles()						@@\
subdirMakefiles:							@@\
	$(RM) $(MAKEFILE_SUBDIR)/Makefile.bak				@@\
	-@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \			@@\
	echo "	$(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
	$(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
	else exit 0; fi							@@\
	cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
	$(NEWTOP)$(JRESTOREDEPS); \					@@\
	$(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles			@@\
									@@\
subsubdirMakefiles:							@@\
	$(RM) $(MAKEFILE_SUBDIR)/Makefile.bak				@@\
	-@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \			@@\
	echo "	$(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
	$(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
	else exit 0; fi							@@\
	cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
	$(NEWTOP)$(JRESTOREDEPS); \					@@\
	$(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles			@@\
									@@\
subsubsubdirMakefiles:							@@\
	$(RM) $(MAKEFILE_SUBDIR)/Makefile.bak				@@\
	-@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \			@@\
	echo "	$(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
	$(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
	else exit 0; fi @@\
	cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
	$(NEWTOP)$(JRESTOREDEPS); \					@@\
	$(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles			@@\
									@@\
subsubsubsubdirMakefiles:						@@\
	$(RM) $(MAKEFILE_SUBDIR)/Makefile.bak				@@\
	-@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then \			@@\
	echo "	$(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak"; \ @@\
	$(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \ @@\
	else exit 0; fi							@@\
	cd $(MAKEFILE_SUBDIR); $(JMAKE_CMD) -DTopDirPwd=$(TOP_PWD) -DTopDir=$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(TOP) -DCurDir=$(NEW_CURRENT_DIR); \ @@\
	$(NEWTOP)$(JRESTOREDEPS); \					@@\
	$(MAKE) $(MFLAGS) NEWTOP= Makefile Makefiles
#endif /* MakeNsubdirMakefiles */
\end{code}

\subsubsection{@MakefileSubdirs@}

Generate rules to create \tr{Makefiles}.

\begin{code}
#ifndef MakefileSubdirs
#define MakefileSubdirs(dirs)						@@\
MakeMakeSubdirs(dirs,Makefiles)						@@\
									@@\
MakeNsubdirMakefiles()
#endif /* MakefileSubdirs */
\end{code}

\begin{code}
#ifndef MakeDirectories
#define MakeDirectories(step,dirs)					@@\
step::									@@\
	$(MKDIRHIER) dirs
#endif
\end{code}

\begin{code}
#ifndef LinkDirectories
#define LinkDirectories(step,dirs,todir)				@@\
step::									@@\
	@case '${MFLAGS}' in *[ik]*) set +e;; esac; \			@@\
	for i in dirs ; \						@@\
	do \								@@\
		echo "linking $$i to" todir; \				@@\
		$(LNDIR) todir $$i; \					@@\
	done
#endif
\end{code}
