Author Topic: X-Macro Support  (Read 4284 times)

Tim Kemp

  • Senior Community Member
  • Posts: 546
  • Hero Points: 92
X-Macro Support
« on: March 19, 2012, 02:30:56 PM »
I have been using X-Macros pretty heavily for the last few years and had resigned myself to not being able to do things like resolve generated enumeration values.  Recently I used Visual Studio for debugging and to my surprise it understands X-Macros!  It has all sorts of other deficiencies and I don't plan to move to VS for general code entry, but it did get me to thinking that it would be wonderful if the SlickEdit tagger more fully understood C preprocessor directives.

I found a topic from two years ago about this very subject, but nothing since.  I know it isn't a widely used technique, but it is quite useful and would be even more so if SlickEdit supported it.

Shelku

  • Community Member
  • Posts: 45
  • Hero Points: 0
Re: X-Macro Support
« Reply #1 on: April 08, 2012, 03:43:46 PM »
I agree that this would be nice! I program in C and have found that there are many cases where it is more efficient and less error-prone to set up X-Macro tables than to try to have comments that remind the programmer to update multiple variables/locations simultaneously.

I currently have my compiler give me the preprocessor output files (.i). I then include a select few of these into my project so that SE can tag the X-Macro outputs... the only drawback is that the .i file typically includes lots of other typedefs and includes. That means that when I try to "go to definition" (or similar), then SE always prompts me where I want to navigate to - the .h file or the .i file(s). It would be nice if SE could have an option to "remember" where to navigate to so that it would stop prompting after asking once...

Dennis

  • Senior Community Member
  • Posts: 3961
  • Hero Points: 517
Re: X-Macro Support
« Reply #2 on: April 10, 2012, 12:10:24 PM »
Visual Studio gets its tagging information primarily from the debug information generated by the compiler.  I think they are kind of lucking into having support by virtue of the code being kind enough to at least compile.

You could improve support for your X-Macros in SlickEdit by defining them for the C/C++ preprocessing.  I would recommend defining then for the data structure definitions, since that will help you with tagging the most.  The various procedure body generation tricks, while, yes it would be nice if our tagging could handle that, it would require doing full preprocessing and would pull performance down significantly.

One trick you can do with SlickEdit that you can't do with many other tools is search for references to #include files.  Say you are in a file that contains #include "cpp-trick.h" and you want to see where else the macro tables are included, you can open the Defs tool window, right click on "cpp-trick.h" and then ask to "Show references".  It is basically a string match, it won't distinguish between quotes and angle brackets, or different relative paths, but given the nature of the X-Macros trick, I would expect there to be a lot of consistency in how you reference the #include.

Shelku

  • Community Member
  • Posts: 45
  • Hero Points: 0
Re: X-Macro Support
« Reply #3 on: April 11, 2012, 02:43:11 AM »
Hi Dennis,

Could you please clarify how I would define the X-Macro in SE's preprocessor option? And this would be a global SE option wouldn't it (as opposed to a project/workspace define)?

Here's a pretty simple example that I have:
Code: [Select]
//#define FRAMER_MEMBER(enumName, parser, formatter, maxSize)
#define FRAMER_TABLE \
FRAMER_MEMBER(UNSET, NULL, NULL, 0 ) \
FRAMER_MEMBER(RAW, RawFrameParse, RawFrameFormat, RAW_FRAME_MAX_SIZE ) \
FRAMER_MEMBER(LINE, LineFrameParse, LineFrameFormat,LINE_FRAME_MAX_SIZE )

Then I have various uses of my table:
Code: [Select]
typedef enum
{
#define FRAMER_MEMBER(enumName, parser, formatter, maxSize) \
FRAMER_##enumName,
FRAMER_TABLE
#undef FRAMER_MEMBER

NUM_FRAMERS
}LINK_FRAMERS;

static const struct FRAMER_POINTERS framers[NUM_FRAMERS] = {
#define FRAMER_MEMBER(enumName, parser, formatter, maxSize) \
{parser, formatter, maxSize},
FRAMER_TABLE
#undef FRAMER_MEMBER
};

char const * eStr_LINK_FRAMERS[] = {
#define FRAMER_MEMBER(enumName, parser, formatter, maxSize) \
#enumName,
FRAMER_TABLE
#undef FRAMER_MEMBER
};

Dennis

  • Senior Community Member
  • Posts: 3961
  • Hero Points: 517
Re: X-Macro Support
« Reply #4 on: April 11, 2012, 12:59:54 PM »
Go to: Document > C/C++ Options... > C/C++ Preprocessing

Click New...
Name of the symbol is FRAMER_TABLE
Definition is the body of the macro, like you have it below.

Click New..
Name of the symbol is FRAMER_MEMBER(enumName,parser,formatter,maxSize)
Body of the macro is:
FRAMER_##enumName

Yes, this is a global setting rather than per-project or per-workspace.  The #defines will be stored in your SlickEdit configuration directory in usercpp.h.

This will only cover the enumerator definitions.  But at least then you will get tagging for FRAMER_UNSET, FRAMER_RAW, and FRAMER_LINE.

Like I said, you shouldn't have to worry about expanding the macros correctly in struct initializers and procedure bodies.  The important thing is that the declarations are tagged so that you have the symbol information you want for doing completions.  I don't know how else you use FRAMER_TABLE.  If you also use it to define structs, then that might be more important than the enumerators.  If you want to be clever with it you could define FRAMER_TABLE to cross over and define both enumerators and structs.

Code: [Select]
#define FRAMER_TABLE \
            FRAMER_UNSET \
            FRAMER_RAW \
            FRAMER_LINE \
            NUM_FRAMERS \
            } LINK_FRAMERS; \
            const int RAW_FRAME_MAX_SIZE;\
            const int LINE_FRAME_MAX_SIZE;\
            class RawFrameParse {};\
            class LineFrameParse {};\
            class RawFrameFormat {};\
            class RawFrameFormat {};\
            typedef enum {