[net.lang.c] C-Debug package ...

pkl@daisy.UUCP (Peter K. Lee) (01/26/85)

> Whenever I define a macro to be an expression, I put parens around it
> to avoid surprises.  Similarly, whenever I define a macro to be a
> (compound) statement, I put braces around it.  There are two places
> where braces cause problems: IF statements with ELSE clauses and
> DO statements:
>					hugh@hcrvx1

I learned this from Dave Ungar while working on the 
Berkeley Smalltalk project.

	# define macro(args)\
		if (1) {\
			/* macro body */\
			/* goes here  */;\
		}\
		else

Notice that the trailing "else" will take care of the ";".  
A macro defined this way can go wherever a legal C statement
can go because this IS a legal C statement (when you call it as
macro(args);).

If you think that "if (1)" is silly and may generate inefficient 
code, you better go find a better compiler.

-- 
			-- Peter Lee
			...{ucbvax!amd,decwrl,ihnp4}!nsc!daisy!pkl

[No news is good news]

hugh@hcrvx1.UUCP (Hugh Redelmeier) (01/28/85)

In article <33@daisy.UUCP> pkl@daisy.UUCP (Peter K. Lee) writes:
>>  whenever I define a macro to be a
>> (compound) statement, I put braces around it.  There are two places
>> where braces cause problems: IF statements with ELSE clauses and
>> DO statements:
>>					hugh@hcrvx1
>	# define macro(args)\
>		if (1) {\
>			/* macro body */\
>		}\
>		else
>If you think that "if (1)" is silly and may generate inefficient 
>code, you better go find a better compiler.
I think this is silly.  I guess I better go find a better compiler,
but for what language?  Seriously, several people have suggested
this, but I remain repelled.  I think I will stick with my braces
and accept the occasional syntax error (they are easy to fix, and
braces never lead to undetected errors).

ksbszabo@wateng.UUCP (Kevin Szabo) (01/29/85)

In article <33@daisy.UUCP> pkl@daisy.UUCP (Peter K. Lee) writes:
>	# define macro(args)\
>		if (1) {\
>			/* macro body */\
>		}\
>		else

I am also not going to use Peter's suggestion because it too can cause
un-obvious behavior, but this time if the user makes a small syntax
error. Suppose I forget the semicolon when I call the macro?

		macro( args )
		next_statment;

Voila! next_statement is NEVER called because it is gobbled up in
the `else' clause of the expanded macro. Yuck...that would take hours
to find.

I also find the macro definition hard to read...whenever I see an
`else' I expect it to be controlling something. Very confusing.

				Kevin
-- 
Kevin Szabo  watmath!wateng!ksbszabo (U of Waterloo VLSI Group, Waterloo Ont.)

arnold@gatech.UUCP (Arnold Robbins) (02/01/85)

Okay, folks, we've discussed this one before.  The macro

#define assert(x) if (!(x)) die_miserably("x bombed\n")

doesn't work because of problems with a missing else.  It was suggested

#define assert(x) if (!(x)) die_miserably("x bombed\n") else /* no ; */

but if the real semicolon is left off by accident, the next statement is eaten.
Now, putting braces around it also won't work:

#define assert(x) { if (!(x)) die_miserably("x bombed\n"); }

because of this:

	if (something)
		assert (something_else);/* <--- this ; will bomb cc */
	else
		another_thing_altogether();
	
So, as has been mentioned before, the two ways to do this are

#define assert(x)  do { if (!(x)) die_miserably("x bombed\n"); } while (0)

which will get executed exactly once, and protects the macro syntactically.
This also should not pose a code generation/efficiency problem.  The other
way is this:

#define assert(x)	if(x) ; else die_miserably ("x bombed\n")

which will also work. This topic has gone around (several times) before.
I am hoping that this note will settle it, so that we can discuss something
else.  Thanks,
-- 
Arnold Robbins
CSNET:	arnold@gatech	ARPA:	arnold%gatech.csnet@csnet-relay.arpa
UUCP:	{ akgua, allegra, hplabs, ihnp4, seismo, ut-sally }!gatech!arnold

