Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run preprocessor only but with only for certain statements

I have a number of debug statements defined in a program, and I want to be able to make a copy of the source without these statements.

In order to do this I first looked at GCC's -E command line argument, which only runs the preprocessor, however this did far more than I wanted, expanding the included files and adding #line statements.

For example:

#include <stdio.h>

#ifdef DEBUG
    #define debug( s ) puts ( s );
#else
    #define debug( s )
#endif

int main( int argc, char* argv[] )
{
    debug( "Foo" )

    puts( "Hello, World!" );

    return 0;
}

I'd want this to be processed to:

#include <stdio.h>

int main( int argc, char* argv[] )
{


    puts( "Hello, World!" );

    return 0;
}

I could then tidy that up with something like astyle and no manual work would be needed to get exactly what I want.

Is there a directive I'm missing for GCC or is there a tool capable of doing this?

like image 835
Matt Avatar asked Jan 03 '12 13:01

Matt


People also ask

What does ## mean in C preprocessor?

The double-number-sign or token-pasting operator (##), which is sometimes called the merging or combining operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token, and therefore, can't be the first or last token in the macro definition.

Can GCC output C code after preprocessing?

Yes. Pass gcc the -E option. This will output preprocessed source code.

What is the use of #define preprocessor?

Preprocessor directives, such as #define and #ifdef , are typically used to make source programs easy to change and easy to compile in different execution environments. Directives in the source file tell the preprocessor to take specific actions.

Which statement is executed by preprocessor?

Preprocessor programs provide preprocessor directives that tell the compiler to preprocess the source code before compiling. All of these preprocessor directives begin with a '#' (hash) symbol. The '#' symbol indicates that whatever statement starts with a '#' will go to the preprocessor program to get executed.


2 Answers

If -E is not helping, then try using -fdump-tree-all and if you don't see what you want the that is not-available-in (or) not-provided-by GCC.

OTOH, this question has been discussed in SO as follows, please refer the below to get some ideas.

  1. Can gcc output C code after preprocessing?
  2. How do I see a C/C++ source file after preprocessing in Visual Studio?

Hope it helps!


Hi Mat,

I saw your comment to @nos. But I have one such script handy and so sharing it with you. You can try reading my answer for a similar question here

Copy the below code in a file, say convert.sh. Assign execute permission to that file, chmod +x convert.sh and run it as follows:

$./convert.sh <filename>.c
$cat filename.c.done

The <filename>.c.done will have what you need!

#!/bin/bash

if [[ $# -ne 1 || ! -f $1 ]] ; then
    echo "Invalid args / Check file "
    exit 
fi

file_name=$1

grep '^\s*#\s*include' $file_name > /tmp/include.c
grep -Pv '^\s*#\s*include\b' $file_name > /tmp/code.c
gcc -E /tmp/code.c | grep -v ^# > /tmp/preprocessed.c
cat /tmp/include.c > $file_name.done
cat /tmp/preprocessed.c >> $file_name.done

Hope this helps!

like image 100
Sangeeth Saravanaraj Avatar answered Oct 25 '22 01:10

Sangeeth Saravanaraj


gcc -E -nostdinc test.c produces

# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
# 9 "test.c"
int main( int argc, char* argv[] )
{


    puts( "Hello, World!" );

    return 0;
}

and an error to stderr

test.c:1:19: error: no include path in which to search for stdio.h

You can easily filter out the # lines ... and re-add the includes.

like image 45
pmg Avatar answered Oct 25 '22 00:10

pmg