conditional compilation (was: winsize struct)

Steve Summit scs at adam.mit.edu
Thu Feb 14 18:20:25 AEST 1991


In article <1991Feb13.032238.11640 at athena.mit.edu>, I wrote:
> Don't put the
> code for catching SIGTSTP inside #ifdef JOBCONTROL; put it inside
> #ifdef SIGTSTP.  Settable line disciplines?  TIOCSETD.

In article <17803:Feb1319:45:0991 at kramden.acf.nyu.edu>, Dan Bernstein writes:
>I have to disagree. There may be occasional cases where the macros
>provided by the system exactly match the features you want to use...

I was making a suggestion, not stating a rule.  Obviously a
program's #ifdef strategy depends on a number of factors
particular to the environments in question.  I don't think the
simple cases are occasional.

>you'll never lose anything by sticking to #ifdef JOBCONTROL and putting
>
>	#ifdef SIGTSTP
>	#define JOBCONTROL
>	#endif
>
>inside a .h file. This way someone can (1) figure out what you really
>meant while reading the code; (2) change the definitions with as little
>work as possible in case you messed up.

(What, me mess up? :-) )

The biggest problem people tend to have, when porting code with
lots of #ifdefs to a system significantly different from the ones
the the original author was used to, is figuring out all the
#ifdefs in order to get the -D's and #defines right.  Chains of
#ifdefs can make the problem much worse.  I'm not saying that

	#ifdef SIGTSTP
	#define JOBCONTROL
	#endif

is unilaterally bad -- if the code has a bunch of stuff specific
to job control other than simply catching SIGTSTP, then a
JOBCONTROL macro is a good one to introduce.  However, if the
code is nice and simple (and that's what we all strive for,
right? :-) ), containing merely something like

	#include <signal.h>

	...

	main()
	{
	if(signal(SIGINT, SIG_IGN) != SIG_IGN)
		signal(SIGINT, sigcatcher);

	#ifdef SIGTSTP
	if(signal(SIGTSTP, SIG_IGN) != SIG_IGN)
		signal(SIGTSTP, sigcatcher);
	#endif

	...

	sigcatcher(sig)
	int sig;
	{
	switch(sig)
		{
		case SIGINT:

		...

	#ifdef SIGTSTP:
		case SIGTSTP:
			/* fix something up */
			kill(getpid(), SIGSTOP);
			/* revert to funny state */
			break;
	#endif

then using anything other than #ifdef SIGTSTP is superfluous.

Of course, the easiest #ifdefs to handle are the ones that aren't
there at all.  Many programs go to great lengths to select among
several flavors of a system-dependent feature when they would be
better off not having anything to do with that feature in the
first place.

The folks at Berkeley have actually done a fairly good job of
introducing new features transparently -- that is, most programs
don't need to know about them.  In many cases, though, they have
turned around and modified far more application programs than
strictly necessary, teaching people (by example) that every
interactive program has to know about job control, that every
program that walks directories has to know about symbolic links,
etc.  (Don't follow up to tell me that every program that walks
directories *does* have to know about symlinks.  I know why they
have to, or at least why they think they have to.  That's one of
the problems with symlinks.)

Help break the trend: don't make your programs dependent on
system-specific features at all, if you can get away with it.

                                            Steve Summit
                                            scs at adam.mit.edu



More information about the Comp.unix.programmer mailing list