;########################################################################
;# Jmake rules for building libraries, programs, scripts, and data files
;# $Id: Jmake.rules 18 2006-12-27 10:35:09Z rmanfredi $

/*
 *		   MACHINE-INDEPENDENT RULES -- DO NOT MODIFY
 */

/* $Id: Jmake.rules 18 2006-12-27 10:35:09Z rmanfredi $
 *
 *  Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi
 *  
 *  You may redistribute only under the terms of the Artistic Licence,
 *  as specified in the README file that comes with the distribution.
 *  You may reuse parts of this distribution only within the terms of
 *  that same Artistic Licence; a copy of which may be found at the root
 *  of the source tree for dist 4.0.
 *
 * $Log: Jmake.rules,v $
 * Revision 3.0.1.7  2004/08/22 08:28:58  ram
 * patch71: random cleanup
 *
 * Revision 3.0.1.6  1997/02/28  14:56:01  ram
 * patch61: now handles USRINC for dependencies
 * patch61: smarter about dependencies computation
 *
 * Revision 3.0.1.5  1995/09/25  09:07:19  ram
 * patch59: smarter sed command to strip /usr/include dependencies
 *
 * Revision 3.0.1.4  1995/07/25  13:33:59  ram
 * patch56: install of script man pages can now cope with missing files
 * patch56: the clobber target now removes the .config directory as well
 *
 * Revision 3.0.1.3  1995/03/21  08:35:28  ram
 * patch52: suppressed extra argument to NormalProgramTarget call
 *
 * Revision 3.0.1.2  1995/01/11  14:49:55  ram
 * patch45: new macros ShellScriptTargetExt and SimpleShellScriptTargetExt
 * patch45: directory installation is now made via INSTALLDIR (Configure)
 *
 * Revision 3.0.1.1  1994/10/29  15:46:30  ram
 * patch36: added RemoteDependency rule
 *
 * Revision 3.0  1993/08/18  12:04:14  ram
 * Baseline for dist 3.0 netwide release.
 *
 */

/* Please, edit only with tabstops = 4 (":set ts=4" under vi) */

/*
 * AddedByConfigure:
 *	Gives name of the files generated by Configure that can safely
 *	be removed when a "make clobber" is issued. Not that it is useless
 *	to name config.h or config.sh because these are already taken care
 *	of by jmake.
 */
#define AddedByConfigure(files) @!\
local_clobber::			@@\
	$(RM) files

/*
 * AddSuffix:
 *	Adds a sufix to the .SUFFIXES: list.
 */
#define AddSuffix(ext) @!\
|suffix ext


/*
 * AllTarget:
 *	Generate rules to build necessary things during make all.
 */
#define AllTarget(depends)	@!\
all:: depends				@!\
							@!\
local_realclean::			@@\
	$(RM) depends

/*
 * RemoveTargetProgram:
 *	This is used in some other macros in order to remove the target
 *	before starting its building (saves disk space).  There should be
 *	no '@!' at the end of the '#define' line, because this macro is
 *	used *inside* building rules.
 */
#define RemoveTargetProgram(program) \
	$(RM) program @@\
	if test -f program^^^$(_EXE); then \ @@\
		$(MV) program^^^$(_EXE) program^^~^^^$(_EXE); fi

/*
 * NormalProgramTarget:
 *	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.
 */
#define	NormalProgramTarget(program,sources,objects)	@!\
++OBJECTS objects @!\
++SOURCES sources @!\
NormalObjectRule()				@!\
AllTarget(program)				@!\
								@!\
program: objects				@@\
	RemoveTargetProgram($@)		@@\
	$(CC) -o $@ objects $(JLDFLAGS) $(LIBS) @!\


/*
 * SingleProgramTarget:
 *	Obsolete version of NormalProgramTarget that doesn't have
 *	deplibs.
 */
#define	SingleProgramTarget(program,objects,libs)		\
NormalProgramTarget(program,objects,libs)

/*
 * SimpleProgramTarget:
 *	Generate rules for compiling and linking programs that only have
 *	one C source file.  It should only be used in Jmakefiles that
 *	describe a single program.
 */
#define	SimpleProgramTarget(program)	@!\
NormalProgramTarget(program,program.c,program.o)



/*
 * ComplexProgramTarget:
 *	Generate rules for compiling and linking the program specified by
 *	$(OBJS) and $(SRCS), installing the program and its man page, and
 *	generating dependencies.  It should only be used in Jmakefiles
 *	that describe a single program.
 */
#define	ComplexProgramTarget(program)	@!\
++OBJECTS $(OBJS) @!\
++SOURCES $(SRCS) @!\
NormalObjectRule()					@!\
AllTarget(program)					@!\
									@!\
program: $(OBJS)					@@\
	RemoveTargetProgram($@)			@@\
	$(CC) -o $@ $(OBJS) $(JLDFLAGS) $(LIBS) @!\
									@!\
InstallProgram(program,$(BINDIR))	@!\
InstallManPage(program,$(MANSRC))	@!\
DependTarget()						@!\
LintTarget()


/*
 * ComplexProgramTarget_1:
 *	Generate rules for compiling and linking the program specified by
 *	$(OBJS1) and $(SRCS1), installing the program and its man page,
 *	and generating dependencies for it and any programs described by
 *	$(SRCS2) and $(SRCS3).  It should be used to build the primary
 *	program in Jmakefiles that describe multiple programs.
 */
#define	ComplexProgramTarget_1(program)	@!\
++OBJECTS $(OBJS1) @!\
++SOURCES $(SRCS1) @!\
NormalObjectRule()					@!\
AllTarget(program)					@!\
									@!\
program: $(OBJS1)					@@\
	RemoveTargetProgram($@)			@@\
	$(CC) -o $@ $(OBJS1) $(JLDFLAGS) $(LIBS) @!\
									@!\
InstallProgram(program,$(BINDIR))	@!\
InstallManPage(program,$(MANSRC))	@!\
									@!\
DependTarget()						@!\
LintTarget()


/*
 * ComplexProgramTarget_2:
 *	Generate rules for compiling and linking the program specified by
 *	$(OBJS2) and $(SRCS2) and installing the program and man page.
 *	It should be used to build the second program in Jmakefiles
 *	describing more than one program.
 */
#define	ComplexProgramTarget_2(program)	@!\
++OBJECTS $(OBJS2) @!\
++SOURCES $(SRCS2) @!\
NormalObjectRule()					@!\
AllTarget(program)					@!\
									@!\
program: $(OBJS2)					@@\
	RemoveTargetProgram($@)			@@\
	$(CC) -o $@ $(OBJS2) $(JLDFLAGS) $(LIBS) @!\
									@!\
InstallProgram(program,$(BINDIR))	@!\
InstallManPage(program,$(MANSRC))


/*
 * ComplexProgramTarget_3:
 *	Generate rules for compiling and linking the program specified by
 *	$(OBJS3) and $(SRCS3) and installing the program and man page.  It
 *	should be used to build the third program in Jmakefiles describing
 *	more than one program.
 */
#define	ComplexProgramTarget_3(program) @!\
++OBJECTS $(OBJS3) @!\
++SOURCES $(SRCS3) @!\
NormalObjectRule()					@!\
AllTarget(program)					@!\
									@!\
program: $(OBJS3)					@@\
	RemoveTargetProgram($@)			@@\
	$(CC) -o $@ $(OBJS3) $(JLDFLAGS) $(LIBS) @!\
									@!\
InstallProgram(program,$(BINDIR))	@!\
InstallManPage(program,$(MANSRC))


/*
 * ComplexShellManualTarget:
 *	Builds manual pages that are to be extracted from .SH files into
 *	.$manext files.
 */
#define ComplexShellManualTarget(manpages) @!\
++MANPAGE manpages @!\
|once _ShellManualRule_		@!\
|rule:.SH.$manext:			@!\
|rule: /bin/sh $<			@!\
|rule:						@!\
-once						@!\
AddSuffix(.SH)				@!\
AddSuffix(.$manext)			@!\
AllTarget(manpages)			@!\
							@!\
