-<html>
-<center>
-<p><h1>Condor's Imake Build System Coding Guidlines and Conventions</h1></p>
-<p>
+{section: Condor's Imake Build System Coding Guidlines and Conventions}
 Revised: Tue Jun 22 14:24:56 CDT 2004
-</p>
-</center>
 
-<p>
-<h2>Background</h2>
+{section: Background}
 I, Pete Keller, am writing this in May 2004.  The Imake system has been
 a painful thorn in the side of Condor since anyone could remember. This
 document describes the work which I have done and a new coding style for
@@ -20,9 +14,9 @@
 whitespace sensitive language, i.e, Makefiles. Currently, things *should*
 work for a good many number of ports, but the headaches of "keeping everything
 just right" might get to much, and the evolution will continue.
-</p>
 
-<p>
+
+
 The biggest problem with using imake seemed to be a fundamental lack of
 understanding for how it was supposed to work in the first place. Poorly
 implemented rules which "worked" on old cpps were simply copied around
@@ -31,353 +25,345 @@
 that they had avoided for so long. However, many OSes vendor cpps tread
 into undefined territory, so I worked hard to find a common ground,
 the stuff that all cpps are supposed to implement.
-</p>
 
-<p>
+
+
 The main culprits for the failure of our Imake system to be resilient and
 robust comes down to two systemic problems. Serious misuse of whitespace
 and the '##' concatenation operator. These two problems alone caused
 the most headaches while trying to port Condor to a new compiler which
 happens often and will, if it had been left alone, cause problems for
 the rest of eternity.
-</p>
 
-<h3>Guidelines and Rules for the Use of Imake with Condor</h3>
-<ul>
 
-<li>
-	<h4>The CPP</h4>
+{section: Guidelines and Rules for the Use of Imake with Condor}
+
+
+
+{subsection: The CPP}
+
+
+The build system has been changed to use the same cpp that comes
+with the distribution of the target OS. This would be the same
+cpp that the X Consortium source code would need to compile. On
+most machines it is /lib/cpp, or even /usr/lib/cpp, etc. It
+doesn't matter the revision of the cpp since the rest of the
+guildlines explain how to write generalized preprocessor macros.
+There is a new script, ansi_cpp, in the imake/ directory which figures
+out which cpp to use for each architecture. On some architectures,
+we are forced to use the vendor compiler, and so that must be installed.
+On other architectures, there are a lot of cpp programs to choose from
+and we must choose the right one. At all times, I've tried to stay
+cannon to what the X Consortium code does to compile X.
+
+
+
+
+{subsection: TAB characters}
+TAB characters passed through cpp and then imake are preserved in all
+cases except an errant gcc 3.1 revision. This errant version was fixed
+by hacking our imake code to invoke the cpp differently.
+
+
+
+
+{subsection: #endif Comments}
+Comments on the same line as the #endif, but after it, must be C style
+comments, not bare text.
+
+
+
+
+{subsection: #define [thing] [stuff]}
+[thing] MUST be a true C Identifier:
+
+_CORRECT_:
+
+=#define IS_I386_LINUX_RH9 YES=
+
+_INCORRECT_:
+
+=#define IS_I386_LINUX-RH9 YES=
+
+
+
+
+
+{subsection: Generated Makefile Comments}
+If you'd like comments in the generated Makefile, please use XCOMM in
+the Imakefile like this:
+_XCOMM This is a comment in the generated Makefile_
+
+
+XCOMM is an imake program built in.
+
+
+
+
+
+{subsection: Macro Names}
+Macro names must not unintentionally appear in any XCOMM comments as
+they can be possibly expanded by various revisions of cpps.
+
+
+
+
+{subsection: Macro Definitions}
+There can be no whitespace in the parameter list of a macro
+definition. Also, no whitespace around the interior of the
+parenthesis, which is a common idiom in Condor C/C++ code.
+Here is an example:
+
+
+
+_CORRECT_: =#define Concat(x,y)x##y=
+
+_INCORRECT_: =#define Concat( x, y )x##y=
+
+
+In addition, there should be no spaces after the closing parenthesis
+and the start of the nonwhitespace text--especially in a one
+line macro rule:
+
+_CORRECT_: =#define copy(x,y)cp x y=
+
+_INCORRECT_: =#define copy(x,y) cp x y=
+
+
+
+If you have a multiline rule where you use @@\ to end the line(but
+continue the rule to the next line),
+any whitespace from the @@\ to the previous nonwhitespace character
+on that line is undefined for its preservation. Do not rely
+on the existance of that particular sort of whitespace. In practice,
+however, no rules rely on this and it would be out of the ordinary
+if a rule does.
+
+
+
+
+{subsection: Rule Invocation in an Imakefile}
+
+There must be NO WHITESPACE around the open/closing parenthesis and
+commas in rule invocation since this whitespace is undefined in its
+preservation between cpps. However, whitespace could exist in the
+invocation rule if it is separating items within a parameter:
+
+
+
+_CORRECT_:
+
+=program_target(thingy,$(OBJS) foo.o bar.o,$(LIBS))=
+Notice the whitespace in the second parameter, whitespace of this
+specific kind is valid.
+
+
+_INCORRECT_:
+
+=program_target( thingy, $(OBJS) foo.o bar.o, $(LIBS) )=
+
+
+In addition, you may NOT use the line continuation character:
+='\'= anywhere in the line when invoking a rule:
+
+
+_INCORRECT_:
 
-	<p>
-	The build system has been changed to use the same cpp that comes
-	with the distribution of the target OS. This would be the same
-	cpp that the X Consortium source code would need to compile. On
-	most machines it is /lib/cpp, or even /usr/lib/cpp, etc. It
-	doesn't matter the revision of the cpp since the rest of the
-	guildlines explain how to write generalized preprocessor macros.
-	There is a new script, ansi_cpp, in the imake/ directory which figures
-	out which cpp to use for each architecture. On some architectures,
-	we are forced to use the vendor compiler, and so that must be installed.
-	On other architectures, there are a lot of cpp programs to choose from
-	and we must choose the right one. At all times, I've tried to stay
-	cannon to what the X Consortium code does to compile X.
-	</p>
-</li>
-
-<li>
-	<h4>TAB characters</h4>
-	<p> TAB characters passed through cpp and then imake are preserved in all
-		cases except an errant gcc 3.1 revision. This errant version was fixed
-		by hacking our imake code to invoke the cpp differently.
-	</p>
-</li>
-
-<li>
-	<h4>#endif Comments</h4>
-	<p> Comments on the same line as the #endif, but after it, must be C style
-		comments, not bare text.
-	</p>
-</li>
-
-<li>
-	<h4>#define [thing] [stuff]</h4>
-	<p> [thing] MUST be a true C Identifier: </p>
-
-	<p><em>CORRECT</em>:</p>
-	<p><tt>#define IS_I386_LINUX_RH9 YES</tt></p>
-	<p><em>INCORRECT</em>:</p>
-	<p><tt>#define IS_I386_LINUX-RH9 YES</tt></p>
-	</p>
-</li>
-
-
-<li>
-	<h4>Generated Makefile Comments</h4>
-	<p> If you'd like comments in the generated Makefile, please use XCOMM in
-	the Imakefile like this:
-	<p><em>XCOMM This is a comment in the generated Makefile</em></p>
-	</p>
-	<p>
-		XCOMM is an imake program built in.
-	</p>
-
-</li>
-
-<li>
-	<h4>Macro Names</h4>
-	<p>Macro names must not unintentionally appear in any XCOMM comments as
-		they can be possibly expanded by various revisions of cpps.
-	</p>
-</li>
-
-<li>
-	<h4>Macro Definitions</h4>
-	<p>There can be no whitespace in the parameter list of a macro
-		definition. Also, no whitespace around the interior of the
-		parenthesis, which is a common idiom in Condor C/C++ code.
-		Here is an example:
-	</p>
-
-	<p>
-		<p><em>CORRECT</em>:</p>
-		<p><tt>#define Concat(x,y)x##y</tt></p>
-		<p><em>INCORRECT</em>:</p>
-		<p><tt>#define Concat( x, y )x##y</tt></p>
-	</p>
-
-	<p> In addition, there should be no spaces after the closing parenthesis
-		and the start of the nonwhitespace text--especially in a one
-		line macro rule:
-
-		<p><em>CORRECT</em>:</p>
-		<p><tt>#define copy(x,y)cp x y</tt></p>
-		<p><em>INCORRECT</em>:</p>
-		<p><tt>#define copy(x,y) cp x y</tt></p>
-
-	</p>
-
-	<p> If you have a multiline rule where you use @@\ to end the line(but
-		continue the rule to the next line),
-		any whitespace from the @@\ to the previous nonwhitespace character
-		on that line is undefined for its preservation. Do not rely
-		on the existance of that particular sort of whitespace. In practice,
-		however, no rules rely on this and it would be out of the ordinary
-		if a rule does.
-	</p>
-</li>
-
-<li>
-	<h4>Rule Invocation in an Imakefile</h4>
-	<p>
-		There must be NO WHITESPACE around the open/closing parenthesis and
-		commas in rule invocation since this whitespace is undefined in its
-		preservation between cpps. However, whitespace could exist in the
-		invocation rule if it is separating items within a parameter:
-	</p>
-
-
-	<p><em>CORRECT</em>:</p>
-	<p>
-		<p><tt>program_target(thingy,$(OBJS) foo.o bar.o,$(LIBS))</tt></p>
-		Notice the whitespace in the second parameter, whitespace of this
-		specific kind is valid.
-	</p>
-
-	<p><em>INCORRECT</em>:</p>
-
-	<p><tt>program_target( thingy, $(OBJS) foo.o bar.o, $(LIBS) )</tt></p>
-
-	<p>
-		In addition, you may NOT use the line continuation character:
-		<tt>'\'</tt> anywhere in the line when invoking a rule:
-	</p>
-
-	<p><em>INCORRECT</em>:</p>
-
-	<p>
-	<pre>program_target(thingy,$(OBJS) foo.o bar.o,\
-		$(LIBS))
-	</pre>
-	</p>
-
-	<p>
-		Different pre-processors preserve or don't preserve the whitespace
-		up to the <tt>$(LIBS)</tt> lexeme and that can cause trouble
-		depending how your rules are layed out. Since it COULD be possible to
-		use the <tt>'\'</tt> character in some places and not others validly,
-		I'm striking out the use of it altogether so we don't have to
-		worry about the details of when you can or can't use it.
-	</p>
-
-</li>
-
-<li>
-	<h4>Use of the concatenation operator: ##</h4>
-	<p>
-		This operator is the main reason for the problems we've experienced
-		using the Imake system.  People had been using ##
-		incorrectly in the sense that they were compressing
-		out whitespace preserved by cpp during incorrect Rule
-		Invocations but, in doing so, produced invalid C identifier
-		tokens with respect to the usage of ## according to the
-		specifications in the ANSI C manual.
-	</p>
-
-	<p>
-		Since using ## to produce a non-C token was "undefined"
-		according to the specification, many, but not all, cpp
-		programmers honored the pasting together of two lexemes
-		for the reason of whitespace removal. But ultimately,
-		it was bad behavior and since the specification has
-		been tightened to reject arbitrary lexeme pastings by
-		many modern cpp versions.
-	</p>
-
-	<p>
-		If you do need to use ##, then use one of the <tt>Concat*()</tt>
-		rules which exist for this purpose that are found
-		in Global.h. These rules embody special behavior for
-		certain cpp programs where ## can be replaced with /**/
-		because ## wasn't supported correctly or even available
-		at all in the cpp.
-	</p>
-
-	<p>
-		Since we now FORCE, by the creation of this document, that ANY and
-		ALL rule invocations must not have any extraneous whitespace, we can
-		consign the use of ## back to where it is supposed to be, in the
-		<tt>Concat*()</tt> rules.
-	</p>
-
-	<p> This is the <em>ONLY VALID USE </em>
-		of the ## operator: </p>
-	<p> c_identifier1##c_identifer2 -> c_identifier1c_identifier2 <p>
-
-	<p>These are examples of <em>INCORRECT</em> uses of the
-		## operator:</p>
-
-	<p>
-	<tt>path##/##to##/##some##/##dir##</tt><br>
-	<tt>directory##.static</tt><br>
-	<tt>##make_target##: stuff things other</tt><br>
-	<tt>perl condor_scripts/make_both_tarball -cmd "$(TAR_CMD)" strip##, name##, files##, contribfiles</tt><br>
-	<tt>DEPEND_C_SRC := $(##obj_list##:.o=.c)</tt><br>
-	</p>
-
-	<p> Now, here is the important thing: </p>
-
-	<p>
-		<span class="good"><em>
-		YOU WILL NEVER NEED TO USE THE ## OPERATOR EVER! USE ONE OF THE
-		<tt>Concat*()</tt> RULES INSTEAD AND ONLY WHEN PRODUCING A TRUE
-		C IDENTIFIER.
-		</em></span>
-	</p>
-
-</li>
-
-<li>
-	<h4> <tt>#</tt> and Preprocessor Directives </h4>
-	<p>When using preprocessor directives like <tt>#define</tt>, etc,
-		please be sure to place the <tt>#</tt> character in the
-		FIRST column of the text window. However, there can be
-		whitespace between the hash mark and the preprocessor
-		directive like this:
-		<pre>
+
+{code}program_target(thingy,$(OBJS) foo.o bar.o,\
+$(LIBS))
+{endcode}
+
+
+
+Different pre-processors preserve or don't preserve the whitespace
+up to the =$(LIBS)= lexeme and that can cause trouble
+depending how your rules are layed out. Since it COULD be possible to
+use the ='\'= character in some places and not others validly,
+I'm striking out the use of it altogether so we don't have to
+worry about the details of when you can or can't use it.
+
+
+
+
+
+{subsection: Use of the concatenation operator: ##}
+
+This operator is the main reason for the problems we've experienced
+using the Imake system.  People had been using ##
+incorrectly in the sense that they were compressing
+out whitespace preserved by cpp during incorrect Rule
+Invocations but, in doing so, produced invalid C identifier
+tokens with respect to the usage of ## according to the
+specifications in the ANSI C manual.
+
+
+
+Since using ## to produce a non-C token was "undefined"
+according to the specification, many, but not all, cpp
+programmers honored the pasting together of two lexemes
+for the reason of whitespace removal. But ultimately,
+it was bad behavior and since the specification has
+been tightened to reject arbitrary lexeme pastings by
+many modern cpp versions.
+
+
+
+If you do need to use ##, then use one of the =Concat*()=
+rules which exist for this purpose that are found
+in Global.h. These rules embody special behavior for
+certain cpp programs where ## can be replaced with /**/
+because ## wasn't supported correctly or even available
+at all in the cpp.
+
+
+
+Since we now FORCE, by the creation of this document, that ANY and
+ALL rule invocations must not have any extraneous whitespace, we can
+consign the use of ## back to where it is supposed to be, in the
+=Concat*()= rules.
+
+
+This is the _ONLY VALID USE _
+of the ## operator:
+c_identifier1##c_identifer2 -> c_identifier1c_identifier2
+
+These are examples of _INCORRECT_ uses of the
+## operator:
+
+{code}
+=path##/##to##/##some##/##dir##=<br>
+=directory##.static=<br>
+=##make_target##: stuff things other=<br>
+=perl condor_scripts/make_both_tarball -cmd "$(TAR_CMD)" strip##, name##, files##, contribfiles=<br>
+=DEPEND_C_SRC := $(##obj_list##:.o=.c)=<br>
+{endcode}
+
+Now, here is the important thing:
+
+
+*YOU WILL NEVER NEED TO USE THE ## OPERATOR EVER! USE ONE OF THE
+=Concat*()= RULES INSTEAD AND ONLY WHEN PRODUCING A TRUE
+C IDENTIFIER.*
+
+
+
+
+
+{subsection:  =#= and Preprocessor Directives }
+When using preprocessor directives like =#define=, etc,
+please be sure to place the =#= character in the
+FIRST column of the text window. However, there can be
+whitespace between the hash mark and the preprocessor
+directive like this:
+{code}
 
 #    define FOO BAR
-		</pre>
-	</p>
-</li>
-
-</ul>
-
-<p> <h3>Conventions in the Imake Build Files</h3> </p>
-
-<ul>
-
-<li>
-	<h4>Macro Namespace</h4>
-
-	<p>The name of a macro can only be used during the invocation of a macro.
-	</p>
-	<p>
-		For example, suppose we have a macro called
-		<tt>BUILD(x,y)</tt>. Now in an Imakefile rule, we have a
-		cleanup rule for a target which looks like this, <tt>rm
-		-rf BUILD</tt>--which is completely seperate from the
-		invocation of the macro rule <tt>BUILD(x,y)</tt>. In
-		this case the cleanup rule is an illegal use of the
-		macro <tt>BUILD(x,y)</tt>.
-	</p>
-	<p> In short, do not mix the namespaces of the macro names and the
-		entities the generated Makefile will manage.
-	</p>
-
-</li>
-
-<li>
-	<h4>Code Reuse</h4>
-	<p>Suppose in a rule you'd like to have _static appended to
-		a directory name in multiple places or something
-		similar. Instead of using Concat(name,_static) everywhere,
-		write a simple rule like this (toward the beginning of
-		the Imake.rules file):
-	</p>
-
-	<p><tt>#define sufstatic(x)Concat(x,_static)</tt></p>
-	<p> And now whenever you want foo_static, you write sufstatic(foo) instead.
-		This will greatly help in producing maintainable and defensive code.
-	</p>
-
-</li>
-
-<li>
-	<h4>Writing New Imake Rules</h4>
-	<p> New rules should be written in this sort of style: </p>
-	<pre>
-	#ifndef release_target
-	#define release_target(file,dir,mode)           @@\
-	XCOMM Begin translation of func(release_target) @@\
-	$(RELEASE_DIR)/dir/file: file                   @@\
-		/bin/rm -f $(RELEASE_DIR)/dir/file          @@\
-		cp file $(RELEASE_DIR)/dir                  @@\
-		chmod mode $(RELEASE_DIR)/dir/file          @@\
-		release:: $(RELEASE_DIR)/dir/file           @@\
-	XCOMM End translation of func(release_target)
-	#endif /* release_target */
-	</pre>
-
-	<p>
-
-	Notice the XCOMM comments dictating that we are beginning
-	and ending the translation of this particular function. The
-	macro <tt>func()</tt> is defined in Imake.rules which
-	expands(even in the comment) the given function name into a nice piece
-	of text in the Makefile which describes the line of translation of the
-	associated function in the original Imakefile. While these are not
-	required for the rule to function, I <span class="good">STRONGLY
-	ENCOURAGE</span> you to follow it. Obviously, for very simple rules
-	like the <tt>sufstatic()</tt> rule above, you don't need it, but
-	for anything more complicated you should strive to put it in.
-	</p>
-</li>
-
-<li>
-	<h4>Converting older style Imake rules to New Imake Rules</h4>
-
-	<p>If you see any function (simple or complex)
-		that does not follow the conventions outlined in this document then
-		update the function to follow the guidlines. This is more of
-		a concern while merging as these changes propogate through the various
-		branches. But if you are editing a source file which
-		looks like it is adhering to these conventions, then assume it is
-		adhering to these conventions and change it accordingly.
-	</p>
-</li>
-
-<li>
-	<h4>The Imake processor is the
-		<em>C Preprocessor</em>:</h4>
-	<p>The usual caveats to this applies, e.g.:</p>
-	<p>If you need to do something like this:</p>
-
-	<p><tt>#define cat(x,y)x##y</tt></p>
-	<p>and you want to use it like this: <tt>cat(cat(1,2),3)</tt> it will
-		do the wrong thing and produce <tt>cat(1,2)3</tt>. If you want to do
-		it right, then you'd need an additional rule like this:</p>
-	<p><tt>#define xcat(x,y)cat(x,y)</tt></p>
-	<p>which would then produce the correct concatenation sequence.
-		Remember that section A.12 in the K&R C book applies.</p>
-
-
-	<p>In the case of the Condor build system,
-		<em>this specific example is already implemented</em>
-		in the <tt>Concat*()</tt> rules written in
-		<tt>Global.h</tt>.</p>
+{endcode}
+
+
+
+
+
+{section: Conventions in the Imake Build Files}
+
+
+
+
+{subsection: Macro Namespace}
+
+The name of a macro can only be used during the invocation of a macro.
+
+
+For example, suppose we have a macro called
+=BUILD(x,y)=. Now in an Imakefile rule, we have a
+cleanup rule for a target which looks like this, =rm
+-rf BUILD=--which is completely seperate from the
+invocation of the macro rule =BUILD(x,y)=. In
+this case the cleanup rule is an illegal use of the
+macro =BUILD(x,y)=.
+
+In short, do not mix the namespaces of the macro names and the
+entities the generated Makefile will manage.
+
+
+
+
+
+{subsection: Code Reuse}
+Suppose in a rule you'd like to have _static appended to
+a directory name in multiple places or something
+similar. Instead of using Concat(name,_static) everywhere,
+write a simple rule like this (toward the beginning of
+the Imake.rules file):
+
+
+=#define sufstatic(x)Concat(x,_static)=
+And now whenever you want foo_static, you write sufstatic(foo) instead.
+This will greatly help in producing maintainable and defensive code.
+
+
+
+
+
+{subsection: Writing New Imake Rules}
+New rules should be written in this sort of style:
+{code}
+#ifndef release_target
+#define release_target(file,dir,mode)           @@\
+XCOMM Begin translation of func(release_target) @@\
+$(RELEASE_DIR)/dir/file: file                   @@\
+/bin/rm -f $(RELEASE_DIR)/dir/file          @@\
+cp file $(RELEASE_DIR)/dir                  @@\
+chmod mode $(RELEASE_DIR)/dir/file          @@\
+release:: $(RELEASE_DIR)/dir/file           @@\
+XCOMM End translation of func(release_target)
+#endif /* release_target */
+{endcode}
+
+
+
+Notice the XCOMM comments dictating that we are beginning
+and ending the translation of this particular function. The
+macro =func()= is defined in Imake.rules which
+expands(even in the comment) the given function name into a nice piece
+of text in the Makefile which describes the line of translation of the
+associated function in the original Imakefile. While these are not
+required for the rule to function, I *STRONGLY
+ENCOURAGE* you to follow it. Obviously, for very simple rules
+like the =sufstatic()= rule above, you don't need it, but
+for anything more complicated you should strive to put it in.
+
+
+
+
+{subsection: Converting older style Imake rules to New Imake Rules}
+
+If you see any function (simple or complex)
+that does not follow the conventions outlined in this document then
+update the function to follow the guidlines. This is more of
+a concern while merging as these changes propogate through the various
+branches. But if you are editing a source file which
+looks like it is adhering to these conventions, then assume it is
+adhering to these conventions and change it accordingly.
+
+
+
+
+{subsection: The Imake processor is the C Preprocessor:}
+The usual caveats to this applies, e.g.:
+If you need to do something like this:
 
-</li>
+=#define cat(x,y)x##y=
+and you want to use it like this: =cat(cat(1,2),3)= it will
+do the wrong thing and produce =cat(1,2)3=. If you want to do
+it right, then you'd need an additional rule like this:
+=#define xcat(x,y)cat(x,y)=
+which would then produce the correct concatenation sequence.
+Remember that section A.12 in the K&R C book applies.
 
-</ul>
 
-</html>
+In the case of the Condor build system,
+_this specific example is already implemented_
+in the =Concat*()= rules written in
+=Global.h=.