How to get line of text from source file using Preprocessor?

1.9k Views Asked by At

We have a file and a line (__file__, __line__) in it we want to print its contents. Is such thing possible via Preprocessor?

2

There are 2 best solutions below

1
On

Maybe something like this?

#include <stdio.h>

#define DBG(X) printf(__FILE__":%d DBG("#X")\n", __LINE__)

int main ()
{
    DBG(this is a test);
}

This produces the output:

test.cc:7 DBG(this is a test)

Edit: You either have to access the source file, or store the source file. Once you have the file stored, it is trivial to print the proper line. One way:

#define PROGRAM_PRINT_INIT(X) \
    static ProgramPrint pp = ProgramPrint(X)
#define DBG(X) std::cerr << "[" << pp.name << ":" << X << "]" \
                         << pp.file[X] << std::endl

struct ProgramPrint {
    std::string name;
    std::vector<std::string> file;
    ProgramPrint (const char *filename) : name(filename) {
        std::ifstream in(filename);
        std::string line;
        while (getline(in, line)) file.push_back(line);
    }
};

Note that vector indices start at zero, so use DBG() accordingly.

0
On

Yeah, C/C++ are NOT made for that. But this is one suggestion if you really want to see how far you can bend things.

Say you wanted to compile test.cpp to test. We need to prepend a cstring array of source code lines to the source code file before we compile it. We'll do this in a separate file, test_temp.cpp, and we'll call the array TEST_CODE.

Put the following in a file: code.awk (this will make it easier to resuse).

BEGIN {
    for (i = 0; i < 128; i++) {
        table = sprintf("%s%c", table, i);
    }
    print("= {\"\"")
}
{
    printf(",\"")
    for(j=1; j<=length($1); j++) {
        c = substr($1,j,1)
        printf("\\x%x", index(table, c) - 1)
    }
    printf("\"\n")
}
END {
    printf("};\n")
}

By reference a 'table' of ASCII characters, this uses the (hexidecimal) ASCII value for each character (e.g. '\x41' for 'A'), in case of stuff like tabs, etc. that could be in your source code but should be escaped in a C/C++ string literal.

To compile, in the command line (or in your makefile), type

echo "char* TEST_CODE[]" > test_temp.cpp
awk -f code.awk test.cpp >> test_temp.cpp
cat test.cpp >> test_temp.cpp
g++ -o test test_temp.cpp
rm test_temp.cpp

If you wanted to get line 80 of the source code file (1-based), you would write

TEST_CODE[80]

Notes this takes place BEFORE preprocessor commands. This can be done with multiple files and with header files, by changing the array name from TEST_CODE in each case.

This does have holes, but it will work in common cases.

Note: The may be A LOT compiler warnings from g++ because of the char* / string literal conversion, but you can turn those off with the -w flag.