Re: Complete macro expansion with cpp

codeworker@free.fr (Cedric LEMAIRE)
16 Feb 2005 20:50:07 -0500

          From comp.compilers

Related articles
Complete macro expansion with cpp peter.mathes@gmx.de (2005-02-12)
Re: Complete macro expansion with cpp RLake@oxfam.org.uk (Rici Lake) (2005-02-13)
Re: Complete macro expansion with cpp skandgoe@gwdg.de (Skandinavisches Seminar) (2005-02-13)
Re: Complete macro expansion with cpp codeworker@free.fr (2005-02-16)
Re: Complete macro expansion with cpp codeworker@free.fr (2005-02-16)
Re: Complete macro expansion with cpp peter.mathes@gmx.de (peter.mathes@gmx.de) (2005-02-16)
| List of all articles for this month |

From: codeworker@free.fr (Cedric LEMAIRE)
Newsgroups: comp.compilers
Date: 16 Feb 2005 20:50:07 -0500
Organization: http://groups.google.com
References: 05-02-059
Keywords: C, macros
Posted-Date: 16 Feb 2005 20:50:07 EST

I propose you to use CodeWorker, a parsing tool and a source code
generator, and to run it as a program transformer. CodeWorker is
distributed under LGPL and is available at
"http://www.codeworker.org".


I wrote you the program transformation script for what you are
expecting.


Type:
    codeworker -translate macro_expansion.cwp myFile.c myFile.c




with "macro_expansion.cwp" being:
// what you parse is what you write to the output
#implicitCopy


substitute_define ::=
    // ignore C/C++-like comments and whitespaces
    // between BNF terminals and non-terminals
    #ignore(C++)
    // look for every '#define' in the C file
    [
        ->[
                // be careful! a constant string might
                // have '#define ...' inside!
                #readCString
            |
                '#'
                #readIdentifier:"define"
                // here we are
                #readIdentifier:sDefine
                // do not ignore comments and
                // whitespaces anymore
                #!ignore
                [
                        // do not handle
                        // parameterized macros
                        '('
                        // jump to the end of line
                        // (filtering '\\\n')
                        ->['\\' ['\r']? '\n' #nextStep >heck(false) | '\n']
                    |
                        handle_define(sDefine)
                ]
        ]
    ]*
    // copy the rest of the file
    ->#empty
    ;


// explore the value, modify it if needed and register it
handle_define(sDefine : value) ::=
    // jump to the first non-whitespace character
    [' ' | '\t']*
    => local iStart = getOutputLocation();
    [
            // is the token an identifier?
            #explicitCopy // do not copy what is parsed
            #readIdentifier:sValue
            [
                    // is this identifier a preproc definition?
                    >heck(this.macros.findElement(sValue))
                    // yes, substitute (template-based script)!
                    => { @@this.macros[sValue]@@ }
                |
                    // no, write the word
                    => { @@sValue@@ }
            ]
        |
            // backslash before and end-of-line: continue!
            '\\' ['\r']? '\n'
        |
            // continue while not a regular end-of-line
            ~[['\r']? '\n']
    ]*
    // register the macro, after aventual changes
    => local sValue = getLastWrittenChars($getOutputLocation() -
iStart$);
    // if no value, default is 1
    => if !sValue sValue = 1;
    => insert this.macros[sDefine] = sValue;
    ['\r']? '\n' // consume the end-of-line
    ;






If you want to explore '#include "myInclude.h"' recursively, then
insert the follwing piece of code at line 32:
            |
                #explicitCopy
                '#'
                // recursive call into include files
                #readIdentifier:"include"
                #readCString:sFilename
                // do we find the file amongst include paths?
                >heck(sFilename.existFile())
                // this include was already explored?
                >heck(!this.includes.findElement(sFilename))
                // no! register it as visited, and expand it
                => insert this.includes[sFilename];
                // for the rest of the sequence, change
                // the file to parse
                #parsedFile(sFilename)
                #implicitCopy
                substitute_define
                #implicitCopy




Note: the first time the include file is encountered, it is expanded.


peter.mathes@gmx.de wrote in message news:05-02-059...
> Hallo!
> I need to get all macro #definitions output to stdout or some file.
> The problem is:
> When I pre-process the following lines
>
> #define MACRO1 (1)
> #define MACRO2 (MACRO1)
>
> using cpp with the option '-dM' it outputs the same lines:
>
> #define MACRO1 (1)
> #define MACRO2 (MACRO1)
>
> But I need an output with the macros expanded completely. Something
> like this:
>
> #define MACRO1 (1)
> #define MACRO2 ((1))
>
> Any idea how to get this done?


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.