how to do two-stage preprocessing of one file

Discussion in 'C Programming' started by andreyvul, Nov 12, 2007.

  1. andreyvul

    andreyvul Guest

    What I'm trying to do is have the preprocessor parse one file twice.
    The file has three parts, and each is dependent on the previous.
    Example (file name is foo.c):
    #ifndef ONCE /* first part */
    #define D #define
    #define ONCE
    #include "foo.c"
    #endif
    #ifdef ONCE /* second part */
    D x int
    #ifndef TWICE
    #define TWICE
    #include "foo.c"
    #endif
    #endif
    #ifdef TWICE /* third part */
    x y;
    #endif

    The problem is that the preprocessor just adds the third part to the
    second part, but doesn't preprocess the third part in the process.
    How do I make my #includes and #ifedefs so that the third part will be
    preprocessed?
     
    andreyvul, Nov 12, 2007
    #1
    1. Advertising

  2. In article <>,
    andreyvul <> wrote:
    >What I'm trying to do is have the preprocessor parse one file twice.


    You cannot do that using the facilities defined by the C preprocessor.

    Your particular implementation -probably- offers a way to
    preprocess files. For example, on the system I am using at the
    moment, the sequence would look something like,

    cc -P myfile.c
    mv myfile.i myfile_preprocessed.c
    cc -o outputfile myfile_preprocessed.c

    But it would also not be uncommon on a Unix system for the sequence
    to look something closer to

    cc -E myfile.c | egrep -v '^#line' > myfile_preprocessed.c
    cc -o outfile myfile_preprocessed.c

    Many unix C compilers offer some option as in the second example,
    to preprocess and send the result to standard output; it may
    or may not be necessary in your toolchain to remove #line directives
    from the preprocessed output before you can push the file back
    through the C parseer.

    If you are using one of the Windows compilers... there is probably
    some similar option, but probably not named -P or -E .
    --
    "Is there any thing whereof it may be said, See, this is new? It hath
    been already of old time, which was before us." -- Ecclesiastes
     
    Walter Roberson, Nov 13, 2007
    #2
    1. Advertising

  3. andreyvul

    andreyvul Guest

    On Nov 12, 7:11 pm, -cnrc.gc.ca (Walter Roberson)
    wrote:
    > In article <>,
    >
    > andreyvul <> wrote:
    > >What I'm trying to do is have the preprocessor parse one file twice.

    >
    > You cannot do that using the facilities defined by the C preprocessor.

    Oh, I meant _recursively_ preprocess the file twice.
    That's why I was asking about proper #include/#ifdef structure, so
    that it preprocesses like this:

    #block 1
    |->#block 2 (via recursive include)
    |->#block 3 (via recursive include)

    however, it doesn't get to |->#block 3
     
    andreyvul, Nov 13, 2007
    #3
  4. andreyvul

    Ark Khasin Guest

    andreyvul wrote:
    > On Nov 12, 7:11 pm, -cnrc.gc.ca (Walter Roberson)
    > wrote:
    >> In article <>,
    >>
    >> andreyvul <> wrote:
    >>> What I'm trying to do is have the preprocessor parse one file twice.

    >> You cannot do that using the facilities defined by the C preprocessor.

    > Oh, I meant _recursively_ preprocess the file twice.
    > That's why I was asking about proper #include/#ifdef structure, so
    > that it preprocesses like this:
    >
    > #block 1
    > |->#block 2 (via recursive include)
    > |->#block 3 (via recursive include)
    >
    > however, it doesn't get to |->#block 3
    >

    I didn't try it but something along these lines might do it:

    #ifndef REC_COUNT
    #define REC_COUNT 2
    #elif REC_COUNT == 2
    #undef REC_COUNT
    #define REC_COUNT 1
    #elif REC_COUNT == 1
    #undef REC_COUNT
    #define REC_COUNT 0
    #endif
    /* Here is the meat */
    #if REC_COUNT == 2
    /* first iteration */
    #elif REC_COUNT == 1
    /* second iteration */
    #else
    /* third and last iteration */
    #if REC_COUNT != 0
    #include __FILE__
    #endif

    --
    Ark
     
    Ark Khasin, Nov 13, 2007
    #4
  5. In article <>,
    andreyvul <> wrote:
    >On Nov 12, 7:11 pm, -cnrc.gc.ca (Walter Roberson)
    >wrote:
    >> In article <>,


    >> andreyvul <> wrote:
    >> >What I'm trying to do is have the preprocessor parse one file twice.


    >> You cannot do that using the facilities defined by the C preprocessor.


    >Oh, I meant _recursively_ preprocess the file twice.


    Oh, in that case, let me correct my statement:

    The facilities of the C preprocessor are defined in such a way that
    you are not guaranteed to be able to do this; if you were able to
    get it to work at all, it would be due to implementation-dependant
    behaviour.
    --
    "History is a pile of debris" -- Laurie Anderson
     
    Walter Roberson, Nov 13, 2007
    #5
  6. andreyvul

    andreyvul Guest

    On Nov 12, 7:58 pm, Ark Khasin <> wrote:
    > andreyvul wrote:
    > > On Nov 12, 7:11 pm, -cnrc.gc.ca (Walter Roberson)
    > > wrote:
    > >> In article <>,

    >
    > >> andreyvul <> wrote:
    > >>> What I'm trying to do is have the preprocessor parse one file twice.
    > >> You cannot do that using the facilities defined by the C preprocessor.

    > > Oh, I meant _recursively_ preprocess the file twice.
    > > That's why I was asking about proper #include/#ifdef structure, so
    > > that it preprocesses like this:

    >
    > > #block 1
    > > |->#block 2 (via recursive include)
    > > |->#block 3 (via recursive include)

    >
    > > however, it doesn't get to |->#block 3

    >
    > I didn't try it but something along these lines might do it:
    >
    > #ifndef REC_COUNT
    > #define REC_COUNT 2
    > #elif REC_COUNT == 2
    > #undef REC_COUNT
    > #define REC_COUNT 1
    > #elif REC_COUNT == 1
    > #undef REC_COUNT
    > #define REC_COUNT 0
    > #endif
    > /* Here is the meat */
    > #if REC_COUNT == 2
    > /* first iteration */
    > #elif REC_COUNT == 1
    > /* second iteration */
    > #else
    > /* third and last iteration */
    > #if REC_COUNT != 0
    > #include __FILE__
    > #endif
    >
    > --
    > Ark


    Nope, doesn't work.

    Great, I have now figured out it is impossible to recursively
    preprocess more than one level. Is this supposed to happen per ANSI
    specs, or should I go to the cpp newsgroup?
     
    andreyvul, Nov 13, 2007
    #6
  7. andreyvul

    andreyvul Guest

    And I got it to work now:
    cc foo.c -E | sed -re '/#[^di]/D' -e /^$/D' | head -7 | cc -x c - -o
    foo
    Kind of impossible on windows without GnuWin32, msys, or cygwin.
     
    andreyvul, Nov 13, 2007
    #7
  8. andreyvul

    Ark Khasin Guest

    andreyvul wrote:
    > On Nov 12, 7:58 pm, Ark Khasin <> wrote:
    >> andreyvul wrote:
    >>> On Nov 12, 7:11 pm, -cnrc.gc.ca (Walter Roberson)
    >>> wrote:
    >>>> In article <>,
    >>>> andreyvul <> wrote:
    >>>>> What I'm trying to do is have the preprocessor parse one file twice.
    >>>> You cannot do that using the facilities defined by the C preprocessor.
    >>> Oh, I meant _recursively_ preprocess the file twice.
    >>> That's why I was asking about proper #include/#ifdef structure, so
    >>> that it preprocesses like this:
    >>> #block 1
    >>> |->#block 2 (via recursive include)
    >>> |->#block 3 (via recursive include)
    >>> however, it doesn't get to |->#block 3

    >> I didn't try it but something along these lines might do it:
    >>
    >> #ifndef REC_COUNT
    >> #define REC_COUNT 2
    >> #elif REC_COUNT == 2
    >> #undef REC_COUNT
    >> #define REC_COUNT 1
    >> #elif REC_COUNT == 1
    >> #undef REC_COUNT
    >> #define REC_COUNT 0
    >> #endif
    >> /* Here is the meat */
    >> #if REC_COUNT == 2
    >> /* first iteration */
    >> #elif REC_COUNT == 1
    >> /* second iteration */
    >> #else
    >> /* third and last iteration */
    >> #if REC_COUNT != 0
    >> #include __FILE__
    >> #endif
    >>
    >> --
    >> Ark

    >
    > Nope, doesn't work.
    >
    > Great, I have now figured out it is impossible to recursively
    > preprocess more than one level. Is this supposed to happen per ANSI
    > specs, or should I go to the cpp newsgroup?
    >

    You didn't try hard enough :). The text I posted was not #balanced.
    Here's a working example:
    ------------- iter.c -------------
    #include <stdio.h>
    int main()
    {
    #include "iter.h"
    return 0;
    }
    ------------- iter.h -------------
    #ifndef REC_COUNT
    # define REC_COUNT 2
    /* first iteration */
    puts("first iteration");
    #elif REC_COUNT == 2
    # undef REC_COUNT
    # define REC_COUNT 1
    /* second iteration */
    puts("second iteration");
    #elif REC_COUNT == 1
    # undef REC_COUNT
    # define REC_COUNT 0
    /* third and last iteration */
    puts("third and last iteration");
    #endif
    #if REC_COUNT != 0
    # include __FILE__
    #endif
    ------------ output --------------------
    first iteration
    second iteration
    third and last iteration

    .... which also disproves a claim of a nearby post that it's impossible.
    In fact, you can do recursion of any fixed depth this way.
    Unless of course I misunderstood what you were trying to achieve.

    --
    Ark
     
    Ark Khasin, Nov 13, 2007
    #8
  9. andreyvul

    andreyvul Guest

    On Nov 12, 9:54 pm, Ark Khasin <> wrote:
    > andreyvul wrote:
    > > On Nov 12, 7:58 pm, Ark Khasin <> wrote:
    > >> andreyvul wrote:
    > >>> On Nov 12, 7:11 pm, -cnrc.gc.ca (Walter Roberson)
    > >>> wrote:
    > >>>> In article <>,
    > >>>> andreyvul <> wrote:
    > >>>>> What I'm trying to do is have the preprocessor parse one file twice.
    > >>>> You cannot do that using the facilities defined by the C preprocessor.
    > >>> Oh, I meant _recursively_ preprocess the file twice.
    > >>> That's why I was asking about proper #include/#ifdef structure, so
    > >>> that it preprocesses like this:
    > >>> #block 1
    > >>> |->#block 2 (via recursive include)
    > >>> |->#block 3 (via recursive include)
    > >>> however, it doesn't get to |->#block 3
    > >> I didn't try it but something along these lines might do it:

    >
    > >> #ifndef REC_COUNT
    > >> #define REC_COUNT 2
    > >> #elif REC_COUNT == 2
    > >> #undef REC_COUNT
    > >> #define REC_COUNT 1
    > >> #elif REC_COUNT == 1
    > >> #undef REC_COUNT
    > >> #define REC_COUNT 0
    > >> #endif
    > >> /* Here is the meat */
    > >> #if REC_COUNT == 2
    > >> /* first iteration */
    > >> #elif REC_COUNT == 1
    > >> /* second iteration */
    > >> #else
    > >> /* third and last iteration */
    > >> #if REC_COUNT != 0
    > >> #include __FILE__
    > >> #endif

    >
    > >> --
    > >> Ark

    >
    > > Nope, doesn't work.

    >
    > > Great, I have now figured out it is impossible to recursively
    > > preprocess more than one level. Is this supposed to happen per ANSI
    > > specs, or should I go to the cpp newsgroup?

    >
    > You didn't try hard enough :). The text I posted was not #balanced.
    > Here's a working example:
    > ------------- iter.c -------------
    > #include <stdio.h>
    > int main()
    > {
    > #include "iter.h"
    > return 0;}
    >
    > ------------- iter.h -------------
    > #ifndef REC_COUNT
    > # define REC_COUNT 2
    > /* first iteration */
    > puts("first iteration");
    > #elif REC_COUNT == 2
    > # undef REC_COUNT
    > # define REC_COUNT 1
    > /* second iteration */
    > puts("second iteration");
    > #elif REC_COUNT == 1
    > # undef REC_COUNT
    > # define REC_COUNT 0
    > /* third and last iteration */
    > puts("third and last iteration");
    > #endif
    > #if REC_COUNT != 0
    > # include __FILE__
    > #endif
    > ------------ output --------------------
    > first iteration
    > second iteration
    > third and last iteration
    >
    > ... which also disproves a claim of a nearby post that it's impossible.
    > In fact, you can do recursion of any fixed depth this way.
    > Unless of course I misunderstood what you were trying to achieve.
    >
    > --
    > Ark


    What if you had a macro in the third iteration that was to be expanded
    by the previous iterations?
     
    andreyvul, Nov 13, 2007
    #9
  10. andreyvul

    andreyvul Guest

    On Nov 12, 9:54 pm, Ark Khasin <> wrote:
    > andreyvul wrote:
    > > On Nov 12, 7:58 pm, Ark Khasin <> wrote:
    > >> andreyvul wrote:
    > >>> On Nov 12, 7:11 pm, -cnrc.gc.ca (Walter Roberson)
    > >>> wrote:
    > >>>> In article <>,
    > >>>> andreyvul <> wrote:
    > >>>>> What I'm trying to do is have the preprocessor parse one file twice.
    > >>>> You cannot do that using the facilities defined by the C preprocessor.
    > >>> Oh, I meant _recursively_ preprocess the file twice.
    > >>> That's why I was asking about proper #include/#ifdef structure, so
    > >>> that it preprocesses like this:
    > >>> #block 1
    > >>> |->#block 2 (via recursive include)
    > >>> |->#block 3 (via recursive include)
    > >>> however, it doesn't get to |->#block 3
    > >> I didn't try it but something along these lines might do it:

    >
    > >> #ifndef REC_COUNT
    > >> #define REC_COUNT 2
    > >> #elif REC_COUNT == 2
    > >> #undef REC_COUNT
    > >> #define REC_COUNT 1
    > >> #elif REC_COUNT == 1
    > >> #undef REC_COUNT
    > >> #define REC_COUNT 0
    > >> #endif
    > >> /* Here is the meat */
    > >> #if REC_COUNT == 2
    > >> /* first iteration */
    > >> #elif REC_COUNT == 1
    > >> /* second iteration */
    > >> #else
    > >> /* third and last iteration */
    > >> #if REC_COUNT != 0
    > >> #include __FILE__
    > >> #endif

    >
    > >> --
    > >> Ark

    >
    > > Nope, doesn't work.

    >
    > > Great, I have now figured out it is impossible to recursively
    > > preprocess more than one level. Is this supposed to happen per ANSI
    > > specs, or should I go to the cpp newsgroup?

    >
    > You didn't try hard enough :). The text I posted was not #balanced.
    > Here's a working example:
    > ------------- iter.c -------------
    > #include <stdio.h>
    > int main()
    > {
    > #include "iter.h"
    > return 0;}
    >
    > ------------- iter.h -------------
    > #ifndef REC_COUNT
    > # define REC_COUNT 2
    > /* first iteration */
    > puts("first iteration");
    > #elif REC_COUNT == 2
    > # undef REC_COUNT
    > # define REC_COUNT 1
    > /* second iteration */
    > puts("second iteration");
    > #elif REC_COUNT == 1
    > # undef REC_COUNT
    > # define REC_COUNT 0
    > /* third and last iteration */
    > puts("third and last iteration");
    > #endif
    > #if REC_COUNT != 0
    > # include __FILE__
    > #endif
    > ------------ output --------------------
    > first iteration
    > second iteration
    > third and last iteration
    >
    > ... which also disproves a claim of a nearby post that it's impossible.
    > In fact, you can do recursion of any fixed depth this way.
    > Unless of course I misunderstood what you were trying to achieve.
    >
    > --
    > Ark


    What if you have a macro in the third iteration that needs expanding
    in the second iteration, which needs expanding in the first iteration?
    *That* was what I was trying to do.
     
    andreyvul, Nov 13, 2007
    #10
  11. andreyvul

    andreyvul Guest

    Here's an example of what I mean:
    #ifndef REC
    #define REC 2
    #define d #define
    #define i include
    #elif REC == 2
    #undef REC
    #define REC 1
    i <stdio.h>
    d p(a) puts(a)
    d q(a) int a
    d Q main
    d r(a) char**a
    #elif REC == 1
    #undef REC
    #define REC 0
    q(Q)(q(c), r(v)){p("Hello, World!\n");return 0;}
    #endif
    #if REC != 0
    #include __FILE__
    #endif

    Should produce:
    [stdio.h]
    int main(int c, char**v){puts("Hello, World!\n"); return 0;}
     
    andreyvul, Nov 13, 2007
    #11
  12. andreyvul

    Ark Khasin Guest

    andreyvul wrote:
    > Here's an example of what I mean:
    > #ifndef REC
    > #define REC 2
    > #define d #define
    > #define i include
    > #elif REC == 2
    > #undef REC
    > #define REC 1
    > i <stdio.h>
    > d p(a) puts(a)
    > d q(a) int a
    > d Q main
    > d r(a) char**a
    > #elif REC == 1
    > #undef REC
    > #define REC 0
    > q(Q)(q(c), r(v)){p("Hello, World!\n");return 0;}
    > #endif
    > #if REC != 0
    > #include __FILE__
    > #endif
    >
    > Should produce:
    > [stdio.h]
    > int main(int c, char**v){puts("Hello, World!\n"); return 0;}
    >

    THAT you should not even attempt to do. It's a tad late to find quotes
    from the standard, but basically:
    - # in a context of macro definition means STRINGIZE when applied to a
    macro argument; I doubt other uses are meaningful or valid
    - you cannot (re)define preprocessor directives
    So it is not valid C.

    This is what you are doing:
    - You deliberately take a bad (i.e. invalid) C-like source,
    - You massage it to automatically produce a valid C source and run with it.
    If that's what you want, you can use an arbitrary pair of source
    language style and a corresponding preprocessor utility; that has
    nothing to do with C.

    YOU CAN, however, process your file in every which way you like, as you
    demonstrated in this thread. Attempting to coerce a C compiler to do
    preprocessing is not a terribly good idea. I'd suggest to use a
    standalone PP that gives you some guarantees of what it outputs. (Google
    them C preprocessors.) Or use a specific compiler you know suits your needs.
    Keep in mind that:
    - the compiler is under no obligation to produce preprocessor output.
    - if the compiler does produce PP output, it may turn bad source into a
    perfectly good source; I used to have a vivid example of that around
    #define SLASH /
    something /SLASH alleged comment
    but I lost it. Basically, PP found a token /, then a token SLASH which
    it expanded to / and output //. It compiles as start of comment (a
    single token //) but in the original source they were, effectively, two
    / tokens. One might argue that PP should have produced / / but then
    again, the compiler owes me nothing in that department.

    If my hunch is correct and all you are trying to do is to obfuscate your
    code, there are better ways of doing so.

    --
    Ark
     
    Ark Khasin, Nov 13, 2007
    #12
    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. Anoops
    Replies:
    1
    Views:
    632
    navneetcertain
    Aug 1, 2013
  2. Anoops
    Replies:
    0
    Views:
    517
    Anoops
    Sep 9, 2005
  3. Brian Folke Seaberg

    Initialization -- One Stage or Two Stage

    Brian Folke Seaberg, Jan 4, 2005, in forum: C++
    Replies:
    4
    Views:
    726
    Howard
    Jan 4, 2005
  4. andreyvul

    how to do two-stage preprocessing of one file

    andreyvul, Nov 12, 2007, in forum: C Programming
    Replies:
    1
    Views:
    328
    santosh
    Nov 13, 2007
  5. Pedro Graca

    calculations in the preprocessing stage

    Pedro Graca, Feb 18, 2008, in forum: C Programming
    Replies:
    6
    Views:
    289
    Ben Bacarisse
    Feb 19, 2008
Loading...

Share This Page