local_install.man::			@@\
	_MakeInstallDirIgnore($(MANSRC)) \					@@\
	for file in manpages; do \		@@\
		(set -x; $(INSTALL) -c -m 444 $$file \ @@\
			$(INSTALL_PREFIX)$(MANSRC)) || exit 1; \	@@\
	done					@!\
							@!\
local_deinstall.man::		@@\
	@case '${MFLAGS}' in *[i]*) set +e;; esac; \	@@\
	for file in manpages; do \		@@\
		(set -x; $(RM) $(INSTALL_PREFIX)$(MANSRC)/$$file); \	@@\
	done


/*
 * Initialize:
 *	Puts the line symbol = value in the initialization section of
 *	Makefile.SH (the one that is subject to parameter substitutions).
 */
#define Initialize(symbol,value) @!\
+symbol = value


/*
 * InstallLibrary:
 *	Generate rules to install the indicated library.
 */
#define	InstallLibrary(libname,dest)	@!\
local_install:: lib^^libname.a		@@\
	_MakeInstallDirIgnore(dest) \	@@\
	$(INSTALL) -c -m 644 lib^^libname.a $(INSTALL_PREFIX)^^^dest		@@\
	$(RANLIB) dest/lib^^libname.a	@@\
	chmod 444 dest/lib^^libnane.a	@!\
									@!\
local_deinstall::					@@\
	$(RM) $(INSTALL_PREFIX)^^^dest/lib^^libname.a


/*
 * InstallSharedLibrary:
 *	Generate rules to install the shared library.
 */
#define	InstallSharedLibrary(libname,rev,dest)	@!\
local_install:: lib^^libname.so.rev 	@@\
	_MakeInstallDirIgnore(dest) \		@@\
	$(INSTALL) -c -m 444 lib^^libname.so.rev $(INSTALL_PREFIX)^^^dest @!\
										@!\
local_deinstall::						@@\
	$(RM) $(INSTALL_PREFIX)^^^dest/lib^^libname.so.rev


/*
 * InstallSharedLibraryData:
 *	Generate rules to install the shared library data
 */
#define	InstallSharedLibraryData(libname,rev,dest)	@!\
local_install:: lib^^libname.sa.rev		@@\
	_MakeInstallDirIgnore(dest) \		@@\
	$(INSTALL) -c -m 444 lib^^libname.sa.rev $(INSTALL_PREFIX)^^^dest @!\
									@!\
local_deinstall::					@@\
	$(RM) $(INSTALL_PREFIX)^^^dest/lib^^libname.sa.rev


/*
 * InstallLibraryAlias:
 *	Generate rules to create a link from one library name to another
 *	for the purposes of aliasing.
 */
#define	InstallLibraryAlias(libname,alias,dest)	@!\
local_install:: lib^^libname.a	@@\
	$(RM) lib^^alias.a		@@\
	-(cd dest; $(LN) lib^^libname.a lib^^alias.a) @!\
							@!\
local_deinstall::			@@\
	$(RM) dest/lib^^alias.a


/*
 * InstallLintLibrary:
 *	Generate rules to install the indicated lint library.
 */
#define	InstallLintLibrary(libname,dest)	@!\
install.ln:: llib-l^^libname.ln			@@\
	_MakeInstallDirIgnore(dest) \		@@\
	$(INSTALL) -c -m 444 llib-l^^libname.ln $(INSTALL_PREFIX)^^^dest @!\
							@!\
deinstall.ln::				@@\
	$(RM) $(INSTALL_PREFIX)^^^dest/llib-l^^libname.ln


/*
 * InstallManPageLong:
 *	Generate rules to install the indicated manual page, giving it an
 *	alternate name.  This is used for installing man pages whose base
 *	name without the .man suffix would normally be longer than 8
 *	characters (the limit for using source code control systems on
 *	files systems with short file names).
 */
#define	InstallManPageLong(file,destdir,dest)	@!\
local_install.man:: file.man			@@\
	_MakeInstallDirIgnore(destdir) \	@@\
	$(INSTALL) -c -m 444 file.man $(INSTALL_PREFIX)^^^destdir/dest.$(L) @!\
										@!\
local_deinstall.man::					@@\
	$(RM) $(INSTALL_PREFIX)^^^destdir/dest.$(L)		@!\


/*
 * InstallManPage:
 *	Generate rules to install the indicated manual page.
 */
#define	InstallManPage(file,dest)	@!\
InstallManPageLong(file,dest,file)


/*
 * InstallNonExec:
 *	Generate rules to install a data file using any special
 *  install flags.
 */
#define	InstallNonExec(file,dest)	@!\
local_install:: file				@@\
	_MakeInstallDirIgnore(dest) \	@@\
	$(INSTALL) -c -m 444 file $(INSTALL_PREFIX)^^^dest	@!\
									@!\
local_deinstall::					@@\
	$(RM) $(INSTALL_PREFIX)^^^dest/file


/*
 * InstallProgramWithFlags:
 *	Generate rules to install an executable program using given
 *	install flags.
 */
#define InstallProgramWithFlags(program,dest,flags)	@!\
local_install:: program				@@\
	_MakeInstallDirIgnore(dest) \	@@\
	$(INSTALL) -c -s -m 555 flags program^^^$(_EXE) $(INSTALL_PREFIX)^^^dest @!\
									@!\
local_deinstall::					@@\
	$(RM) $(INSTALL_PREFIX)^^^dest/program^^^$(_EXE)


/*
 * InstallProgramNoStripWithFlags:
 *	Generate rules to install an executable program using given
 *	install flags.
 */
#define InstallProgramNoStripWithFlags(program,dest,flags)	@!\
local_install:: program				@@\
	_MakeInstallDirIgnore(dest) \	@@\
	$(INSTALL) -c -m 555 flags program^^^$(_EXE) $(INSTALL_PREFIX)^^^dest @!\
									@!\
local_deinstall::					@@\
	$(RM) $(INSTALL_PREFIX)^^^dest/program^^^$(_EXE)


/*
 * InstallProgram:
 *	Generate rules to install an executable program using any special
 *	install flags set in $(INSTALLFLAGS).
 */
#define	InstallProgram(program,dest)	@!\
InstallProgramWithFlags(program,dest,^^)


/*
 * InstallProgramNoStrip:
 *	Generate rules to install an executable program using any special
 *	install flags set in $(INSTALLFLAGS), but without stripping the
 *	executable from debugging symbols.
 */
#define	InstallProgramNoStrip(program,dest)	@!\
InstallProgramNoStripWithFlags(program,dest,^^)


/*
 * InstallScriptWithFlags:
 *	Generate rules to install an executable script using given
 *	install flags.
 */
#define InstallScriptWithFlags(script,dest,flags)	@!\
local_install:: script				@@\
	_MakeInstallDirIgnore(dest) \	@@\
	$(INSTALL) -c -m 555 flags script $(INSTALL_PREFIX)^^^dest @!\
									@!\
local_deinstall::					@@\
	$(RM) $(INSTALL_PREFIX)^^^dest/script


/*
 * InstallScript:
 *	Generate rules to install an executable script using any special
 *	install flags set in $(INSTALLFLAGS).
 */
#define	InstallScript(script,dest)	@!\
InstallScriptWithFlags(script,dest,^^)


/*
 * InstallScripts:
 *	Generate rules to install all the scripts listed in the generated
 *  $(SCRIPTS) and $(LSCRIPTS) macros.
 */
#define	InstallScripts()	@!\
|once _InstallScripts_		@!\
local_install:: $(SCRIPTS) $(LSCRIPTS) 			@@\
	_MakeInstallDirIgnore($(SCRIPTDIR)) \		@@\
	for file in $(SCRIPTS) $(LSCRIPTS); do \	@@\
		(set -x; \	@@\
		$(INSTALL) -c -m 555 $$file $(INSTALL_PREFIX)$(SCRIPTDIR)) || \	@@\
		exit 1; \	@@\
	done					@!\
							@!\
local_deinstall::			@@\
	@for file in $(SCRIPTS) $(LSCRIPTS); do \	@@\
		case '${MFLAGS}' in *[i]*) set +e;; esac; \	@@\
		(set -x; $(RM) $(INSTALL_PREFIX)$(SCRIPTDIR)/$$file); \	@@\
	done					@!\
