Token pasting and what does the result need to be?

M

Mark Odell

I'm running two different compilers against some hairy macros and one,
gcc, doesn't like my token pasting result so much. It says, " "." and
"foo" does not give a valid preprocessing token ". Some further reading
suggests that since .foo is not a valid preproc. token that I can't
really do what I want, portably. The macro looks like this:

#define DMA_CHECK_SR_BIT(reg, REG, ch) do \
{ \
DmaSr sr; \
\
sr.all = 0; \
sr.bit.##reg##ch = 1; \
\
printf("SR[" #REG "] = 0x%08X", sr.all); \
if (sr.all == DMA0_SR_##REG##_CHAN(ch)) \
{ \
printf(", okay\n"); \
} \
else \
{ \
printf(" != 0x%08X (FAIL)\n", DMA0_SR_##REG##_CHAN(ch)); \
} \
} while (0)

and DMA_CHECK_SR_BIT(cs, CS, 0) ends up creating what looks like
exactly what I want (sorry for the long line):

do { DmaSr sr; sr.all = 0; sr.bit.cs0 = 1; printf("SR[" "CS" "] =
0x%08X", sr.all); if (sr.all == DMA0_SR_CS_CHAN(0)) { printf(",
okay\n"); } else { printf(" != 0x%08X (FAIL)\n", DMA0_SR_CS_CHAN(0)); }
} while (0);

So I fear that gcc and the other compiler do the right thing, for me,
but I should re-write the macro to be more portable.

Comments? Thanks,
 
E

Eric Sosman

Mark Odell wrote On 05/01/06 14:21,:
I'm running two different compilers against some hairy macros and one,
gcc, doesn't like my token pasting result so much. It says, " "." and
"foo" does not give a valid preprocessing token ". Some further reading
suggests that since .foo is not a valid preproc. token that I can't
really do what I want, portably. The macro looks like this:

#define DMA_CHECK_SR_BIT(reg, REG, ch) do \
{ \
DmaSr sr; \
\
sr.all = 0; \
sr.bit.##reg##ch = 1; \
^^
Lose these. You don't want a token made
up of . and reg and ch, you want the two tokens . and
regch.
 
W

Walter Roberson

Eric Sosman said:
Mark Odell wrote On 05/01/06 14:21,:
^^
Lose these. You don't want a token made
up of . and reg and ch, you want the two tokens . and
regch.

Also, since . is an operator, one can have whitespace around it.
If one were to add a space after the sr.bit. portion then it would
perhaps become clearer as to what kind of token-pasting one needed to do.
 
M

Mark Odell

Eric said:
Mark Odell wrote On 05/01/06 14:21,:
^^
Lose these. You don't want a token made
up of . and reg and ch, you want the two tokens . and
regch.

Thanks for the reply. However, trying what you suggest seems to
engender the same warning, .e.g.

#define DMA_CHECK_SR_BIT(regCh, REG, ch) do \
{ \
DmaSr sr; \
\
sr.all = 0; \
sr.bit.##regCh = 1; \
[snip]

invoked with DMA_CHECK_SR_BIT(cs0, CS, 0); gives me:

pasting "." and "cs0" does not give a valid preprocessing token
do { DmaSr sr; sr.all = 0; sr.bit.cs0 = 1;
[snip]

I don't think I understood your suggestion correctly.

Regards,
 
E

Eric Sosman

Mark Odell wrote On 05/01/06 15:20,:
Eric said:
Mark Odell wrote On 05/01/06 14:21,:


^^
Lose these. You don't want a token made
up of . and reg and ch, you want the two tokens . and
regch.


Thanks for the reply. However, trying what you suggest seems to
engender the same warning, .e.g.

#define DMA_CHECK_SR_BIT(regCh, REG, ch) do \
{ \
DmaSr sr; \
\
sr.all = 0; \
sr.bit.##regCh = 1; \
[snip]

invoked with DMA_CHECK_SR_BIT(cs0, CS, 0); gives me:

pasting "." and "cs0" does not give a valid preprocessing token
do { DmaSr sr; sr.all = 0; sr.bit.cs0 = 1;
[snip]

I don't think I understood your suggestion correctly.

Perhaps the up-arrows don't line up in your newsreader
as they do in my newswriter. You should lose the first ##,
not the second, so the offending line looks like

sr.bit.reg##ch = 1;

Or, following Walter Roberson's sensible suggestion

sr.bit. reg##ch = 1;
 
M

Mark Odell

Eric said:
Mark Odell wrote On 05/01/06 15:20,:
Eric said:
Mark Odell wrote On 05/01/06 14:21,:

I'm running two different compilers against some hairy macros and one,
gcc, doesn't like my token pasting result so much. It says, " "." and
"foo" does not give a valid preprocessing token ". Some further reading
suggests that since .foo is not a valid preproc. token that I can't
really do what I want, portably. The macro looks like this:

#define DMA_CHECK_SR_BIT(reg, REG, ch) do \
{ \
DmaSr sr; \
\
sr.all = 0; \
sr.bit.##reg##ch = 1; \

^^
Lose these. You don't want a token made
up of . and reg and ch, you want the two tokens . and
regch.


Thanks for the reply. However, trying what you suggest seems to
engender the same warning, .e.g.

#define DMA_CHECK_SR_BIT(regCh, REG, ch) do \
{ \
DmaSr sr; \
\
sr.all = 0; \
sr.bit.##regCh = 1; \
[snip]

invoked with DMA_CHECK_SR_BIT(cs0, CS, 0); gives me:

pasting "." and "cs0" does not give a valid preprocessing token
do { DmaSr sr; sr.all = 0; sr.bit.cs0 = 1;
[snip]

I don't think I understood your suggestion correctly.

Perhaps the up-arrows don't line up in your newsreader
as they do in my newswriter. You should lose the first ##,
not the second, so the offending line looks like

sr.bit.reg##ch = 1;

Or, following Walter Roberson's sensible suggestion

sr.bit. reg##ch = 1;

Oh. But then I can't write one macro to handle multiple registers via a
macro argument. I did not think you meant that, despite the ^^ markers
because it was not what I wished to have. I agree with you that your
proposed solution will work and be correct WRT ISO C, it's just not
what I was hoping for. Thanks to you both for your replies.
 
W

Walter Roberson

[...]

Oh. But then I can't write one macro to handle multiple registers via a
macro argument. I did not think you meant that, despite the ^^ markers
because it was not what I wished to have.[/QUOTE]

You are apparently passing in both reg and ch to the macro.
For example, if you passed in A and 17, you would want A17 to
be the result? Should the combined register name then be
eligable for further substitution -- for example,

#define A7 SP
DMA_CHECK_SR_BIT(A,something,7)

would you then want the code to be generated in terms of A7 or would
you want the completed token A7 to then be looked up and SP substituted?


I suspect that what you want to do is something like this:

#define PASTE(a,b) a##b

then

sr.bit. PASTE(reg,ch)


There are some subtle semantics about exactly what is substituted
when you use ## and usually you can get around the semantics by
using an extra layer of #define to do the pasting.
 
M

Mark Odell

Walter said:
Mark Odell wrote On 05/01/06 14:21,:
#define DMA_CHECK_SR_BIT(reg, REG, ch) do \
[...]

Oh. But then I can't write one macro to handle multiple registers via a
macro argument. I did not think you meant that, despite the ^^ markers
because it was not what I wished to have.

You are apparently passing in both reg and ch to the macro.
For example, if you passed in A and 17, you would want A17 to
be the result? Should the combined register name then be
eligable for further substitution -- for example,

#define A7 SP
DMA_CHECK_SR_BIT(A,something,7)

would you then want the code to be generated in terms of A7 or would
you want the completed token A7 to then be looked up and SP substituted?


I suspect that what you want to do is something like this:

#define PASTE(a,b) a##b

then

sr.bit. PASTE(reg,ch)[/QUOTE]

Thanks again for the reply. Sadly, I completely missed the mark on
Eric's reply. Had I done what he had instructed on the correct source
file in the directory under test, instead of some other file. The
warning would have gone away and I would have had the desired result. I
get it now and it works. The answer was just as Eric said, remove the
first pair of #'s. E.g. sr.bit.reg##ch works w/o warning and
sr.bit.##reg##ch worked but is (now) weird looking and produces a
warning.

Best regards,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top