macros that build macros

Discussion in 'C Programming' started by Thant Tessman, Sep 11, 2007.

  1. Back before C++ templates, I was taught a trick whereby one built C
    macros that built other C macros. I can't remember how the heck we did
    it. The problem is that there seems to be no standard way to include a
    '#' or '#define' in the output of a macro. The other problem is that we
    might have been using some sort of non-standard preprocessor trick to do it.

    Obliged if anyone can point me in the right direction or tell me what
    I'm trying to do is impossible.

    -thant
    Thant Tessman, Sep 11, 2007
    #1
    1. Advertising

  2. Thant Tessman

    Guest

    On Sep 11, 11:08 am, Thant Tessman <> wrote:
    > Back before C++ templates, I was taught a trick whereby one built C
    > macros that built other C macros. I can't remember how the heck we did
    > it. The problem is that there seems to be no standard way to include a
    > '#' or '#define' in the output of a macro. The other problem is that we
    > might have been using some sort of non-standard preprocessor trick to do it.
    >
    > Obliged if anyone can point me in the right direction or tell me what
    > I'm trying to do is impossible.
    >
    > -thant


    It is impossible, according to the standard (paragraph 3 of 6.10.3.4
    "Rescanning and further replacement")

    "The resulting completely macro-replaced preprocessing token sequence
    is not processed
    as a preprocessing directive even if it resembles one, but all pragma
    unary operator
    expressions within it are then processed as specified in 6.10.9
    below."

    In other words, you cannot create preprocessor directives using macro
    replacement. Of course, the compiler you were using in the past may
    have had a non-standard extension which may have allowed such
    behaviour

    Regards,
    B
    , Sep 11, 2007
    #2
    1. Advertising

  3. Thant Tessman

    Jack Klein Guest

    On Mon, 10 Sep 2007 19:08:16 -0600, Thant Tessman
    <> wrote in comp.lang.c:

    >
    > Back before C++ templates, I was taught a trick whereby one built C
    > macros that built other C macros. I can't remember how the heck we did
    > it. The problem is that there seems to be no standard way to include a
    > '#' or '#define' in the output of a macro. The other problem is that we
    > might have been using some sort of non-standard preprocessor trick to do it.
    >
    > Obliged if anyone can point me in the right direction or tell me what
    > I'm trying to do is impossible.
    >
    > -thant


    "borophyll" already gave you the standard answer, that you cannot
    directly generate a macro to be replaced in the expansion of another
    macro.

    There are other ways, depending on what it is you are trying to do,
    which you haven't made clear. Show us an example of the macro you
    would like to generate, and the other macros that you would like to
    use in the generation. It might be possible.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Sep 11, 2007
    #3
  4. Thant Tessman

    Guest

    On Sep 10, 8:08 pm, Thant Tessman <> wrote:
    > Back before C++ templates, I was taught a trick whereby one built C
    > macros that built other C macros. I can't remember how the heck we did
    > it. The problem is that there seems to be no standard way to include a
    > '#' or '#define' in the output of a macro. The other problem is that we
    > might have been using some sort of non-standard preprocessor trick to do it.
    >
    > Obliged if anyone can point me in the right direction or tell me what
    > I'm trying to do is impossible.



    While it's not possible in general, sometimes people run C source code
    through the preprocessor twice before the compiler proper. That way
    any generated #defines in the first preprocessor pass get expanded in
    the second.

    There's no standard way of doing that, but many compilers have an
    option to stop after the preprocessing phase and to emit that code.
    Some compilers implement the preprocessor as a separate program, which
    you can run manually. Again, all well outside the scope of the
    standard.
    , Sep 11, 2007
    #4
  5. Thant Tessman

    Guest

    On Sep 11, 3:08 am, Thant Tessman <> wrote:
    > Back before C++ templates, I was taught a trick whereby one built C
    > macros that built other C macros. I can't remember how the heck we did
    > it. The problem is that there seems to be no standard way to include a
    > '#' or '#define' in the output of a macro. The other problem is that we
    > might have been using some sort of non-standard preprocessor trick to do it.
    >
    > Obliged if anyone can point me in the right direction or tell me what
    > I'm trying to do is impossible.


    As indicated by others it is not possible to do this using the
    standard preprocessor and compiler, you need to run the preprocessor
    more than once.

    A preprocessor that I used for something like this is GPP (http://
    en.nothingisreal.com/wiki/GPP), which is a general purpose
    preprocessor. Next to the standard evaluation rules that CPP uses it
    also defines a 2-pass evaluation. This is from the manual page:

    #defeval x y
    This acts in a similar way to #define, but the second argument y is
    evaluated immediately. Since user macro definitions are also evaluated
    each time they are called, this means that the macro y will undergo
    two successive evaluations.

    Kind regards,
    Johan Borkhuis
    , Sep 11, 2007
    #5
  6. I (Thant Tessman) wrote:

    > Back before C++ templates, I was taught a trick whereby one built C
    > macros that built other C macros. I can't remember how the heck we did
    > it. [...]


    My thanks to all who replied. For the curious, the basic form of what
    I'm trying to do is this:

    #define FOO(A,B) stuff

    should produce another macro:

    #define BAR_A_B(C) stuff

    The macros produce code in support of type-safe inter-process message
    passing routines.

    This is definitely a situation where it would be inappropriate to
    deviate from the standard, and the workaround is simple enough:

    #define FOO(A,B) stuff
    #define BAR(A,B,C) more stuff

    The reason this solution is less desirable is that the latter allows for
    errors that the former would catch. But it's workable.

    Again, thanks for the replies.

    -thant
    Thant Tessman, Sep 11, 2007
    #6
  7. Thant Tessman

    Dave Hansen Guest

    On Sep 11, 7:24 am, Thant Tessman <> wrote:
    [...]
    > My thanks to all who replied. For the curious, the basic form of what
    > I'm trying to do is this:
    >
    > #define FOO(A,B) stuff
    >
    > should produce another macro:
    >
    > #define BAR_A_B(C) stuff
    >
    > The macros produce code in support of type-safe inter-process message
    > passing routines.
    >
    > This is definitely a situation where it would be inappropriate to
    > deviate from the standard, and the workaround is simple enough:
    >
    > #define FOO(A,B) stuff
    > #define BAR(A,B,C) more stuff
    >
    > The reason this solution is less desirable is that the latter allows for
    > errors that the former would catch. But it's workable.


    It's not really clear to me what you're trying to do. But I've used
    sort of a backwards means of doing something similar. Consider the
    following macros:

    #define BIT(p,b) (b)

    #define PORT(p,b) (PORT ## p)
    #define PIN(p,b) (PIN ## p)
    #define DDR(p,b) (DDR ## p)

    #define MASK(b) (1 << (b))

    #define Set_Port_Bit(p,b) ((p) |= MASK(b))
    #define Clr_Port_Bit(p,b) ((p) &= ~MASK(b))
    #define Tgl_Port_Bit(p,b) ((p) ^= MASK(b))

    #define Get_Port_Bit(p,b) (((p) & MASK(b)) != 0)

    #define Set_Output(io) Set_Port_Bit(PORT(io),BIT(io))
    #define Reset_Output(io) Clr_Port_Bit(PORT(io),BIT(io))

    #define Get_Input(io) Get_Port_Bit(PIN(io),BIT(io))

    #define Tristate(io) Clr_Port_Bit(DDR(io),BIT(io))
    #define Drive(io) Set_Port_Bit(DDR(io),BIT(io))

    This was for an AVR microprocessor. There were for digital I/O ports,
    a, B, C, and D. There were three I/O address for each digital I/O
    port, PIN for reading input, PORT for writing output, and DDR (Data
    Direction Register) to set each bit to be an input or an output. The
    name of each register was appended with the port it referred to, e.g.,
    PORTA, DDRB, PIND.

    The macros above let me specify my output bits something like this

    #define STATUS_LED A,7
    #define SWITCH(n) D,(n+3) // switches on D3, D4, and D5

    Then I could invoke the macros something like

    Set_Output(STATUS_LED);
    state = Get_Input(SWITCH(1));

    If the hardware changes, and the status LED moved to port B, pin 3,
    all I have to do is change the STATUS_LED definition to

    #define STATUS_LED B,3

    and everything works.

    Perhaps you can adapt something like this.

    Regards,

    -=Dave
    Dave Hansen, Sep 11, 2007
    #7
    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. Replies:
    80
    Views:
    2,360
    Stephen J. Bevan
    Nov 7, 2003
  2. Replies:
    1
    Views:
    429
    Marco Antoniotti
    Oct 7, 2003
  3. Replies:
    5
    Views:
    483
  4. Michael T. Babcock

    Re: Explanation of macros; Haskell macros

    Michael T. Babcock, Nov 3, 2003, in forum: Python
    Replies:
    0
    Views:
    505
    Michael T. Babcock
    Nov 3, 2003
  5. Andrew Arro

    macros-loop? calling macros X times?

    Andrew Arro, Jul 23, 2004, in forum: C Programming
    Replies:
    2
    Views:
    479
    S.Tobias
    Jul 24, 2004
Loading...

Share This Page