-once

/*
 * InstallManScripts:
 *	Generate rule to install/deinstall manual pages for scripts listed
 *	in the automatically generated $(SCRIPTS) macro.
 */
#define InstallManScripts()	@!\
|once _InstallManScripts_	@!\
?NOMAN:|skip				@!\
local_install.man::			@@\
	_MakeInstallDirIgnore($(MANSRC)) \		@@\
	for file in $(SCRIPTS); do \			@@\
		if test -f $$file.man; then \		@@\
			(set -x; \						@@\
			$(INSTALL) -c -m 444 $$file.man \ @@\
				$(INSTALL_PREFIX)$(MANSRC)/$$file.$(L)) || \ @@\
				exit 1; \	@@\
		fi; \				@@\
	done					@!\
							@!\
local_deinstall.man::		@@\
	case '${MFLAGS}' in *[i]*) set +e;; esac; \	@@\
	for file in $(SCRIPTS); do \	@@\
		(set -x; $(RM) $(INSTALL_PREFIX)$(MANSRC)/$$file.$(L)); \	@@\
	done					@!\
							@!\
-skip						@!\
-once



/*
 * LinkFileList:
 *	Link a list of list of files from one place to another
 */
#define LinkFileList(step,list,dir,sub)	@!\
step:: list							@@\
	@case '${MFLAGS}' in *[i]*) set +e;; esac; \	@@\
	echo "	cd" dir; cd dir; for i in list; do (set -x; $(LN) sub/$$i .); done


/*
 * InstallMultipleDestFlags:
 *	Generate rules to install multiple files at once during a particular
 *	step in the build using a specific set of install flags.
 */
#define InstallMultipleDestFlags(step,list,dest,flags)	@!\
step:: list							@@\
	_MakeInstallDirIgnore(dest) \	@@\
	for i in list; do \				@@\
		(set -x; $(INSTALL) -c flags \ @@\
			$$i $(INSTALL_PREFIX)^^^dest) || exit 1;\	@@\
	done

/*
 * DeinstallMultipleDest:
 *	Generate rules to deinstall multiple files at once during a particular
 *	step in the build.
 */
#define DeinstallMultipleDest(step,list,dest)	@!\
step::								@@\
	@case '${MFLAGS}' in *[i]*) set +e;; esac; \	@@\
	for i in list; do \				@@\
		(set -x; $(RM) $(INSTALL_PREFIX)^^^dest/$$i); \	@@\
	done

/*
 * InstallMultiple:
 *	Generate rules to install multiple files at once during the install
 *	step of the build using any install flags set in $(INSTALLFLAGS)
 *	and deinstall them.
 */
#define	InstallMultiple(list,dest)	@!\
InstallMultipleDestFlags(local_install,list,dest,$(INSTALLFLAGS)) @!\
DeinstallMultipleDest(local_deinstall,list,dest) 


/*
 * InstallMultipleFlags:
 *	Generate rules to install multiple files at once during the
 *	install step of the build using the given install flags.
 */
#define InstallMultipleFlags(list,dest,flags)	@!\
InstallMultipleDestFlags(local_install,list,dest,flags) @!\
DeinstallMultipleDest(local_deinstall,list,dest)


/*
 * InstallMultipleMan:
 *	Generate rules to install a variety of manual pages
 *	during the install.man step of the build.
 */
#define InstallMultipleMan(list,dest)	@!\
InstallMultipleDestFlags(local_install.man,list,dest,$(INSTALLFLAGS)) @!\
DeinstallMultipleDest(local_deinstall.man,list,dest) 


/*
 * DependDependency:
 *	Generate rules to build the makedepend program.
 */
#define DependDependency() 			@!\
depend:: TOPDIR/mkdep				@!\
									@!\
TOPDIR/mkdep:						@!\
?TOP: @echo "You have to run Configure first."; exit 1	@!\
%TOP: @echo "You have to run Configure in $(TOP) first."; exit 1


/*
 * DependTarget:
 *	Generate rules to compute dependencies for all files listed
 *	in $(SOURCES) (automatically generated macro).
 */
#define	DependTarget()				@!\
+USRINC = $usrinc @!\
|once _DependTarget_				@!\
DependDependency()					@!\
									@!\
depend::							@@\
	($(SED) '/^# DO NOT DELETE/q' Makefile && \ @@\
	$(MKDEP) $(SOURCES) | \			@@\
	$(SED) -e 's:/usr/lib[^ ]*::g; s:$(USRINC)[^ ]*::g; ' \ @@\
		-e '/: / b print' -e '$$ b print' -e 'H; d; n; : print' \ @@\
		-e 'x; s/\\$$//; s/\\\n//g; s/ ^^ */ /g; s/ :/:/;' -e '/: *$$/d' \ @@\
	) > Makefile.new				@@\
	cp Makefile Makefile.bak		@@\
	cp Makefile.new Makefile		@@\
	$(RM) Makefile.new				@!\
									@!\
-once


/*
 * CleanTarget:
 *	Generate rules to remove any garbage files.
 */
#define	CleanTarget()				@!\
?SUBDIRS:clean: sub_clean local_clean				@!\
%SUBDIRS:clean: local_clean							@!\
?SUBDIRS:realclean: sub_realclean local_realclean	@!\
%SUBDIRS:realclean: local_realclean					@!\
?SUBDIRS:clobber: sub_clobber local_clobber			@!\
%SUBDIRS:clobber: local_clobber						@!\
									@!\
local_clean:: 						@@\
	if test -f core; then $(RM) core; fi @@\
	$(RM) *~ *.o					@!\
									@!\
local_realclean:: local_clean		@!\
?TOP: $(RM) -r UU					@!\
									@!\
local_clobber:: local_realclean		@!\
%TOP: $(RM) Makefile config.sh		@!\
?TOP: $(RM) config.sh config.h		@!\
?TOP: $(RM) -r .config				@!\
?TOP: $(RM) Makefile				@!\


/*
 * InstallTarget:
 *	Generate rules to recursively install files
 */
#define	InstallTarget()											@!\
?SUBDIRS:install:: local_install sub_install					@!\
%SUBDIRS:install:: local_install								@!\
?SUBDIRS:install.man:: maybe_install.man sub_install.man		@!\
%SUBDIRS:install.man:: maybe_install.man						@!\
?SUBDIRS:deinstall:: sub_deinstall local_deinstall				@!\
%SUBDIRS:deinstall:: local_deinstall							@!\
?SUBDIRS:deinstall.man:: sub_deinstall.man maybe_deinstall.man	@!\
%SUBDIRS:deinstall.man:: maybe_deinstall.man					@!\
																@!\
?MANSRC:install.man-yes: local_install.man						@!\
install.man-no:													@!\
?MANSRC:deinstall.man-yes: local_deinstall.man					@!\
deinstall.man-no:												@!\


/*
 * TagsTarget:
 *	Generate rules to compute tags files for C source code.
 */
#define	TagsTarget()				@!\
tags::								@@\
	$(CTAGS) -w *.[ch]				@@\
	$(CTAGS) -xw *.[ch] > tags		@!\
									@!\
local_clobber::						@@\
	$(RM) tags



/*
 * BuildMakefileSH:
 *	Generate rules to build a Makefile.SH from an Jmakefile and any
 *	special jmake flags.  This is generally done automatically by the
 *	template or by any special Jmakefiles.
 *	This function will simply touch Makefile.SH if no $(TOP)/.package
 *	exists, assuming the Jmakefile is not in a production environment.
 */
