Add FUNCTION, LINE, time information to all existing “couts” [duplicate]

六眼飞鱼酱① 提交于 2019-12-12 02:39:17

问题


I already have a large code base that uses a lot of couts. I cannot go and change all the existing couts. Is there something I can do so that, the existing couts add FUNCTION , LINE and time information along with what needs to be printed in the cout? In otherwords can I override cout to use my implementationwhich will print the string along with all the extra information. I am open to doing anything else too, not necessarily overriding..

Maybe I didnt explain clearly.. This is what I need. I already have stuff like,

cout<<"This thing does not work"; <-- In A.cpp

cout<<"This thing does works but the problem is XYZ"; <-- In B.cpp

cout<<"There was a problem reading JHI"; <-- In C.cpp

. . and so on..

in a large code base in which I CANNOT edit all the existing couts..

I would need these couts to print something similar to..

cout<<"This thing does not work"<<__FUNCTION__<<__LINE__; <-- In A.cpp

cout<<"This thing does works but the problem is XYZ"<<__FUNCTION__<<__LINE__; <-- In B.cpp

cout<<"There was a problem reading JHI"<<__FUNCTION__<<__LINE__; <-- In C.cpp . .

Hope this makes it clearer.. I want the original couts to be AUTOMATICALLY(by doing some trick maybe) transformed so that they also print this extra information..


回答1:


(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...




回答2:


The obvious solution would be to use some editor macro, such as vim's macros paired with a grep -rnw 'directory' -e "cout <<", assuming a Linux platform.

Regarding C++, if you are using cout and not std::cout throughout your code, then a possible solution would be to remove your using namespace std and then rollout your own cout function - assuming you don't have other code depending on std:: which will break.

The question which has been marked as a duplicate, might contain an answer to your problem.



来源:https://stackoverflow.com/questions/34952381/add-function-line-time-information-to-all-existing-couts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!