Re: [PATCH] 2.4.19-rc2-ac2 pdc202xx.c update

Mikael Pettersson (mikpe@csd.uu.se)
Tue, 23 Jul 2002 12:49:56 +0200 (MET DST)


On Tue, 23 Jul 2002 09:19:15 +0200, Francois Romieu wrote:
>support <support@promise.com.tw> :
>> We think there is no problems, Acturally it is
>>
>> if (speed == XFER_UDMA_2) {
>> OUT_BYTE((thold + adj), indexreg);
>> OUT_BYTE((IN_BYTE(datareg) & 0x7f), datareg);
>> }
>>
>> So,
>> if (speed == XFER_UDMA_2)
>> set_2regs(thold, (IN_BYTE(datareg) & 0x7f));

The problem is a common one for complex statement-like macros.
You have a macro M consisting of (in this case) two statements
S1 and S2: "#define M S1; S2". Now consider what happens when
M is used in non-block context, i.e. not as a top-level
statement between { and } but rather in e.g. the true branch
of an if-statement:

if (condition)
M;

which after preprocessing becomes

if (condition)
S1; S2;

However, indentation doesn't matter, only grouping does, so this
USE of the macro really is

if (condition)
S1;
S2;

Now do you see? The macro body was broken up, and the second statement
is now executed unconditionally.

The traditional approach is to write the body of a complex macro as a
do { ... } while(0) statement (i.e. #define M do { S1; S2; } while(0))
since this turns the macro body into a single unbreakable statement
which is safe to use in any context where a statement may occur.

Simply wrapping the macro body with a pair of braces { } doesn't work
in all contexts; the do{...}while(0) idiom does.

/Mikael
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/