#define	BuildMakefileSH(jmakeflags)	@!\
Makefile.SH: Jmakefile 				@@\
	-@if test -f $(TOP)/.package; then \ @@\
		if test -f Makefile.SH; then \	@@\
			echo "	$(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \ @@\
			$(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \	@@\
		fi; \						@@\
		echo "	$(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" jmakeflags; \ @@\
		$(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) jmakeflags; \ @@\
	else touch $@; fi


/*
 * BuildMakefile:
 *	Generate rules to build a Makefile from a Makefile.SH.
 */
#define	BuildMakefile()	@!\
Makefile: Makefile.SH				@@\
	/bin/sh Makefile.SH


/*
 * MakefileTarget:
 *	Generate rules to build a normal Makefile.
 */
#define MakefileTarget()		@!\
BuildMakefileSH(^^)				@!\
BuildMakefile()


/*
 * NormalObjectRule:
 *	Generate make rule to build usual object files.
 */
#define	NormalObjectRule()			@!\
|once _ObjectRule_					@!\
|rule:.c.o:							@!\
|rule: $(CC) -c $(JCFLAGS) $<		@!\
|rule:								@!\
-once

/*
 * NormalLibraryObjectRule:
 *	Generate make rules to build "normal" objects.
 */
#define	NormalLibraryObjectRule()	@!\
|once _ObjectRule_					@!\
|rule:.c.o:							@!\
|rule: $(RM) $@						@!\
|rule: $(CC) -c $(JCFLAGS) $<		@!\
|rule:								@!\
-once

/*
 * ProfiledLibraryObjectRule:
 *	Generate make rules to build both profiled and "normal" objects.
 */
#define	ProfiledLibraryObjectRule()	@!\
all::								@@\
	@if [ ! -d profiled ]; then mkdir profiled; fi	@!\
									@!\
|rule:.c.o:							@!\
|rule: $(RM) $@ profiled/$@			@!\
|rule: $(CC) -pg -c $(JCFLAGS) $*.c	@!\
|rule: $(MV) $*.o profiled/$*.o		@!\
|rule: $(CC) -c $(JCFLAGS) $*.c		@!\
|rule:								@!\
local_clean:: 						@@\
	-@if [ -d profiled ]; then echo "	$(RM) profiled/?*.o"; \	@@\
		$(RM) profiled/?*.o; fi


/*
 * DebuggedLibraryObjectRule:
 *	Generate make rules to build both debuggable and "normal"
 *	objects.
 */
#define	DebuggedLibraryObjectRule()					@!\
all::									@@\
	@if [ ! -d debugger ]; then mkdir debugger; fi	@!\
									@!\
|rule:.c.o:							@!\
|rule: $(RM) $@ debugger/$@			@!\
|rule: $(CC) -g -c $(JCFLAGS) $*.c	@!\
|rule: $(MV) $*.o debugger/$*.o		@!\
|rule: $(CC) -c $(JCFLAGS) $*.c		@!\
|rule:								@!\
local_clean::						@@\
	-@if [ -d debugger ]; then echo "	$(RM) debugger/?*.o"; \ @@\
		$(RM) debugger/?*.o; fi


/*
 * DebuggedAndProfiledLibraryOjbectRule:
 *	Generate make rules to build debuggable, profiled, and "normal"
 *	objects.
 */
#define	DebuggedAndProfiledLibraryObjectRule()	@!\
all::									@@\
	@if [ ! -d profiled ]; then mkdir profiled; fi	@@\
	@if [ ! -d debugger ]; then mkdir debugger; fi	@!\
										@!\
|rule:.c.o:								@!\
|rule: $(RM) $@ profiled/$@ debugger/$@	@!\
|rule: $(CC) -pg -c $(JCFLAGS) $*.c		@!\
|rule: $(MV) $*.o profiled/$*.o			@!\
|rule: $(CC) -g -c $(JCFLAGS) $*.c		@!\
|rule: $(MV) $*.o debugger/$*.o			@!\
|rule: $(CC) -c $(JCFLAGS) $*.c			@!\
|rule:									@!\
local_clean::							@@\
	-@if [ -d profiled ]; then echo "	$(RM) profiled/?*.o"; \ @@\
		$(RM) profiled/?*.o; fi			@@\
	-@if [ -d debugger ]; then echo "	$(RM) debugger/?*.o"; \ @@\
		$(RM) debugger/?*.o; fi


/*
 * SharedLibraryObjectRule:
 *	Generate make rules to build shared and "normal" object files.
 */
#define SharedLibraryObjectRule()					@!\
all::								@@\
	@if [ ! -d shared ]; then mkdir shared; fi		@!\
									@!\
|rule:.c.o:							@!\
|rule: $(RM) $@ shared/$@			@!\
|rule: $(CC) -pic -c $(SHAREDCODEDEF) $(SHLIBDEF) $(JCFLAGS) $*.c	@!\
|rule: $(MV) $*.o shared/$*.o		@!\
|rule: $(CC) -c $(SHLIBDEF) $(JCFLAGS) $*.c				@!\
|rule:								@!\
local_clean::						@@\
	-@if [ -d shared ]; then echo "	$(RM) shared/?*.o"; \		@@\
		$(RM) shared/?*.o; fi

/*
 * SharedAndDebuggedLibraryObjectRule:
 *	Generate make rules to build shared, debuggable, and "normal"
 *	object files.
 */
#define SharedAndDebuggedLibraryObjectRule()	@!\
all::										@@\
	@if [ ! -d shared ]; then mkdir shared; fi		@@\
	@if [ ! -d debugger ]; then mkdir debugger; fi	@!\
											@!\
|rule:.c.o:									@!\
|rule: $(RM) $@ shared/$@ debugger/$@		@!\
|rule: $(CC) -pic -c $(SHAREDCODEDEF) $(SHLIBDEF) $(JCFLAGS) $*.c	@!\
|rule: $(MV) $*.o shared/$*.o				@!\
|rule: $(CC) -g -c $(SHLIBDEF) $(JCFLAGS) $*.c	@!\
|rule: $(MV) $*.o debugger/$*.o				@!\
|rule: $(CC) -c $(SHLIBDEF) $(JCFLAGS) $*.c	@!\
|rule:										@!\
local_clean:: 								@@\
	-@if [ -d shared ]; then echo "	$(RM) shared/?*.o"; \		@@\
		$(RM) shared/?*.o; fi				@@\
	-@if [ -d debugger ]; then echo "	$(RM) debugger/?*.o"; \ @@\
		$(RM) debugger/?*.o; fi

/*
 * SpecialSharedAndDebuggedObjectRule:
 *	Generate rules to compile a file with special flags and to make
 *	shared and debuggable versions.
 */
#define	SpecialSharedAndDebuggedObjectRule(objs,depends,options)	@!\
all::									@@\
	@if [ ! -d shared ]; then mkdir shared; fi		@@\
	@if [ ! -d debugger ]; then mkdir debugger; fi	@!\
										@!\
objs:	depends							@@\
	$(RM) $@ shared/$@ debugger/$@		@@\
	$(CC) -pic -c $(SHAREDCODEDEF) $(SHLIBDEF) $(JCFLAGS) options $*.c @@\
	$(MV) $*.o shared/$*.o				@@\
	$(CC) -g -c $(SHLIBDEF) $(JCFLAGS) options $*.c			@@\
	$(MV) $*.o debugger/$*.o			@@\
	$(CC) -c $(SHLIBDEF) $(JCFLAGS) options $*.c

/*
 * SpecialSharedObjectRule:
 *	Generate rules to compile a file with special flags and to make
 *	shared and debuggable versions.
 */
#define	SpecialSharedObjectRule(objs,depends,options)		@!\
all::									@@\
	@if [ ! -d shared ]; then mkdir shared; fi		@!\
										@!\
objs:	depends							@@\
	$(RM) $@ shared/$@ 					@@\
	$(CC) -pic -c $(SHAREDCODEDEF) $(SHLIBDEF) $(JCFLAGS) options $*.c @@\
	$(MV) $*.o shared/$*.o				@@\
	$(CC) -c $(SHLIBDEF) $(JCFLAGS) options $*.c


/*
 * SpecialObjectRule:
 *	Generate rules to compile a file with special flags.
 */
#define SpecialObjectRule(objs,depends,options)		@!\
objs:	depends							@@\
	$(RM) $@							@@\
	$(CC) -c $(JCFLAGS) options $*.c


/*
 * SpecialProfiledObjectRule:
 *	Generate rules to compile a file with special flags and to make a
 *	profiled version.
 */
#define	SpecialProfiledObjectRule(objs,depends,options)			@!\
all::									@@\
	@if [ ! -d profiled ]; then mkdir profiled; fi	@!\
										@!\
objs:	depends							@@\
	$(RM) $@ profiled/$@				@@\
	$(CC) -pg -c $(JCFLAGS) options $*.c	@@\
	$(MV) $*.o profiled/$*.o			@@\
	$(CC) -c $(JCFLAGS) options $*.c


/*
 * SpecialDebuggedObjectRule:
 *	Generate rules to compile a file with special flags and to make a
 *	debuggable version.
 */
#define	SpecialDebuggedObjectRule(objs,depends,options)	@!\
all::									@@\
	@if [ ! -d debugger ]; then mkdir debugger; fi	@!\
										@!\
objs:	depends							@@\
	$(RM) $@ debugger/$@				@@\
	$(CC) -g -c $(JCFLAGS) options $*.c	@@\
	$(MV) $*.o debugger/$*.o			@@\
	$(CC) -c $(JCFLAGS) options $*.c


/*
 * SpecialDebuggedAndProfiledObjectRule:
 *	Generate rules to compile a file with special flags and to make
 *	debuggable and profiled versions.
 */
#define	SpecialDebuggedAndProfiledObjectRule(objs,depends,options)	@!\
all::									@@\
	@if [ ! -d profiled ]; then mkdir profiled; fi	@@\
	@if [ ! -d debugger ]; then mkdir debugger; fi	@!\
										@!\
objs:	depends							@@\
	$(RM) $@ profiled/$@ debugger/$@	@@\
	$(CC) -pg -c $(JCFLAGS) options $*.c	@@\
	$(MV) $*.o profiled/$*.o			@@\
	$(CC) -g -c $(JCFLAGS) options $*.c	@@\
	$(MV) $*.o debugger/$*.o			@@\
	$(CC) -c $(JCFLAGS) options $*.c


/*
 * NormalLibraryTarget:
 *	Generate rules to create a library. The 'srclist' and 'objlist'
 *	parameters are added to SOURCES and OBJECTS macros. The 'srclist'
 *	is not otherwise used by this rule, but is necessary for make depend.
 */
#define	NormalLibraryTarget(libname,srclist,objlist)	@!\
++OBJECTS objlist @!\
++SOURCES srclist @!\
NormalLibraryObjectRule()		@!\
AllTarget(lib^^libname.a)		@!\
								@!\
lib^^libname.a: objlist			@@\
	$(RM) $@					@@\
	$(AR) $@ objlist			@@\
	$(RANLIB) $@


/*
 * NormalSharedLibraryTarget:
 *	Generate rules to create a shared library; build it into a
 *	different name so that the we don't hose people by having the
 *	library gone for long periods.
 */
#define NormalSharedLibraryTarget(libname,rev,solist)	@!\
AllTarget(lib^^libname.so.rev)	@!\
									@!\
lib^^libname.so.rev:  solist		@@\
	$(RM) $@~						@@\
	(cd shared; $(LD) -o ../$@~ -assert pure-text solist)		@@\
	$(RM) $@ 						@@\
	$(MV) $@~ $@

/*
 * NormalSharedLibraryDataTarget:
 *	Generate rules to create shlib data file; build it into a
 *	different name so that the we don't hose people by having the
 *	library gone for long periods.
 */
#define NormalSharedLibraryDataTarget(libname,rev,salist)	@!\
AllTarget(lib^^libname.sa.rev)	@!\
									@!\
lib^^libname.sa.rev:  salist		@@\
	$(RM) $@						@@\
	$(AR) $@ salist					@@\
	$(RANLIB) $@


/*
 * NormalLibraryTarget2:
 *	Generate rules to create a library in two steps.  This is used to
 *	create libraries with large numbers of files.
 */
#define	NormalLibraryTarget2(libname,srclist,objlist1,objlist2)	@!\
++SOURCES srclist @!\
++OBJECTS objlist1 @!\
++OBJECTS objlist2 @!\
NormalLibraryObjectRule()			@!\
AllTarget(lib^^libname.a)			@!\
									@!\
lib^^libname.a: objlist1 objlist2	@@\
	$(RM) $@						@@\
	$(AR) $@ objlist1				@@\
	$(AR) $@ objlist2				@@\
	$(RANLIB) $@


/*
 * ProfiledLibraryTarget:
 *	Generate rules to create a profiled library.
 */
#define	ProfiledLibraryTarget(libname,srclist,objlist)	@!\
++SOURCES srclist @!\
++OBJECTS objlist @!\
AllTarget(lib^^libname^^_p.a)		@!\
									@!\
lib^^libname^^_p.a: objlist			@@\
	$(RM) $@						@@\
	cd profiled; $(AR) ../$@ objlist	@@\
	$(RANLIB) $@


/*
 * DebuggedLibraryTarget:
 *	Generate rules to create a debuggable library.
 */
#define	DebuggedLibraryTarget(libname,srclist,objlist)	@!\
++SOURCES srclist @!\
++OBJECTS objlist @!\
AllTarget(lib^^libname^^_d.a)		@!\
									@!\
lib^^libname^^_d.a: objlist			@@\
	$(RM) $@							@@\
	cd debugger; $(AR) ../$@ objlist	@@\
	$(RANLIB) $@


/*
 * AliasedLibraryTarget:
 *	Generate rules to link one library to another.
 */
#define	AliasedLibraryTarget(libname,alias)	@!\
AllTarget(lib^^alias.a)			@!\
								@!\
lib^^alias.a: lib^^libname.a	@@\
	$(RM) $@					@@\
	$(LN) lib^^libname.a $@


/*
 * PrelinkedRelocatableTarget:
 *	Generate rules to produce a relocatable object file instead of a
 *	library.
 */
#define	PrelinkedRelocatableTarget(objname,objlist,libs)	@!\
AllTarget(objname.o)				@!\
									@!\
objname.o: objlist					@@\
	$(RM) $@						@@\
	$(LD) $(JLDFLAGS) -r objlist -o $@ libs


/*
 * NormalObjectTarget:
 *	Generate rules to produce a single object file.o from a file.c.
 */
#define	NormalObjectTarget(file)	@!\
++SOURCES file^^.c					@!\
AllTarget(file^^.o)					@!\
NormalObjectRule()

/*
 * NormalRelocatableTarget:
 *	Generate rules to produce a relocatable object file instead of a
 *	library.
 */
#define	NormalRelocatableTarget(objname,objlist)	@!\
AllTarget(objname.o)				@!\
									@!\
objname.o: objlist					@@\
	$(RM) $@						@@\
	$(LD) $(JLDFLAGS) -r objlist -o $@


/*
 * ProfiledRelocatableTarget:
 *	Generate rules to produce a profiled relocatable object file
 *	instead of a library.
 */
#define	ProfiledRelocatableTarget(objname,objlist)	@!\
AllTarget(objname^^_p.o)		@!\
								@!\
objname^^_p.o: objlist			@@\
	$(RM) $@					@@\
	$(LD) -X -r objlist -o $@


/*
 * DebuggedRelocatableTarget:
 *	Generate rules to produce a debuggable relocatable object file
 *	instead of a library.
 */
#define	DebuggedRelocatableTarget(objname,objlist)	@!\
AllTarget(objname^^_d.o)		@!\
								@!\
objname^^_d.o: objlist			@@\
	$(RM) $@					@@\
	$(LD) -X -r objlist -o $@

/*
 * LintLibraryTarget:
 *	Generate rules to create a lint library.  Note that the lint
 *	library is always forced to be newer than the library itself.
 */
#define	LintLibraryTarget(libname,srclist)	@!\
lintlib:: llib-l^^libname.ln	@!\
								@!\
llib-l^^libname.ln: srclist		@@\
	$(RM) $@					@@\
	$(LINT) $(LINTLIBFLAG)^^libname $(LINTFLAGS) srclist


/*
 * NormalLintTarget:
 *	Generate rules to lint a set of sources.
 */
#define NormalLintTarget(srclist)	@!\
lint:								@@\
	$(LINT) $(LINTFLAGS) srclist $(LINTLIBS)


/*
 * LintTarget:
 *	Generate rules to lint $(SOURCES) (automatically generated)
 */
#define LintTarget()			@!\
|once _LintTarget_				@!\
NormalLintTarget($(SOURCES))	@!\
-once


/*
 * LinkSourceFile:
 *	Snag source file from some other directory
 */
#define LinkSourceFile(src,dir)		@!\
src:  dir/src			@@\
	$(RM) $@			@@\
	$(LN) $? $@			@!\


/*
 * MakeSubincludesForBuild:
 *	Make includes in sub directories.
 */
#define MakeSubincludesForBuild(step,dir,srclist)	@!\
step::  dir srclist								@@\
	@-(list=`echo srclist | sed -e 's/[^ ]*\///g'`; \		@@\
		set -x; cd dir; $(RM) $$list)			@@\
	@for i in srclist; do \						@@\
		(set -x; cd dir; $(LN) ../$$i .) || exit 1; \		@@\
	done										@!\
												@!\
MakeDirectories(dir,dir)						@!\
												@!\
local_realclean:: 								@@\
	@-(if [ -d dir ]; then \					@@\
		list=`echo srclist | sed -e 's/[^ ]*\///g'`; \		@@\
		set -x; cd dir; $(RM) $$list; fi)


/*
 * CommonSubdirsRule:
 *	Rule for making $(TARGET) in every subdirectory, with $(VERB) as
 *	verbose message and $(FLAGS) as additional flags.
 */
#define CommonSubdirsRule(dirs) @!\
subdirs: 						@@\
	@case '${MFLAGS}' in *[ik]*) set +e;; esac; \			@@\
	for i in dirs ;\					@@\
	do \								@@\
		(cd $$i ; echo $(VERB) "in $(DIR)$$i..."; \		@@\
			$(MAKE) $(MFLAGS) $(FLAGS) $(TARGET)) || exit 1; \	@@\
	done
	