Help advance the state of Computer Science: Nuke a PR1ME today!

alex@ucla-cs.UUCP (02/03/85)

[Debugged]

Wherever possible a macro should expand into an expression.

    #define assert(x) (!(x) ? die_miserably("x bombed\n") : 1)

will do what is desired--if x is untrue, die_miserably will be executed.
(Maybe this could even be improved by casting the result to void?)  

aug@cybvax0.UUCP (Alan Green) (02/04/85)

> Okay, folks, we've discussed this one before.  The macro
> 
> #define assert(x) if (!(x)) die_miserably("x bombed\n")
> 
> doesn't work because of problems with a missing else.  It was suggested
> ...

Whats wrong with:

#define assert(cond)	( (cond) ? 0 : \
			    (fprintf (stderr, \
				"assertion failed at line %d in file %s\n", \
					__LINE__, __FILE__), \
			     exit(-1) \
			    ) \
			)

	???


					harvard!cybvax0!aug

jss@sjuvax.UUCP (J. Shapiro) (02/05/85)

[Aren't you hungry...]

In article <33@daisy.UUCP> pkl@daisy.UUCP (Peter K. Lee) writes:
>	# define macro(args)\
>		if (1) {\
>			/* macro body */\
>		}\
>		else
Kevin Szabo points out that:
>	macro( args )
>	next_statment;
fails in this macro, and is hard to find.  If, hoever, one writes

	else;

instead of

	else

the problem goes away.

Personally I still like my macros simple. I favor the notion of intelligent
compilation and elimination of redundant/unused object modules as more
valuable then #define'd pseudofunctions.

If only there were a way to say "now about this function - it goes inline"
in C. It's been done in Franz Lisp - take a look at defmacro....
Any volunteers? :-)

ndiamond@watdaisy.UUCP (Norman Diamond) (02/08/85)

> > >	# define macro(args)\
> > >		if (1) {\
> > >			/* macro body */\
> > >		}\
> > >		else
> > > -- P. Lee
> >
> >	macro( args )
> >	next_statment;
> > fails in this macro, and is hard to find.
> > -- K. Szabo
>
> If, hoever, one writes
> 	else;
> instead of
> 	else
> the problem goes away.
> -- J. Shapiro

Then:
    if (condition)
         macro( args );
    else
         other_stuff;
gives a syntax error!
(OK it's easier to find, but then suppose the macro changes to a function.
OK, it's still easier to find.
BUT IT'S STILL OBNOXIOUS!)
-- 

   Norman Diamond

UUCP:  {decvax|utzoo|ihnp4|allegra|clyde}!watmath!watdaisy!ndiamond
CSNET: ndiamond%watdaisy@waterloo.csnet
ARPA:  ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa

"Opinions are those of the keyboard, and do not reflect on me or higher-ups."

bsa@ncoast.UUCP (Brandon Allbery) (02/11/85)

> Article <1924@wateng.UUCP>, from ksbszabo@wateng.UUCP (Kevin Szabo)
+----------------
| In article <33@daisy.UUCP> pkl@daisy.UUCP (Peter K. Lee) writes:
| >	# define macro(args)\
| >		if (1) {\
| >			/* macro body */\
| >		}\
| >		else
| 
| I am also not going to use Peter's suggestion because it too can cause
| un-obvious behavior, but this time if the user makes a small syntax
| error. Suppose I forget the semicolon when I call the macro?
| ...
| I also find the macro definition hard to read...whenever I see an
| `else' I expect it to be controlling something. Very confusing.

The answer was posted about 3 months ago.

#define macro(args)\
	do\
	    {\
	    /* macro body */\
	    }\
	    while (0)

The body is executed exactly once, since the condition isn't found to
b false until the end... and a missing semicolon will show up as a syntax
error, which is reasonable.

Brandon (bsa@ncoast.UUCP)
-- 
Brandon Allbery, decvax!cwruecmp!ncoast!bsa, "ncoast!bsa"@case.csnet (etc.)
6504 Chestnut Road, Independence, Ohio 44131 +1 216 524 1416 (or what have you)