(your question is not exactly duplicate of this because you also want to output line & source file information, à la __FILE__
and __LINE__
, and that makes a significant difference; however I feel that your question is a bit too broad and is lacking details)
customizing your compiler
You might customize a recent GCC compiler to do what you wish using GCC MELT (which I have designed & implemented). You'll then code an additional "optimization pass" which would magically transform your std::cout <<
... output statements (inside the compiler) adding some builtin expressions by making them the equivalent of std::cout << __builtin_FILE () << ' ' << __builtin_LINE () << ' ' <<
....; you'll need to make the appropriate transformation at the Gimple level.
It is probably not a trivial task, since you'll need to understand the details of GCC internal representations. Therefore, I'm not entirely sure it is worthwhile (unless your code base has at least half a millions of source code line, and spending a couple of weeks to write your MELT customization is worthwhile).
If you can afford to manually edit every relevant line, a macro approach like here is perhaps simpler.
You could perhaps combine both, using MELT to detect the right lines to edit and feed them into a sed
script transforming your source code to invoke a macro.
why the transformation is not simple
Internally, a compiler works on some internal representation which is a normalized AST, or even something simpler (Gimple). For GCC, you want to transform the internal representation of
extern "C" void testit(int x) {
if (x>0)
std::cout << "x=" << x << std::endl;
}
into something close to the internal representation of
extern "C" void transformed_testit (int x) {
if (x>0)
std::cout << __builtin_FILE() << ' ' << __builtin_LINE() << ' '
<< "x=" << x << std::endl;
}
To understand the Gimple representation, compile these with g++ -fdump-tree-gimple
; here is the textual dump of the Gimple code of the first function (actually, Gimple is only an in-memory data structure):
void testit(int) (int x)
{
struct basic_ostream & D.21753;
struct basic_ostream & D.21754;
if (x > 0) goto <D.21751>; else goto <D.21752>;
<D.21751>:
D.21753 = std::operator<< <std::char_traits<char> > (&cout, "x=");
D.21754 = std::basic_ostream<char>::operator<< (D.21753, x);
std::basic_ostream<char>::operator<< (D.21754, endl);
goto <D.21755>;
<D.21752>:
<D.21755>:
}
why you need to work inside the compiler
Because your source code may contains such output in many variants, including
std::cout << "x=" << x << std::endl;
or
using namespace std;
cout << "x=" << x << endl;
or
#define MY_LOG(Out) do{std::cout<<Out<<std::endl;} while(0)
MY_LOG("x=" << x);
or even
auto& output = std::cout;
output << "x=" << x << std::endl;
(in the examples above, the two lines of code might be very far apart, or even in different files, e.g. the #define MY_LOG
in some header file, and used in some implementation file... But the Gimple representation would be very similar in all cases)
hence a purely textual or syntactic approach won't always work, and you need a complex tool, similar to a compiler, to do the transform.
So, if you can afford spending at least two weeks of your work to solve your issue, try using GCC MELT. Otherwise, run manually some sed
script, or code your Emacs function to do that edit interactively
cheating in C++
Maybe you might have
struct myoutputat {
const char*fil;
int lin;
myoutputat(const char*f, int l) : fil(f), lin(l) {};
std::ofstream& operator << (const char*msg) {
std::cout << f << ' ' << l << msg;
return std::cout;
}
}; // end of myoutputat
#define mycout myoutputat(__FILE__,__LINE__)
then you might do
mycout << "x=" << x << std::endl;
Hence you could try #define cout mycout
after the #define mycout
...; it probably would spill many error messages, and you could manually tweak the code at their location
PS. You can contact me by private email to basile@starynkevitch.net
but then please mention the URL of your question and give much more details: what is your code doing, what is its source size, what exact compiler you are using, what is your employer & country, etc...