/*
 * NamedTargetSubdirsRule:
 *	Recursively make a series of steps in the specified directories.
 */
#define NamedTargetSubdirsRule(dirs,name,verb,flags)	@!\
name::									@@\
	@case '${MFLAGS}' in *[ik]*) set +e;; esac; \		@@\
	for i in dirs ;\					@@\
	do \								@@\
		(cd $$i ; echo verb "in $(DIR)$$i..."; \	@@\
			$(MAKE) $(MFLAGS) flags name) || exit 1; \	@@\
	done
	
	
/*
 * NamedTargetSubdirs:
 *	Recursively make a series of steps.
 */
#define NamedTargetSubdirs(name,verb,flags)		@!\
name:: 									@@\
	@$(MAKE) subdirs TARGET=name VERB=verb FLAGS=flags


/*
 * NamedSubTargetSubdirs:
 *	Recursively make a series of steps, like NamedTargetSubdirs.
 *	However, the supplied "name" has "sub_" prefixed to it.
 */
#define NamedSubTargetSubdirs(name,verb,flags)	@!\
sub_^^^name:: 									@@\
	@$(MAKE) subdirs TARGET=name VERB=verb FLAGS=flags

/*
 * NamedDepthTargetSubdirs:
 *	Recursively make a series of steps. We first enter the
 *	subdirectories, then perform the local entries.
 *	The supplied "name" has "sub_" prefixed to it.
 */
