[comp.lang.c] How to force cpp to abort?

mikeg@c3.c3.lanl.gov (Michael P. Gerlek) (08/12/90)

I'm writing some machine dependent code...

#if defined(__convex__)
	(do Convex stuff)
#else
#if defined(cray)
	(do Cray stuff)
#else
#if defined(sun)
	(do Sun stuff)
#else
	(oops)	/* force abort */
#endif
#endif
#endif


Question: if the code is compiled on, say, a Vax, how do I force the
compiler (or perhaps cpp) to abort in the "oops" block above?  Sure, I
could throw in some syntactically bad code and force a syntax error,
but that's not really very clean.  Sure, too, I could conditonally
compile in an fprintf(stderr,"Machine not supported"), but the code
would have to be run - I want to cleanly abort at compile-time.

Suggestions?


[  M.P.Gerlek (mikeg@lanl.gov)                 -
[  Los Alamos Nat'l Lab / Merrimack College    -
[  Disclaimer: Yes, Mom, I'll play nice.       -
[  "My other machine's a multi-threaded YMP."  -

karl@haddock.ima.isc.com (Karl Heuer) (08/13/90)

In article <MIKEG.90Aug11180036@c3.c3.lanl.gov> mikeg@c3.c3.lanl.gov (Michael P. Gerlek) writes:
>[If none of the preprocessor conditions hold, I want to abort.  How?]

Use `#error put_some_text_here'.  This is the ANSI C solution.

I presume you also want this to work on pre-ANSI compilers (since you used
`#else\n#if' instead of the cleaner `#elif' construct).  If you add a leading
space, i.e. ` #error', it should be invisible to pre-ANSI compilers that would
complain about unknown cpp-control lines.  (ANSI allows horizontal whitespace
before `#' as well as after.)  Then an attempt to compile in a pre-ANSI
environment where none of the conditionals holds should get an `illegal
character' warning when the `#' is encountered in the next compiler pass.

If you insist on aborting during the preprocessor pass, you could use
`#include "/-/put_some_text_here/-/", which is what I used to use before
`#error' was invented.

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

mikeg@c3.c3.lanl.gov (Michael P. Gerlek) (08/13/90)

In article <17377@haddock.ima.isc.com>,
      karl@haddock.ima.isc.com (Karl Heuer) writes:
> In article <MIKEG.90Aug11180036@c3.c3.lanl.gov> I (Michael P. Gerlek) wrote:
> > [If none of the preprocessor conditions hold, I want to abort.  How?]
>
>  Use `#error put_some_text_here'.  This is the ANSI C solution.
>
>  I presume you also want this to work on pre-ANSI compilers (since you used
>  `#else\n#if' instead of the cleaner `#elif' construct).

Yup, bingo.

>  If you add a leading
>  space, i.e. ` #error', it should be invisible to pre-ANSI compilers that would
>  complain about unknown cpp-control lines.  (ANSI allows horizontal whitespace
>  before `#' as well as after.)  Then an attempt to compile in a pre-ANSI
>  environment where none of the conditionals holds should get an `illegal
>  character' warning when the `#' is encountered in the next compiler pass.
>
>   If you insist on aborting during the preprocessor pass, you could use
>  `#include "/-/put_some_text_here/-/", which is what I used to use before
>  `#error' was invented.

Most of the email responses I got said the same thing, and it's
almost what I want (I missed the #error directive when I looked thru
K&R) --  But it's still ANSI-only...


So, academic question: from what I understand, #error isn't guaranteed
to stop compilation.  Can someone tell me why there isn't something
like an "#abort error-message-here" directive that *would* terminate?
Seems like this'd be really useful...


[  M.P.Gerlek (mikeg@lanl.gov)                 -
[  Los Alamos Nat'l Lab / Merrimack College    -
[  Disclaimer: Yes, Mom, I'll play nice.       -
[  "My other machine *used* to be an XMP."     -

meissner@osf.org (Michael Meissner) (08/14/90)

In article <MIKEG.90Aug13092741@c3.c3.lanl.gov> mikeg@c3.c3.lanl.gov
(Michael P. Gerlek) writes:

| So, academic question: from what I understand, #error isn't guaranteed
| to stop compilation.  Can someone tell me why there isn't something
| like an "#abort error-message-here" directive that *would* terminate?
| Seems like this'd be really useful...

I always use something like:

	int double error;	/* reason */

It's grungy, but it should generate an error on anything that calls
itself a C compiler.
--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142

Do apple growers tell their kids money doesn't grow on bushes?

gs26@prism.gatech.EDU (Glenn R. Stone) (08/14/90)

In <MIKEG.90Aug13092741@c3.c3.lanl.gov> mikeg@c3.c3.lanl.gov (Michael P. Gerlek) writes:

>So, academic question: from what I understand, #error isn't guaranteed
>to stop compilation.  Can someone tell me why there isn't something
>like an "#abort error-message-here" directive that *would* terminate?
>Seems like this'd be really useful...

ummmm, maybe 'cause unix jocks are expected to keep up with silly things
like defining things in header files?  :) 

Actually, with either a sharp programmer or something like Larry Wall's
"configure" script, it's not too hard to have these things taken care of,
ergo there *wasn't a need* for such things.... but, alas, with the size
and complexity and fuzziness of today's programs....

see also the .sig quote.

Glenn R. Stone
gs26@prism.gatech.edu
Unix.  Op Sys with an attitude.
Your fault (core dumped).
%

henry@zoo.toronto.edu (Henry Spencer) (08/15/90)

In article <MIKEG.90Aug13092741@c3.c3.lanl.gov> mikeg@c3.c3.lanl.gov (Michael P. Gerlek) writes:
>... Can someone tell me why there isn't something
>like an "#abort error-message-here" directive that *would* terminate?

Response to error conditions was generally considered to be a "quality
of implementation" issue outside the province of the standard.  One
might ask why you *want* to do this...
-- 
It is not possible to both understand  | Henry Spencer at U of Toronto Zoology
and appreciate Intel CPUs. -D.Wolfskill|  henry@zoo.toronto.edu   utzoo!henry

karl@haddock.ima.isc.com (Karl Heuer) (08/16/90)

In article <MIKEG.90Aug13092741@c3.c3.lanl.gov> mikeg@c3.c3.lanl.gov (Michael P. Gerlek) writes:
>it's almost what I want (I missed the #error directive when I looked thru
>K&R) -- But it's still ANSI-only...

Huh?  Read again what I wrote.  If you spell it ` #error', with a leading
space, then both Classic and ANSI compilers should die at that point (though
for different reasons).  And the `#include "/-/error_message_here/-/"' hack
also works on both dialects, though I prefer the former method.

>So, academic question: from what I understand, #error isn't guaranteed
>to stop compilation.  Can someone tell me why there isn't something
>like an "#abort error-message-here" directive that *would* terminate?
>Seems like this'd be really useful...

That's what `#error' is for.  Note that there's *no* construct which is
guaranteed to stop compilation; a `friendly' implementation might decide to
delete everything that causes an error (after issuing at least one diagnostic,
of course), and add `main(){}' at the end if necessary, so that a compilation
never fails.  But the vendors know we wouldn't like that, so they don't do it.
The same applies to `#error'.

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

tony@oha.UUCP (Tony Olekshy) (08/17/90)

In message <1990Aug14.174615.22829@zoo.toronto.edu>, henry@zoo.toronto.edu
(Henry Spencer) writes:
>
> In article <MIKEG.90Aug13092741@c3.c3.lanl.gov> mikeg@c3.c3.lanl.gov
> (Michael P. Gerlek) writes:
> >
> >... Can someone tell me why there isn't something
> >like an "#abort error-message-here" directive that *would* terminate?
> 
> Response to error conditions was generally considered to be a "quality
> of implementation" issue outside the province of the standard.  One
> might ask why you *want* to do this...

From the Indian Hill C Style and Coding Standards as amended for U of T
Zoology UNIX:

     32. If you #ifdef dependencies, make sure that if no machine is
         specified, the result is a syntax error, not a default machine!

This is excellent advice.  However, it would be nice if the user could be
given some information on what happened, instead of just a syntax error.
We use #include "*** Useful Message Here ***", which works, but says things
like ``can't find *** Useful Message Here ***'', which is slightly misleading
if you're not expecting it.

--
Yours etc., Tony Olekshy.               Internet: tony%oha@CS.UAlberta.CA
					  BITNET: tony%oha.uucp@UALTAMTS.BITNET
					    uucp: alberta!oha!tony

nathan@elberton.inmos.co.uk (Nathan Sidwell) (08/17/90)

In article <MIKEG.90Aug11180036@c3.c3.lanl.gov> mikeg@c3.c3.lanl.gov (Michael P. Gerlek) writes:
>
>I'm writing some machine dependent code...
>
>#if defined(__convex__)
>	(do Convex stuff)
>#else
>#if defined(cray)
>	(do Cray stuff)
>#else
>#if defined(sun)
>	(do Sun stuff)
>#else
>	(oops)	/* force abort */
>#endif
>#endif
>#endif
>
>[how to tidily abort compile at oops]

You can use the #error preprocessor directive, viz

#error Machine type not supported

I would have emailed this, but it struck me that it also helps in another
thread about array initializing. When I define an initialized array in a
header file, and initialize it in the code file, the two must be kept in step.
Ie

"module.h"

#define DETECTORS 7
extern char *detectors[DETECTORS] ;

"module.c"

#if DETECTORS != 7
#error Module assumes DETECTORS == 7
#endif
extern char *detectors[DETECTORS] =
{
  "Photomultiplier",
  "Silicon",
  "Raman",
  "Detector 3",
  "Detector 4",
  "Detector 5",
  "Detector 6",
};

Much better than a comment telling me to keep them in step!


Nathan Sidwell, INMOS Ltd, UK         JANET:    nathan@uk.co.inmos
Generic disclaimer applies            UUCP:     ukc!inmos!nathan
My indicision is final (I think)      INTERNET: nathan@inmos.com

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (08/18/90)

In article <9679@ganymede.inmos.co.uk>, nathan@elberton.inmos.co.uk (Nathan Sidwell) writes:
> but it struck me that [using #error] also helps in another
> thread about array initializing.  When I define an initialized array in a
> header file, and initialize it in the code file, the two must be kept in step.

> /* module.h */
> 
> #define DETECTORS 7
> extern char *detectors[DETECTORS];

> /* module.c */
> 
> #if DETECTORS != 7
> #error Module assumes DETECTORS == 7
> #endif
> extern char *detectors[DETECTORS] =
> {
	/* 7 strings deleted */
> };

For an array with 2 or more dimensions, you haven't the choice,
but for a one-dimensional array a better method is just to write
	extern char *detectors[];
in the header file.  With the code as presented, if DETECTORS is
too small, the C compiler is going to report an error anyway.

I feel rather uncomfortable at having the master definition for
the contents of the table in one place and the master definition
for the size of the table in another.

The little AWK program I posted a while back for turning tables into
C has a smaller brother, which generates header files from the same
tables.  Recall the example:

	#File: mktable.demo

	EntryCt;	int whence;	int whither;	char *name

	Butcher;	1;		2;		"Butcher"
	Baker;		1;		3;		"Baker"
	Bellman;	2;		3;		"Bellman"
	Boojum;		0;		0;		NULL
	#End: mktable.demo

Running the command

	awk -F";" -f mkheader.awk mktable.demo

produces

	/* From mktable.demo */
	#define Butcher 0
	#define Baker 1
	#define Bellman 2
	#define Boojum 3
	#define EntryCt 4
	extern 	int whence[4];
	extern 	int whither[4];
	extern 	char *name[4];
	/* End mktable.demo */

automagically.  (If any of the table names has "static" in it, that
table name is not written out by mkheader.awk.)  Having "make" generate
the C initialisations and the header file automatically from a common
source is one way of making sure that they *can't* get out of step.

-- 
The taxonomy of Pleistocene equids is in a state of confusion.