473,378 Members | 1,436 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Help with 2-level macro expansion

Hi,
We have bunch of message levels and depending on whether that level is
turned on, messages of that level are printed. For example, we have
levels like MSG_LOW, MSG_MED etc.

We want to provide a wrapper API on top of this to print various kinds
of messages and map the wrapper API to either MSG_LOW or MSG_MED. For
example, our wrapper API have macros such as
MSG_FUNCTION_ENTRY, MSG_FUNCTION_EXIT, MSG_STATE_CHANGE,
MSG_INVALID_INPUT etc. Whenever a function is called, we call
MSG_FUNCTION_ENTRY macro. This shields the programmer from whether
this kind of messages is mapped to LOW or MED and it allows us to
configure what kind of messages we want to print in various flavors of
a build. In debug build, we might map MSG_FUNCTION_ENTRY to MSG_MED
and in production build, we might map it to MSG_LOW.

I wrote following macros to get this functionality.

#define IS_MSG_LOW_ON 0
#define IS_MSG_MED_ON 1

#define MSG_FUNCTION_ENTRY_LEVEL MSG_MED
#define MSG_FUNCTION_EXIT_LEVEL MSG_MED

#define MSG_FUNCTION_ENTRY(fmt_string, x, y, z) \
#if (IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON == 1) \
printf(fmt_string, x, y, z);

But this is not working as IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON is
translated to IS_MSG_FUNCTION_ENTRY_LEVEL_ON instead of IS_MSG_MED_ON.
So how do I get this to work?

Thx,
Srinivas
Jun 27 '08 #1
5 1750
Srinivas Mudireddy wrote:
...I wrote following macros to get this functionality.

#define IS_MSG_LOW_ON 0
#define IS_MSG_MED_ON 1

#define MSG_FUNCTION_ENTRY_LEVEL MSG_MED
#define MSG_FUNCTION_EXIT_LEVEL MSG_MED

#define MSG_FUNCTION_ENTRY(fmt_string, x, y, z) \
#if (IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON == 1) \
printf(fmt_string, x, y, z);

But this is not working...
See...

http://www.c-faq.com/cpp/index.html

--
Peter
Jun 27 '08 #2
Srinivas Mudireddy <sr****************@gmail.comwrites:

This seems not have been answered, so I'll have a go...
We want to provide a wrapper API on top of this to print various kinds
of messages and map the wrapper API to either MSG_LOW or MSG_MED.
<snip>
I wrote following macros to get this functionality.

#define IS_MSG_LOW_ON 0
#define IS_MSG_MED_ON 1

#define MSG_FUNCTION_ENTRY_LEVEL MSG_MED
#define MSG_FUNCTION_EXIT_LEVEL MSG_MED

#define MSG_FUNCTION_ENTRY(fmt_string, x, y, z) \
#if (IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON == 1) \
printf(fmt_string, x, y, z);

But this is not working as IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON is
translated to IS_MSG_FUNCTION_ENTRY_LEVEL_ON instead of IS_MSG_MED_ON.
So how do I get this to work?
Three things need to be sorted. First, a typo:

#if (IS_ ## MSG_FUNCTION_ENTRY_LEVEL ## _ON == 1) \