#define NamedDepthTargetSubdirs(name,verb,flags)		@!\
sub_^^^name:: 					@@\
	@$(MAKE) subdirs TARGET=name VERB=verb FLAGS=flags	@@\
	@echo "Back to $(CURRENT) for "name^^...


/*
 * MakeSubdirs:
 *	Generate rules to do makes in the given subdirectories.
 */
#define MakeSubdirs() \
NamedTargetSubdirs(all,"Making all",^^)


/*
 * DependDirs:
 *	Generate rules to recursively compute dependencies as part of the
 *	make depend step.
 */
#define DependDirs(dirs) \
NamedTargetSubdirsRule(dirs,depend,"Depending",^^)


/*
 * DependSubdirs:
 *	Generate rules to recursively compute dependencies as part of the
 *	make depend step.
 */
#define DependSubdirs() \
DependDirs($(SUBDIRS))


/*
 * InstallSubdirs:
 *	Generate rules to recursively install and deinstall programs and
 *	files.
 */
#define InstallSubdirs() \
NamedSubTargetSubdirs(install,"Installing",^^) @!\
NamedDepthTargetSubdirs(deinstall,"Deinstalling",^^)


/*
 * InstallManSubdirs:
 *	Generate rules to recursively install and deinstall manual pages.
 */
#define InstallManSubdirs() \
NamedSubTargetSubdirs(install.man,"Installing man pages",^^) @!\
NamedDepthTargetSubdirs(deinstall.man,"Deinstalling man pages",^^)


/*
 * IncludesSubdirs:
 *	Generate rules to recursively put include files in build
 */
#define IncludesSubdirs() \
NamedTargetSubdirs(includes,including,^^)


/*
 * CleanSubdirs:
 *	Generate rules to recursively clean out garbage files.
 */
#define CleanSubdirs() \
NamedDepthTargetSubdirs(clean,"Cleaning",^^)	@!\
NamedDepthTargetSubdirs(realclean,"Real cleaning",^^)	@!\
NamedDepthTargetSubdirs(clobber,"Clobbering",^^)


/*
 * TagSubdirs:
 *	Generate rules to recursively create tags files.
 */
#define TagSubdirs(dirs) \
NamedTargetSubdirsRule(dirs,tag,"Tagging",^^)

/*
 * MakeLintSubdirs:
 *	Generate rules to recursively lint directories as part of the
 *	named step.
 */
#define MakeLintSubdirs(dirs,target) \
NamedTargetSubdirsRule(dirs,target,"Linting",^^)


/*
 * LintDirs:
 *	Generate rules to recursively lint directories as part of the
 *	make lint step.
 */
#define LintDirs(dirs) \
MakeLintSubdirs(dirs,lint)


/*
 * LintSubdirs:
 *	Generate rules to recursively lint directories as part of the
 *	make lint step.
 */
#define LintSubdirs() \
LintDirs($(SUBDIRS))


/*
 * MakeDirs:
 *	Creates a set of directories, even if some directories in the path
 *	do not already exist. There should be no '@!' at the end of the
 *	'#define' line, because this macro is used *inside* building rules.
 */
#define MakeDirs(dirs)	\
	@case '${MFLAGS}' in *[i]*) set +e;; esac; \			@@\
	for dir in dirs; do \									@@\
		(set -x; test -d $$dir || $(INSTALLDIR) $$dir) || \ @@\
		exit 1; \		@@\
	done

/*
 * _MakeInstallDirs:
 *	Creates a set of intall directories, even if some directories in the path
 *	do not already exist. There should be no '@!' at the end of the
 *	'#define' line, because this macro is used *inside* building rules.
 */
#define _MakeInstallDirs(dirs) \
	@case '${MFLAGS}' in *[i]*) set +e;; esac; \	@@\
	for dir in dirs; do	\							@@\
		_MakeInstallDir($$dir)	\					@@\
	done

/*
 * _MakeInstallDir:
 *	Internal macro to create a missing install directory.
 */
#define _MakeInstallDir(dir) \
	(set -x; test -d $(INSTALL_PREFIX)^^^dir || \	@@\
		$(INSTALLDIR) $(INSTALL_PREFIX)^^^dir);

/*
 * _MakeInstallDirIgnore:
 *	Same as _MakeInstallDir but handles "make -i" as well.
 */
#define _MakeInstallDirIgnore(dir) \
	@case '${MFLAGS}' in *[i]*) set +e;; esac;		\ @@\
	_MakeInstallDir(dir)

/*
 * _RmInstallDirs:
 *	Removes a set of intall directories.
 *	There should be no '@!' at the end of the '#define' line, because this
 *	macro is used *inside* building rules.
 */
#define _RmInstallDirs(dirs) \
	@case '${MFLAGS}' in *[i]*) set +e;; esac; \	@@\
	for dir in dirs; do \							@@\
		(set -x; test -d $$dir && $(RM) -r $(INSTALL_PREFIX)$$dir); \	@@\
	done

