Macro Destroyer

Discussion in 'C++' started by JKop, Oct 14, 2004.

  1. JKop

    JKop Guest

    I was doing some Win32 programming today, having to include the file
    "windows.h". Anyway, I'm thinking of writing a program that'll work like so:

    macrodestroyer.exe windows.h

    What this program will do is scour through the file, replacing all macros
    with global const variables and inline functions. So for instance, if you
    have:

    #define MAX_LOADSTRING 100

    It'll become:

    unsigned const MAX_LOADSTRING = 100;

    And if you have:

    #define Minus5(t) (t-5)

    Then'd be turned into

    template <class T,class R>
    inline T Minus5(R r)
    {
    return (t-5);
    }


    Or something along those lines.

    Anyway...

    The main benefits of this would be:

    A) Follows scoping rules, and you could wrap "windows.h" in a namespace, eg:

    namespace Win { #include "windows.h" }


    B) You wouldn't have the problem of:

    SomeMacro(++i);

    in that it may increment it more than once.



    Also, I would turn:

    #define LRESULT long;

    into:

    typdef long LRESULT;


    Anyway, before I get going on this little pet project, has this been done
    before?

    Any ideas, comments at all?


    -JKop
     
    JKop, Oct 14, 2004
    #1
    1. Advertising

  2. JKop

    hari4063 Guest

    It is OK project, but it is highly chance that is not work OK. Reason for
    this my be different meaning of:

    #define MACROTYPE type*

    and

    typedef type MYTYPE

    This two forms are different in term of:

    MACROTYPE a, b;

    is:
    type *a, b; // b is not pointer to type

    but in real typedef (MYTYPE)

    MYTYPE a, b; // a and b are pointers.

    I realy do not know is something like this is present in windows.h so than
    your project have chance :)
     
    hari4063, Oct 14, 2004
    #2
    1. Advertising

  3. JKop

    JKop Guest

    hari4063 posted:

    > It is OK project, but it is highly chance that is not work OK. Reason
    > for this my be different meaning of:
    >
    > #define MACROTYPE type*
    >
    > and
    >
    > typedef type MYTYPE
    >
    > This two forms are different in term of:
    >
    > MACROTYPE a, b;
    >
    > is:
    > type *a, b; // b is not pointer to type
    >
    > but in real typedef (MYTYPE)
    >
    > MYTYPE a, b; // a and b are pointers.
    >
    > I realy do not know is something like this is present in windows.h so
    > than your project have chance :)



    That's a very good thing to point out, I hadn't thought of that.

    I'll look into it...


    -JKop
     
    JKop, Oct 14, 2004
    #3
  4. "JKop" <> wrote in message
    news:tntbd.33396$...
    >
    > I was doing some Win32 programming today, having to include the file
    > "windows.h". Anyway, I'm thinking of writing a program that'll work like
    > so:
    >
    > macrodestroyer.exe windows.h
    >
    > What this program will do is scour through the file, replacing all macros
    > with global const variables and inline functions. So for instance, if you
    > have:

    [examples reordered for discussion]

    > #define MAX_LOADSTRING 100
    > It'll become:
    > unsigned const MAX_LOADSTRING = 100;

    Hum, why *unsigned* ? (the value could be -100)
    I tend to prefer enum { MAX_LOADSTRING = 100 }; for such things anyway.

    [ incorrect trailing ; removed from the next line ]
    > #define LRESULT long
    > into:
    > typdef long LRESULT;


    Note that the two previous cases will not always be easy to distinguish.
    Consider:
    #define THIS_STATUS_CODE SOME_PREVIOUS_ID
    Should this become a typedef or a const?

    You may need to parse #include-d files to find out...
    The problem is aggravated by the fact that SOME_PREVIOUS_ID
    may not even have been seen when the macro is defined.
    How will you translate:
    #define a b
    // ... many lines or files later:
    #define b int // or could be 0x00000000 instead of 'int'

    Also, in <windows.h>, you will find a lot of macros such as:
    #define GetWindowText GetWindowTextA
    Which would best be translated into something like (e.g.):
    inline BOOL GetWindowText(HANDLE h, CHAR* p)
    { return GetWindowTextA(h,p); }

    These may additionally be conditionally compiled:
    #ifndef UNICODE
    #define GetWindowText GetWindowTextA
    #else
    #define GetWindowText GetWindowTextW
    #endif

    > #define Minus5(t) (t-5)
    >
    > Then'd be turned into
    >
    > template <class T,class R>
    > inline T Minus5(R r)
    > {
    > return (t-5);
    > }

    Beware that this may not always be equivalent.
    In particular, it may generate additional member copies.


    > The main benefits of this would be:
    >
    >
    > A) Follows scoping rules, and you could wrap "windows.h" in a namespace,
    > eg:
    >
    > namespace Win { #include "windows.h" }
    >
    >
    > B) You wouldn't have the problem of:
    >
    > SomeMacro(++i);
    >
    > in that it may increment it more than once.

    Yes, but then someone will accidentally compile the code
    with the original version of <windows.h> and eventually
    face strange and unexpected bugs.


    > Anyway, before I get going on this little pet project, has this been done
    > before?
    >
    > Any ideas, comments at all?

    As you can tell, this is not a trivial task: you need
    a preprocessor, a parser, and probably need to scan
    all files together prior to processing.

    I sympathize...
    but I've given up long ago (locally) modifying files supplied
    by a vendor. Better wrap and encapsulate them into
    your own files/classes.


    Regards,
    Ivan
    --
    http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
     
    Ivan Vecerina, Oct 14, 2004
    #4
  5. JKop

    hari4063 Guest

    So, ... if you make this project, please pass mail to me (i will be glad to
    see this, for free-or-not :)
     
    hari4063, Oct 14, 2004
    #5
  6. JKop

    JKop Guest

    My first task will be:


    #pragma once


    becomes:


    #ifndef INCLUDE_BLAH_HPP
    #define INCLUDE_BLAH_HPP

    //contents of file

    #endif
     
    JKop, Oct 14, 2004
    #6
  7. JKop

    Chris Theis Guest

    "Ivan Vecerina" <> schrieb
    im Newsbeitrag news:cklpeh$7tc$...
    [SNIP]

    > > #define MAX_LOADSTRING 100
    > > It'll become:
    > > unsigned const MAX_LOADSTRING = 100;

    > Hum, why *unsigned* ? (the value could be -100)
    > I tend to prefer enum { MAX_LOADSTRING = 100 }; for such things anyway.


    You could also run into trouble with enum. IMHO it would be crucial to check
    thoroughly the value of the assignment and produce code accordingly.

    [SNIP]

    Cheers
    Chris
     
    Chris Theis, Oct 14, 2004
    #7
  8. JKop

    Chris Theis Guest

    "JKop" <> schrieb im Newsbeitrag
    news:tntbd.33396$...
    >
    > I was doing some Win32 programming today, having to include the file
    > "windows.h". Anyway, I'm thinking of writing a program that'll work like

    so:
    >
    > macrodestroyer.exe windows.h
    >
    > What this program will do is scour through the file, replacing all macros
    > with global const variables and inline functions. So for instance, if you
    > have:
    >
    > #define MAX_LOADSTRING 100
    >
    > It'll become:
    >
    > unsigned const MAX_LOADSTRING = 100;
    >
    > And if you have:
    >
    > #define Minus5(t) (t-5)
    >
    > Then'd be turned into
    >
    > template <class T,class R>
    > inline T Minus5(R r)
    > {
    > return (t-5);
    > }
    >
    >
    > Or something along those lines.
    >
    > Anyway...
    >
    > The main benefits of this would be:
    >
    > A) Follows scoping rules, and you could wrap "windows.h" in a namespace,

    eg:
    >
    > namespace Win { #include "windows.h" }
    >
    >
    > B) You wouldn't have the problem of:
    >
    > SomeMacro(++i);
    >
    > in that it may increment it more than once.
    >
    >
    >
    > Also, I would turn:
    >
    > #define LRESULT long;
    >
    > into:
    >
    > typdef long LRESULT;
    >
    >
    > Anyway, before I get going on this little pet project, has this been done
    > before?
    >
    > Any ideas, comments at all?


    You know the road to hell is paved with good intentions ;-) Some subtle
    issues were already pointed out in other postings and in general the problem
    is that you would have to perform a very careful & thorough parsing
    (sometimes of the whole project!). Even with that you have a good chance to
    screw up in many places because the intention of the #defines are different
    and hard to interpret automatically. This will become even more difficult
    when they are somehow interlinked.

    Generally, fumbling with compiler manufacturer's headers are bound to give
    you or somebody else trouble some day.

    The idea of replacing the #pragma statement with ordinary include guards is
    a good one and should not attract trouble but I'd stay away from the rest.
    IMHO you can invest your time in a better way.

    Regards
    Chris
     
    Chris Theis, Oct 14, 2004
    #8
  9. JKop

    Tom Widmer Guest

    On Thu, 14 Oct 2004 11:26:17 GMT, JKop <> wrote:

    >
    >I was doing some Win32 programming today, having to include the file
    >"windows.h". Anyway, I'm thinking of writing a program that'll work like so:
    >
    >macrodestroyer.exe windows.h
    >
    >What this program will do is scour through the file, replacing all macros
    >with global const variables and inline functions. So for instance, if you
    >have:
    >
    >#define MAX_LOADSTRING 100
    >
    >It'll become:
    >
    >unsigned const MAX_LOADSTRING = 100;


    You should keep the type the same:

    int const MAX_LOADSTRING = 100;

    >And if you have:
    >
    >#define Minus5(t) (t-5)
    >
    >Then'd be turned into
    >
    >template <class T,class R>
    >inline T Minus5(R r)
    >{
    > return (t-5);
    >}
    >
    >
    >Or something along those lines.


    That won't work:

    Minus5(10); //error, what about the T parameter?
    You need "typeof" or similar. e.g.
    template <class T>
    typeof(t-5) Minus5(T t)
    {
    return t-5;
    }

    >Anyway...
    >
    >The main benefits of this would be:
    >
    >A) Follows scoping rules, and you could wrap "windows.h" in a namespace, eg:
    >
    >namespace Win { #include "windows.h" }


    I can see this having the potential to cause linker errors. The types
    will be marked as being in namespace Win, but in fact they are global.
    This might cause problems with C++'s typesafe linking (e.g. name
    mangling) that extern "C" doesn't fully negate, but you'll have to try
    it to be sure.

    Tom
     
    Tom Widmer, Oct 14, 2004
    #9
  10. JKop

    JKop Guest


    > That won't work:
    >
    > Minus5(10); //error, what about the T parameter?
    > You need "typeof" or similar. e.g.
    > template <class T>
    > typeof(t-5) Minus5(T t)
    > {
    > return t-5;
    > }



    Can the compiler not determine the return type from the return statement?


    Off to do some experimentation. . .


    -JKop
     
    JKop, Oct 14, 2004
    #10
  11. JKop

    JKop Guest

    I'm going to start off with a broad checklist on this.

    Obviously first of all, I'll deal with #define statements. Here's the kinds:


    1) #define DAYS_IN_A_YEAR 365

    Note: Will become a global const variable of the type of 365.


    2) #define LRESULT long

    Note: Will become a typedef


    3) #define Minus5(a) (a - 5)

    Note: Will become an inline function


    4) #define WIN32_LEAN_AND_MEAN

    Note: I'll leave these alone.


    5) #define public private

    Note: A keyword being redefined - there's obviously some sort of intentional
    hack going on here, so I'll leave it alone!



    After that:

    1) #pragma once

    Note: Will become inclusion guards.



    Any other ideas?


    Firstly I'm going to decide how I'll turn:

    #define DAYS_IN_A_YEAR 365

    into a global const variable. I'll have to devise a way of choosing the
    right type...


    -JKop
     
    JKop, Oct 14, 2004
    #11
  12. JKop wrote:
    > I was doing some Win32 programming today, having to include the file
    > "windows.h". Anyway, I'm thinking of writing a program that'll work like so:
    >
    > macrodestroyer.exe windows.h
    >
    > What this program will do is scour through the file, replacing all macros
    > with global const variables and inline functions. So for instance, if you
    > have:
    >
    > #define MAX_LOADSTRING 100
    >
    > It'll become:
    >
    > unsigned const MAX_LOADSTRING = 100;
    >
    > And if you have:
    >
    > #define Minus5(t) (t-5)
    >
    > Then'd be turned into
    >
    > template <class T,class R>
    > inline T Minus5(R r)
    > {
    > return (t-5);
    > }
    >
    >
    > Or something along those lines.
    >
    > Anyway...
    >
    > The main benefits of this would be:
    >
    > A) Follows scoping rules, and you could wrap "windows.h" in a namespace, eg:
    >
    > namespace Win { #include "windows.h" }
    >
    >
    > B) You wouldn't have the problem of:
    >
    > SomeMacro(++i);
    >
    > in that it may increment it more than once.
    >
    >
    >
    > Also, I would turn:
    >
    > #define LRESULT long;
    >
    > into:
    >
    > typdef long LRESULT;
    >
    >
    > Anyway, before I get going on this little pet project, has this been done
    > before?
    >
    > Any ideas, comments at all?



    Well, why waste time with this old code?


    In any case, in general if you want to create a program which converts
    macro definitions to inline function definitions, etc I think you will
    need to read some book about parsing.

    If you are only interested about doing this for Win32 facilities, you
    have better start reading about .NET and forget that old stuff. :)



    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
     
    Ioannis Vranos, Oct 14, 2004
    #12
  13. JKop

    Jay Nabonne Guest

    On Thu, 14 Oct 2004 11:26:17 +0000, JKop wrote:

    >
    > I was doing some Win32 programming today, having to include the file
    > "windows.h". Anyway, I'm thinking of writing a program that'll work like so:
    >
    > macrodestroyer.exe windows.h
    >
    > What this program will do is scour through the file, replacing all macros
    > with global const variables and inline functions. So for instance, if you
    > have:

    <snip>

    It's *really* important to keep in mind that #define's don't cause
    anything to happen in the "real" file until invoked. They just define text
    replacements for when a macro is eventually used. Here are some fun
    cases (off the top of my head - not tested to be compilable):

    Case 1

    // order isn't important.
    #define Y X+100
    #define X 5

    Case 2

    // Usage of numeric #defines in other preprocessor contexts
    #define VERSION 1
    #ifdef VERSION
    ....
    #endif

    Case 2.1

    #define VERSION 5
    #if VERSION > 4
    ....
    #endif

    Case 3

    // Definitions are transient and may be undone at any time.
    #define X 10

    // later, perhaps in a different file
    #undef X
    #define X 20

    Case 4

    // Anything with token pasting or stringizing...
    #define AGE 29
    #define SayAGE(a) puts("My age is " #a)

    You can combine the above to your heart's discontent.

    I would also be careful about wanting to remove side effects. Unless
    you're using it for new code, there may be dependencies on those side
    effects in existing code, sad as that may be.

    Good luck!

    - Jay
     
    Jay Nabonne, Oct 14, 2004
    #13
  14. JKop wrote:

    >
    > I was doing some Win32 programming today, having to include the file
    > "windows.h". Anyway, I'm thinking of writing a program that'll work like
    > so:
    >
    > macrodestroyer.exe windows.h
    >
    > What this program will do is scour through the file, replacing all macros
    > with global const variables and inline functions. So for instance, if you
    > have:
    >


    This may be very disturbing for you to learn, but you and I think alike.
    Just this morning I was thinking about something I was calling anti-macros.
    (Kind of like anti-matter, but they won't power a starship.) The idea is
    to replace all your macros with the CPP rendering, but store some kind of
    tag that will reverse the process. Something like this would go around the
    expansion. (There are obvious problems here. It's just a first stab.)

    #pragma macro_begin NAME_OF_MACRO
    The expanded form of the macro goes here.
    #pragma macro_end NAME_OF_MACRO


    The motivation for doing things that way would be to revert to the macro
    form of the code when desired. I even went so far as to muse about
    enhancing the CPP rather than abolishing it ... but that frightened me.

    I have some other ideas, but I will probably put them in the KDevelope whish
    list before I post them here.
    --
    "If our hypothesis is about anything and not about some one or more
    particular things, then our deductions constitute mathematics. Thus
    mathematics may be defined as the subject in which we never know what we
    are talking about, nor whether what we are saying is true." - Bertrand
    Russell
     
    Steven T. Hatton, Oct 15, 2004
    #14
  15. JKop wrote:

    >
    >> That won't work:
    >>
    >> Minus5(10); //error, what about the T parameter?
    >> You need "typeof" or similar. e.g.
    >> template <class T>
    >> typeof(t-5) Minus5(T t)
    >> {
    >> return t-5;
    >> }

    >
    >
    > Can the compiler not determine the return type from the return statement?


    I only wish. The one exception, which I have not explored are the
    conversion operator member functions.

    What am I missing here?
    template <typename T>{ T Minus5(const T& t) { return t - 5;} }



    NOTE: The use of 'class' for template parameters rather than 'typename' was
    extremely confusing to me when first learning C++. I still find it less
    intuitive than using 'typename'.

    NOTE: For formal parameters, I always use 'const type& var' rather than
    simply 'type var'. I don't recall the exact reasoning, but I was once given
    a convincing argument to favor this approach. It has something to do with
    passing literals such as '5'.

    NOTE: I will do:

    template <typename T>{ T f(T t) { return op(t); } } // on one line;

    but not

    for(int i; i < stop; i++) doit(); // no braces

    That last statement would, in my code, be

    for(int i; i < stop; i++) { doit(); }

    It's just too easy to neglect to notice that doit2() in

    for(int i; i < stop; i++)
    doit();
    doit2();

    is not part of the for loop.

    The reason I will put the above example on one line is because it allows me
    to compact my code which often results in easier comparison of closely
    related statements. I wouldn't, however do this:

    template <typename T>{ T f(T t) { op2(t); return op(t); } } // BAD;

    That starts looking like perl.
    --
    "If our hypothesis is about anything and not about some one or more
    particular things, then our deductions constitute mathematics. Thus
    mathematics may be defined as the subject in which we never know what we
    are talking about, nor whether what we are saying is true." - Bertrand
    Russell
     
    Steven T. Hatton, Oct 15, 2004
    #15
  16. Chris Theis wrote:

    > Generally, fumbling with compiler manufacturer's headers are bound to give
    > you or somebody else trouble some day.
    >



    I agree that windoze.h is not something to try second guessing, but I
    believe the general idea of pre-edit macro replacement has (great) merit.
    --
    "If our hypothesis is about anything and not about some one or more
    particular things, then our deductions constitute mathematics. Thus
    mathematics may be defined as the subject in which we never know what we
    are talking about, nor whether what we are saying is true." - Bertrand
    Russell
     
    Steven T. Hatton, Oct 15, 2004
    #16
  17. JKop

    Chris Theis Guest

    "Steven T. Hatton" <> wrote in message
    news:...
    > Chris Theis wrote:
    >
    > > Generally, fumbling with compiler manufacturer's headers are bound to

    give
    > > you or somebody else trouble some day.
    > >

    >
    >
    > I agree that windoze.h is not something to try second guessing, but I
    > believe the general idea of pre-edit macro replacement has (great) merit.



    I absolutely agree with you regarding the merit but I wanted to stress that
    this is all but trivial and might become a monstrous task ;-)

    Cheers
    Chris
     
    Chris Theis, Oct 15, 2004
    #17
  18. JKop

    Chris Theis Guest

    "JKop" <> wrote in message
    news:SXzbd.33448$...
    >
    > I'm going to start off with a broad checklist on this.
    >


    Just some comments & remarks to make you aware of common pitfalls.

    > Obviously first of all, I'll deal with #define statements. Here's the

    kinds:
    >
    >
    > 1) #define DAYS_IN_A_YEAR 365
    >
    > Note: Will become a global const variable of the type of 365.
    >
    >
    > 2) #define LRESULT long
    >
    > Note: Will become a typedef


    It will be crucial how to differentiate between case 1 and 2. The
    straightforward strategy might be to check the second argument of #define
    and if it´s a number then you´ll have a constant. Otherwise a typedef is
    what you´re looking for. But wait for a moment because the world is a little
    more complicated. What about the following nested (and probably spread over
    different files) declaration:

    #define X_VAL 1
    #define AXIS_X X_VAL

    What will be the result of the second #define transformation? You can now
    say - "piece of cake", I´ll only create typedefs if the second argument is a
    token specifying a data-type like int, long, etc. Unfortunately there is
    more trouble in store & especially using the MS windows headers you´ll have
    to face it. Think of the following:

    #define BYTE char
    #define PCHAR BYTE*

    or

    #define BYTE char
    #define MYCHAR BYTE

    Furthermore keep in mind that the respective definitions might be spread
    over different files!

    >
    >
    > 3) #define Minus5(a) (a - 5)
    >
    > Note: Will become an inline function
    >
    >
    > 4) #define WIN32_LEAN_AND_MEAN
    >
    > Note: I'll leave these alone.
    >
    >
    > 5) #define public private
    >
    > Note: A keyword being redefined - there's obviously some sort of

    intentional
    > hack going on here, so I'll leave it alone!
    >


    If you encounter such a hack there is certainly something very wrong
    regarding some design issue ;-)

    >
    >
    > After that:
    >
    > 1) #pragma once
    >
    > Note: Will become inclusion guards.
    >


    That´s a good idea & easy to solve.

    >
    > Any other ideas?
    >
    >
    > Firstly I'm going to decide how I'll turn:
    >
    > #define DAYS_IN_A_YEAR 365
    >
    > into a global const variable. I'll have to devise a way of choosing the
    > right type...
    >


    If you´re really going for it then I wish you good luck and would recommend
    to read up on parsing.

    Cheers
    Chris
     
    Chris Theis, Oct 15, 2004
    #18
  19. JKop wrote:
    >

    [snip]
    >
    > Any other ideas?
    >


    Just a few weeks back I did this:

    #define LoadDLLFunction(name) \
    (*(FARPROC*)&name = GetProcAddress( m_hDLL,#name)); \
    if( name == NULL ) { \
    AfxMessageBox( "DLL does not export:\n" #name ); \
    }

    LoadDLLFunction( func1 );
    LoadDLLFunction( func2 );

    It is used to lookup a function 'func1' in a DLL and store a pointer
    to it in a function pointer variable with the same name as the function.

    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, Oct 15, 2004
    #19
  20. Chris Theis wrote:

    >
    > "Steven T. Hatton" <> wrote in message
    > news:...


    >> I agree that windoze.h is not something to try second guessing, but I
    >> believe the general idea of pre-edit macro replacement has (great) merit.

    >
    >
    > I absolutely agree with you regarding the merit but I wanted to stress
    > that this is all but trivial and might become a monstrous task ;-)


    It depends on what you want to accomplish. If your goal is to be 100%
    comprehensive, you will end up with a rather large file in your edit buffer
    if you have something such as #include <iostream> and a few of your own
    headers as well.

    I'm thinking along the lines of cookie-cutter code. Suppose you want to
    create a unit test framework using a standard format for your test
    functions. I've seen this done using macros. It's how the Boost unit test
    stuff works. Basically you pass as macro arguments things such as the
    names of the functions you want to invoke. These are expanded to use both
    the function and a string representation of the function for output
    purposes, etc. I'd be happy to have a tool along the lines of
    tempotemplates (which will work), rather than CPP macros to do all of this.

    But people do use macros, and they have the advantage (and shortcoming) that
    they can be changed at one point in the code resulting in global changes.
    And they are part of the C++ Standard, so they port.
    --
    "If our hypothesis is about anything and not about some one or more
    particular things, then our deductions constitute mathematics. Thus
    mathematics may be defined as the subject in which we never know what we
    are talking about, nor whether what we are saying is true." - Bertrand
    Russell
     
    Steven T. Hatton, Oct 15, 2004
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dead RAM
    Replies:
    20
    Views:
    1,118
    John Harrison
    Jul 14, 2004
  2. D Senthil Kumar

    macro name from macro?

    D Senthil Kumar, Sep 20, 2003, in forum: C Programming
    Replies:
    1
    Views:
    582
    Jack Klein
    Sep 21, 2003
  3. sounak

    to get macro name from macro value

    sounak, Nov 22, 2005, in forum: C Programming
    Replies:
    17
    Views:
    505
    Mark McIntyre
    Nov 22, 2005
  4. Zed Shaw
    Replies:
    0
    Views:
    112
    Zed Shaw
    Jul 28, 2006
  5. cwdjrxyz
    Replies:
    4
    Views:
    186
    Randy Webb
    May 14, 2006
Loading...

Share This Page