Re: Complete macro expansion with cpp

codeworker@free.fr (Cedric LEMAIRE)
16 Feb 2005 20:50:17 -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:17 -0500
Organization: http://groups.google.com
References: 05-02-059
Keywords: C, macros
Posted-Date: 16 Feb 2005 20:50:17 EST

Sorry, my last post wasn't answering to your question exactly. You
don't want to modify the C file, but rather isolate macro definitions
after applying the expansion.


Now, type:
    codeworker -translate macro_expansion.cwp myFile.c output.txt


With "macro_expansion.cwp" being (#include directives are visited):
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)
                ]
            |
                '#'
                // recursive call into include files
                #readIdentifier:"include"
                #nextStep
                #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)
                substitute_define
        ]
    ]*
    // 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']*
    // write the macro definition in the output file
    => {@#define @sDefine@ @}
    => local iStart = getOutputLocation();
    // what you parse is what you write
    #implicitCopy
    [
            // 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
    ;



Post a followup to this message

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