/*
 * MakeDirectories:
 *	Generate rules to create a hierarchy of directories.
 */
#define MakeDirectories(step,dirs)		@!\
step::									@@\
	MakeDirs(dirs)


/*
 * MakeInstallDirectories:
 *	Generate a rule to create a set of directories at installation
 *	time (removed by deinstall).
 */
#define MakeInstallDirectories(dirs) @!\
local_install::				@@\
	_MakeInstallDirs(dirs)	@!\
							@!\
local_deinstall::			@@\
	_RmInstallDirs(dirs)


/*
 * MakeLintLibSubdirs:
 *	Generate rules to recursively create lint libraries.
 */
#define MakeLintLibSubdirs(dirs)	@!\
MakeLintSubdirs(dirs,lintlib)


/*
 * MakeMakeSubdirs:
 *	Generate rules to recursively recreate target as part of the
 *	specified step in the build.  This assumes Makefile.SH has
 *	already been built (which is the case for a delivery), but does
 *	not rely on the existence of a Makefile.
 */
#define MakeMakeSubdirs(target)	@!\
target::								@@\
	@case '${MFLAGS}' in *[ik]*) set +e;; esac; \	@@\
	for i in $(SUBDIRS);\				@@\
	do \								@@\
		echo "Making "target" in $(DIR)$$i..."; \	@@\
		(cd $$i || exit 1; \			@@\
		if test ! -f Makefile; then /bin/sh Makefile.SH; fi; \ @@\
		$(MAKE) $(MFLAGS) target) || exit 1;\	@@\
	done


/*
 * MakeMakefilesSH:
 *	Generate rules to recursively recreate target 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 to be much easier.
 */
#define MakeMakefilesSH()		@!\
Makefiles.SH:: Makefile.SH				@@\
	@case '${MFLAGS}' in *[ik]*) set +e;; esac; \	@@\
	for i in $(SUBDIRS);\					@@\
	do \								@@\
		case "$(DIR)$$i/" in \								@@\
		^^*^^/^^*^^/^^*^^/^^*^^/) newtop=../../../..;; \	@@\
		^^*^^/^^*^^/^^*^^/) newtop=../../..;; \				@@\
		^^*^^/^^*^^/) newtop=../..;; \						@@\
		*^^/) newtop=..;; \									@@\
		esac; \												@@\
		case "$(TOP)" in \				@@\
		/^^*) newtop="$(TOP)" ;; \		@@\
		esac; \							@@\
		echo "Making Makefiles.SH in $(DIR)$$i..."; \	@@\
		(cd $$i || exit 1; \			@@\
			if test -f Jmakefile; then \	@@\
				$(MAKE) $(MFLAGS) -f ../Makefile \	@@\
					Makefile TOP=$$newtop CURRENT=$(DIR)$$i && \ 	@@\
				$(MAKE) $(MFLAGS) Makefiles.SH; \	@@\
			fi; \						@@\
		) || exit 1; \	@@\
	done


/*
 * MakefileSubdirs:
 *	Generate rules to create Makefiles.
 */
#define MakefileSubdirs()		@!\
MakeMakeSubdirs(Makefiles)		@!\
MakeMakefilesSH()


/*
 * CppScriptTarget:
 *	Generate rules to create a shell script by running the input
 *	through cpp.
 */
#define CppScriptTarget(dst,src,defs,deplist)	@!\
dst::  src deplist						@@\
	$(RM) $@							@@\
	$(CPP) defs <src | \				@@\
		sed -e '/^#  *[0-9][0-9]*  *.*$$/d' >$@		@@\
	chmod a+x $@


/*
 * MakeScriptFromCpp:
 *	Generate rules to create a script from a file with a
 *	.cpp suffix.
 */
#define MakeScriptFromCpp(name,defs)	@!\
CppScriptTarget(name,name.cpp,defs,^^)


/*
 * ShellScriptTargetExt:
 *	Generate rules to create and install a set of scripts from
 *	ext files (.sh and .SH are the most common examples). Man pages
 *	derived from the name of the scripts are also installed unless
 *	NoManPages() is specified.
 */
#define ShellScriptTargetExt(scripts,ext)	@!\
++SCRIPTS scripts @!\
SimpleShellScriptTargetExt(scripts,ext)		@!\
InstallScripts()							@!\
InstallManScripts()


/*
 * ShellScriptTarget:
 *	Generate rules to create and install a set of scripts from
 *	.SH files. Man pages derived from the name of the scripts are
 *	also installed unless NoManPages() is specified.
 */
#define ShellScriptTarget(scripts)	@!\
ShellScriptTargetExt(scripts,.SH)


/*
 * SimpleShellScriptTargetExt:
 *	Generate rules to create a set of scripts from ext files where
 *	ext is usually something like .sh or .SH, or whatever file
 *	extension you like..
 */
#define SimpleShellScriptTargetExt(scripts,ext)	@!\
AllTarget(scripts)			@!\
							@!\
|expand s!scripts!			@!\
!s: !s^^ext					@@\
	/bin/sh !s^^ext			@!\
							@!\
-expand


/*
 * SimpleShellScriptTarget:
 *	Generate rules to create a set of scripts from .SH files.
 */
#define SimpleShellScriptTarget(scripts)	@!\
SimpleShellScriptTargetExt(scripts,.SH)


/*
 * ShellScriptLongTarget:
 *	Generate rules to create a set of scripts from .SH files where
 *	the name of the generated file is different from the basename of
 *	the .SH file (when, for instance, the total length with the .SH
 *	extension would not leave enough space for RCS ,v extension).
 */
#define ShellScriptLongTarget(basename,scriptname) @!\
++LSCRIPTS scriptname @!\
AllTarget(scriptname)		@!\
							@!\
scriptname: basename^^.SH	@@\
	/bin/sh basename^^.SH	@!\
							@!\
InstallScripts()			@!\
?NOMAN:|skip				@!\
InstallManPageLong(basename,$(MANSRC),scriptname)	@!\
-skip


/*
 * ForceTarget:
 *	The force target will force reconstruction of all the other
 *	targets which include .FORCE in their own dependencies.
 */
#define ForceTarget()	@!\
|once _force_			@!\
.FORCE:					@!\
						@!\
-once


/*
 * RemoteTargetDependency:
 *	A local target may rely on a remote dependency (e.g. a library)
 *	made in a separate directory. This rule explicits the dependency
 *	and forces a make of that dependency in the remote directory.
 */
#define RemoteTargetDependency(target,directory,dependency) @!\
RemoteDependency(directory,dependency)	@!\
target: directory/^^^dependency	@!\


/*
 * RemoteDependency:
 *	Specify rules for making a remote dependency.
 */
#define RemoteDependency(directory,dependency) @!\
ForceTarget()							@!\
|once =directory/^^^dependency=			@!\
directory/^^^dependency: .FORCE			@@\
	@echo "Checking "^^^dependency" in "^^^directory"..."	@@\
	cd ^^^directory; $(MAKE) ^^^dependency	@@\
	@echo "Continuing in $(CURRENT)..."	@!\
					@!\
-once

/*
 * SetSubdirs:
 *	Actually forces the definition of SUBDIRS, and lets the user
 *	specify what the sub-directories are.  This will be added to the
 *	customization part.
 */
#define SetSubdirs(subdirs) @!\
>SUBDIRS @!\
+SUBDIRS = subdirs


/*
 * NoManPages:
 *	Actually forces the definition of NOMAN, which tells the jmake
 *	program to not generate rules for installing manual pages.
 */
#define NoManPages() @!\
>NOMAN


/*
 * Expand:
 *	This powerful macro expands the `rule' given a `pattern'. It
 *	relies on a built-in command in jmake. The expansion is
 *	documented in the short notes file that comes with jmake and
 *	gives some insights on the internal syntax.
 */
#define Expand(rule, pattern) @!\
|expand pattern @!\
rule @!\
-expand


/*
 * Lex and yacc stuff.
 */

/*
 * YaccRule:
 *	This is the rule which is used to build a .c file from a .y file.
 */