(note the _ON). Second, you will never be able to generate a
pre-processing directive (in this case a #if) using a macro. You
just can't. If you can live with the macro expanding to an "if"
(which will in all likelyhood be optimised away) then you need to sort
out the "real" problem. To get MSG_FUNCTION_ENTRY_LEVEL expanded
rather than literally token pasted, you need another round of macro
expansion:

#define XP(s) PASTE(s)
#define PASTE(s) IS_ ## s ## _ON

#define MSG_FUNCTION_ENTRY(fmt_string, x, y, z) \
if (XP(MSG_FUNCTION_ENTRY_LEVEL) == 1) \
printf(fmt_string, x, y, z)

(You might dream up better names).

Finally, if you have C99's variadic macros, you don't need to have
three fixed arguments to printf.

#define MSG_FUNCTION_ENTRY(fmt_string, ...) \
if (XP(MSG_FUNCTION_ENTRY_LEVEL) == 1) \
printf(fmt_string, __VA_ARGS__)

If you don't have that, you can consider the "double parentheses"
trick:

#define MSG_FUNCTION_ENTRY(args) \
if (XP(MSG_FUNCTION_ENTRY_LEVEL) == 1) \
printf args

where you use it like this:

MSG_FUNCTION_ENTRY(("A message\n"));
MSG_FUNCTION_ENTRY(("An int %d\n", x));

Note, also, that I have removed the trailing ; from the macro. I
prefer to have it added at the invocation.

I hope that is useful.

--
Ben.
Jun 27 '08 #3
On Apr 28, 9:43 am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
Srinivas Mudireddy <srinivas.mudire...@gmail.comwrites:

This seems not have been answered, so I'll have a go...


We want to provide a wrapper API on top of this to print various kinds
of messages and map the wrapper API to either MSG_LOW or MSG_MED.
<snip>
I wrote following macros to get this functionality.
#define IS_MSG_LOW_ON 0
#define IS_MSG_MED_ON 1
#define MSG_FUNCTION_ENTRY_LEVEL MSG_MED
#define MSG_FUNCTION_EXIT_LEVEL MSG_MED
#define MSG_FUNCTION_ENTRY(fmt_string, x, y, z) \
#if (IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON == 1) \
printf(fmt_string, x, y, z);
But this is not working as IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON is
translated to IS_MSG_FUNCTION_ENTRY_LEVEL_ON instead of IS_MSG_MED_ON.
So how do I get this to work?

Three things need to be sorted. First, a typo:

#if (IS_ ## MSG_FUNCTION_ENTRY_LEVEL ## _ON == 1) \

(note the _ON). Second, you will never be able to generate a
pre-processing directive (in this case a #if) using a macro. You
just can't. If you can live with the macro expanding to an "if"
(which will in all likelyhood be optimised away) then you need to sort
out the "real" problem. To get MSG_FUNCTION_ENTRY_LEVEL expanded
rather than literally token pasted, you need another round of macro
expansion:

#define XP(s) PASTE(s)
#define PASTE(s) IS_ ## s ## _ON

#define MSG_FUNCTION_ENTRY(fmt_string, x, y, z) \
if (XP(MSG_FUNCTION_ENTRY_LEVEL) == 1) \
printf(fmt_string, x, y, z)

(You might dream up better names).

Finally, if you have C99's variadic macros, you don't need to have
three fixed arguments to printf.

#define MSG_FUNCTION_ENTRY(fmt_string, ...) \
if (XP(MSG_FUNCTION_ENTRY_LEVEL) == 1) \
printf(fmt_string, __VA_ARGS__)

If you don't have that, you can consider the "double parentheses"
trick:

#define MSG_FUNCTION_ENTRY(args) \
if (XP(MSG_FUNCTION_ENTRY_LEVEL) == 1) \
printf args

where you use it like this:

MSG_FUNCTION_ENTRY(("A message\n"));
MSG_FUNCTION_ENTRY(("An int %d\n", x));

Note, also, that I have removed the trailing ; from the macro. I
prefer to have it added at the invocation.

I hope that is useful.

--
Ben.
Thx for the help Ben.
Jun 27 '08 #4
Ben Bacarisse wrote:
Srinivas Mudireddy <sr****************@gmail.comwrites:

This seems not have been answered, so I'll have a go...
I directed the OP to the FAQ chapter on preprocessing.
#if (IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON == 1) \
printf(fmt_string, x, y, z);

But this is not working as IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON is
translated to IS_MSG_FUNCTION_ENTRY_LEVEL_ON instead of IS_MSG_MED_ON.
So how do I get this to work?

Three things need to be sorted. First, a typo:

#if (IS_ ## MSG_FUNCTION_ENTRY_LEVEL ## _ON == 1) \

(note the _ON).
Note the LEVEL_. Also note that _ON is a reserved (for any use)
identifier.

<snip>

--
Peter
Jun 27 '08 #5
Peter Nilsson <ai***@acay.com.auwrites:
Ben Bacarisse wrote:
>Srinivas Mudireddy <sr****************@gmail.comwrites:

This seems not have been answered, so I'll have a go...

I directed the OP to the FAQ chapter on preprocessing.
#if (IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON == 1) \
printf(fmt_string, x, y, z);

But this is not working as IS_ ## MSG_FUNCTION_ENTRY_LEVEL_ ## ON is
translated to IS_MSG_FUNCTION_ENTRY_LEVEL_ON instead of IS_MSG_MED_ON.
So how do I get this to work?

Three things need to be sorted. First, a typo:

#if (IS_ ## MSG_FUNCTION_ENTRY_LEVEL ## _ON == 1) \

(note the _ON).

Note the LEVEL_.
Yes, I changed both halves but only pointed one out. Presumably you
are suggesting the original form was deliberate (and the real error
was not using MSG_FUNCTION_ENTRY_LEVEL_ earlier). The reason being to
avoid:
Also note that _ON is a reserved (for any use)
identifier.
Ouch! Good catch. However, does it matter in this case? Isn't _ON
is only a preprocessing token and never gets to be real grown up
identifier.

--
Ben.
Jun 27 '08 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

21
by: Dave | last post by:
After following Microsofts admonition to reformat my system before doing a final compilation of my app I got many warnings/errors upon compiling an rtf file created in word. I used the Help...
9
by: Tom | last post by:
A question for gui application programmers. . . I 've got some GUI programs, written in Python/wxPython, and I've got a help button and a help menu item. Also, I've got a compiled file made with...
6
by: wukexin | last post by:
Help me, good men. I find mang books that introduce bit "mang header files",they talk too bit,in fact it is my too fool, I don't learn it, I have do a test program, but I have no correct doing...
3
by: Colin J. Williams | last post by:
Python advertises some basic service: C:\Python24>python Python 2.4.1 (#65, Mar 30 2005, 09:13:57) on win32 Type "help", "copyright", "credits" or "license" for more information. >>> With...
7
by: Corepaul | last post by:
Missing Help Files When I enter "recordset" as the keyword and search the Visual Basic Help index, I get many topics of interest in the resulting list. But there isn't any information available...
5
by: Steve | last post by:
I have written a help file (chm) for a DLL and referenced it using Help.ShowHelp My expectation is that a developer using my DLL would be able to access this help file during his development time...
8
by: Mark | last post by:
I have loaded Visual Studio .net on my home computer and my laptop, but my home computer has an abbreviated help screen not 2% of the help on my laptop. All the settings look the same on both...
10
by: JonathanOrlev | last post by:
Hello everybody, I wrote this comment in another message of mine, but decided to post it again as a standalone message. I think that Microsoft's Office 2003 help system is horrible, probably...
1
by: trunxnirvana007 | last post by:
'UPGRADE_WARNING: Array has a new behavior. Click for more: 'ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?keyword="9B7D5ADD-D8FE-4819-A36C-6DEDAF088CC7"' 'UPGRADE_WARNING: Couldn't resolve...
0
by: hitencontractor | last post by:
I am working on .NET Version 2003 making an SDI application that calls MS Excel 2003. I added a menu item called "MyApp Help" in the end of the menu bar to show Help-> About. The application...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.