#define YaccRule() @!\
AddSuffix(.y)					@!\
|once _YaccRule_				@!\
|rule:.y.c:						@!\
|rule: $(YACC) $(JYFLAGS) $<	@!\
|rule: $(MV) y.tab.c $@			@!\
|rule:							@!\
-once

/*
 * SimpleYaccTarget:
 *	Declare a yacc base.y file to be used in the building of the
 *	specified target program. The source file must be given without
 *	its final .y extension. The name of the .c and .o will be
 *	derived from the source file basename provided.
 */
#define SimpleYaccTarget(program,base) @!\
++SOURCES base.y @!\
++OBJECTS base.o @!\
YaccRule()				@!\
program: base.c			@!\
						@!\
local_realclean::		@@\
	$(RM) base.c		@!\


/*
 * ComplexYaccTarget:
 *	Declare a yacc base.y file to be used in the building of the
 *	specified target program. The source file must be given without
 *	its final .y extension. The name of the .c and .o will be
 *	derived from the source file basename provided.
 *	The difference with SimpleYaccTarget is the identifying process
 *	where all the 'yy' are replaced by the specified prefix.
 */
#define ComplexYaccTarget(program,base,prefix) @!\
++SOURCES base.y @!\
++OBJECTS base.o @!\
program: base.c			@!\
						@!\
base.c: base.y					@@\
	$(YACC) $(JYFLAGS) base.y	@@\
	$(SED) -e 's/yy\(.\)/prefix\1/g' < y.tab.c > base.c	@@\
	$(SED) -e 's/yy\(.\)/prefix\1/g' < y.tab.h > base.h	@@\
	$(RM) y.tab.c y.tab.h	@!\
							@!\
local_realclean::		@@\
	$(RM) base.c		@!\


/*
 * SimpleYaccInclude:
 *	Declare that program will need an include file produced by
 *	the output of yacc on base.y, which typically produces a file
 *	named y.tab.h, which will be renamed as base.h.
 *	The only problem is that the dependencies towards base.h have
 *	to be manually given in the Jmakefile.
 */
#define SimpleYaccInclude(base) @!\
base.h: base.c		@@\
	@if test -f y.tab.h; then \	@@\
		echo "	$(MV) y.tab.h $@"; \	@@\
		$(MV) y.tab.h $@; \		@@\
	fi							@!\
								@!\
local_realclean::				@@\
	$(RM) base.h

/*
 * ComplexYaccInclude:
 *	Declare that program will need an include file produced by
 *	the output of yacc on base.y, which typically produces a file
 *	named y.tab.h, which will be renamed as base.h.
 *	The difference with SimpleYaccInclude is the identifying process
 *	of the y.tab.h file where all 'yy' are renamed to prefix.
 *	The only problem is that the dependencies towards base.h have
 *	to be manually given in the Jmakefile.
 */
#define ComplexYaccInclude(base,prefix) @!\
base.h: base.c		@@\
	@if test -f y.tab.h; then \	@@\
		echo "	$(SED) -e 's/yy\(.\)/prefix\1/g' < y.tab.h > base.h"; \	@@\
		$(SED) -e 's/yy\(.\)/prefix\1/g' < y.tab.h > base.h; \	@@\
		echo "	$(RM) y.tab.h"; \	@@\
		$(RM) y.tab.h; \		@@\
	elif test -f base.h; then \ @@\
		echo "	$(CP) base.h base.ht"; \	@@\
		$(CP) base.h base.ht; \	@@\
		echo "	$(SED) -e 's/yy\(.\)/prefix\1/g' < base.ht > base.h"; \	@@\
		$(SED) -e 's/yy\(.\)/prefix\1/g' < base.ht > base.h; \	@@\
		echo "	$(RM) base.ht"; \ @@\
		$(RM) base.ht; \		@@\
	fi							@!\
								@!\
local_realclean::				@@\
	$(RM) base.h


/*
 * NormalYaccTarget:
 *	Declare a yacc base.y file which should produce a base.c and
 *	base.h file as derived from the output of yacc, to be used by
 *	the specified program.
 */
#define NormalYaccTarget(program,base) @!\
SimpleYaccTarget(program,base) @!\
SimpleYaccInclude(base)


/*
 * IdentifiedYaccTarget:
 *	Declare a yacc base.y file which should produce a base.c and
 *	base.h file as derived from the output of yacc, to be used by
 *	the specified program. The specified prefix is used to remplace
 *	all the 'yy' in the generated file, for use when more than a
 *	single parser is needed in one executable.
 */
#define IdentifiedYaccTarget(program,base,prefix) @!\
ComplexYaccTarget(program,base,prefix) @!\
ComplexYaccInclude(base,prefix)


/*
 * SimpleLexTarget:
 *	This declares a lex base.l file which is to be ran through
 *	lex to produce a base.c file.
 */
#define SimpleLexTarget(program,base) @!\
++SOURCES base.l @!\
++OBJECTS base.o @!\
|once _LexRule_					@!\
|rule:.l.c:						@!\
|rule: $(LEX) $(JLFLAGS) $<		@!\
|rule: $(MV) lex.yy.c $@		@!\
|rule:							@!\
-once							@!\
AddSuffix(.l)			@!\
program: base.c			@!\
						@!\
local_realclean::		@@\
	$(RM) base.c		@!\


/*
 * IdentifiedLexTarget:
 *	This declares a lex base.l file which is to be ran through
 *	lex to produce a base.c file. The prefix is used to replace
 *	the 'yy', so that the lexical analyzer may be identified.
 */
#define IdentifiedLexTarget(program,base,prefix) @!\
++SOURCES base.l @!\
++OBJECTS base.o @!\
program: base.c			@!\
						@!\
base.c: base.l					@@\
	$(LEX) $(JLFLAGS) base.l	@@\
	$(SED) -e 's/yy\(.\)/prefix\1/g' < lex.yy.c > base.c	@@\
	$(RM) lex.yy.c				@!\
						@!\
local_realclean::		@@\
	$(RM) base.c		@!\


/*
 * NormalLexDependTarget:
 *	Declare that program will need an include file produced by
 *	the output of lex on base.l, which typically produces a file
 *	named lex.yy.c which will be renamed as base.c. Besides, the
 *	lexical analyzer needs the file parser.h produced by running
 *	parser.y through yacc and renaming y.tab.h as parser.h.
 */
#define NormalLexDependTarget(program,base,parser) @!\
base.o: parser.h	@!\
					@!\
SimpleLexTarget(program,base)


/*
 * IdentifiedLexDependTarget:
 *	Declare that program will need an include file produced by
 *	the output of lex on base.l, which typically produces a file
 *	named lex.yy.c which will be renamed as base.c. Besides, the
 *	lexical analyzer needs the file parser.h produced by running
 *	parser.y through yacc and renaming y.tab.h as parser.h.
 *	The lexical analyzer is identified with the supplied prefix,
 *	which replaces the regular 'yy' prefix in the symbol names.
 */
#define IdentifiedLexDependTarget(program,base,parser,prefix) @!\
base.o: parser.h	@!\
					@!\
IdentifiedLexTarget(program,base,prefix)


/*
 * NormalParserTarget:
 *	Specify that program is using the lex/yacc combination to
 *	produce a parser. The lexic and parser parameters are the
 *	base name of the .l and .y file, respectively.
 */
#define NormalParserTarget(program,lexic,parser) @!\
NormalLexDependTarget(program,lexic,parser) @!\
NormalYaccTarget(program,parser)


/*
 * IdentifiedParserTarget:
 *	Specify that program is using the lex/yacc combination to
 *	produce a parser. The lexic and parser parameters are the
 *	base name of the .l and .y file, respectively. The parser
 *	produced is identified via its prefix, which replaces all
 *	the normally supplied 'yy' prefix, hence making it possible
 *	to have multiple parsers in a single executable.
 */
#define IdentifiedParserTarget(program,lexic,parser,prefix) @!\
IdentifiedLexDependTarget(program,lexic,parser,prefix) @!\
IdentifiedYaccTarget(program,parser,prefix)


