Добавьте FUNCTION, LINE, информацию о времени ко всем существующим "кроватям"

У меня уже есть большая кодовая база, которая использует много раскладов. Я не могу пойти и изменить все существующие койки. Могу ли я что-нибудь сделать, чтобы существующие койки добавили информацию о ФУНКЦИИ, ЛИНИИ и времени, а также то, что должно быть напечатано в куте? Другими словами, я могу переопределить cout, чтобы использовать мою реализацию, которая напечатает строку вместе со всей дополнительной информацией. Я тоже готов делать что-то еще, не обязательно отменять...

Может быть, я не объяснил четко.. Это то, что мне нужно. У меня уже есть такие вещи, как,

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

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

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

,, и так далее..

в большой базе кода, в которой я не могу редактировать все существующие койки..

Мне нужно эти койки, чтобы напечатать что-то похожее на..

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

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

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

Надеюсь, это прояснит ситуацию. Я хочу, чтобы оригинальные койки были АВТОМАТИЧЕСКИ (возможно, при помощи некоторого трюка) преобразованы, чтобы они также печатали эту дополнительную информацию.

2 ответа

(ваш вопрос не совсем дублирует этот вопрос, потому что вы также хотите вывести информацию о строке и исходном файле, а ля __FILE__ а также __LINE__ и это имеет существенное значение; однако я чувствую, что ваш вопрос слишком широк и не содержит подробностей)

настройка вашего компилятора

Вы можете настроить недавний компилятор GCC, чтобы делать то, что вы хотите, используя GCC MELT (который я разработал и реализовал). Затем вы закодируете дополнительный "проход оптимизации", который волшебным образом преобразит ваш std::cout <<... выходные операторы (внутри компилятора), добавляющие некоторые встроенные выражения, делая их эквивалентными std::cout << __builtin_FILE () << ' ' << __builtin_LINE () << ' ' <<....; вам нужно будет сделать соответствующее преобразование на уровне Gimple.

Это, вероятно, не тривиальная задача, так как вам нужно понять детали внутренних представлений GCC. Поэтому я не совсем уверен, что это стоит (если в вашей кодовой базе не менее полумиллиона строк исходного кода и стоит потратить пару недель на написание своей настройки MELT).

Если вы можете позволить себе вручную редактировать каждую релевантную строку, такой подход, как здесь, может быть проще.

Возможно, вы могли бы объединить оба, используя MELT для определения правильных строк для редактирования и подачи их в sed скрипт, преобразующий ваш исходный код для вызова макроса.

почему преобразование не просто

Внутренне компилятор работает с некоторым внутренним представлением, которое является нормализованным AST, или даже чем-то более простым (Gimple). Для GCC вы хотите преобразовать внутреннее представление

 extern "C" void testit(int x) {
   if (x>0)
   std::cout << "x=" << x << std::endl;
 }

в нечто близкое к внутреннему представлению

 extern "C" void transformed_testit (int x) {
   if (x>0)
     std::cout << __builtin_FILE() << ' ' << __builtin_LINE() << ' ' 
               << "x=" << x << std::endl;
 }    

Чтобы понять представление Gimple, скомпилируйте их с g++ -fdump-tree-gimple; Вот текстовый дамп кода Gimple первой функции (фактически, Gimple - это только структура данных в памяти):

  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>:
  }     

почему вам нужно работать внутри компилятора

Поскольку ваш исходный код может содержать такой вывод во многих вариантах, в том числе

std::cout << "x=" << x << std::endl;

или же

using namespace std;
cout << "x=" << x << endl;

или же

#define MY_LOG(Out) do{std::cout<<Out<<std::endl;} while(0)
MY_LOG("x=" << x);

или даже

auto& output = std::cout;
output << "x=" << x << std::endl;

(в приведенных выше примерах две строки кода могут быть очень далеко друг от друга или даже в разных файлах, например #define MY_LOG в некотором заголовочном файле, и используется в некотором файле реализации... Но представление Gimple было бы очень похоже во всех случаях)

следовательно, чисто текстовый или синтаксический подход не всегда будет работать, и вам потребуется сложный инструмент, похожий на компилятор, чтобы выполнить преобразование.

Так что, если вы можете позволить себе тратить как минимум две недели на решение вашей проблемы, попробуйте использовать GCC MELT. В противном случае, запустите вручную некоторые sed сценарий или код вашей функции Emacs для интерактивного редактирования

измена в C++

Может быть, вы могли бы иметь

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__)

тогда вы могли бы сделать

mycout << "x=" << x << std::endl;

Следовательно, вы можете попробовать #define cout mycout после #define mycout...; это, вероятно, вылило бы много сообщений об ошибках, и вы могли бы вручную настроить код на их месте

PS. Вы можете связаться со мной по электронной почте basile@starynkevitch.net но затем, пожалуйста, укажите URL вашего вопроса и дайте гораздо более подробную информацию: что делает ваш код, каков его исходный размер, какой именно компилятор вы используете, какой у вас работодатель и страна и т. д.

Очевидным решением будет использование некоторого макроса редактора, такого как макросы vim в паре с grep -rnw 'directory' -e "cout <<", предполагая платформу Linux.

Что касается C++, если вы используете cout и не std::cout во всем вашем коде, тогда возможное решение будет удалить using namespace std а затем развернуть свой собственный cout функция - при условии, что у вас нет другого кода в зависимости от std:: который сломается.

Вопрос, помеченный как дубликат, может содержать ответ на вашу проблему.

Другие вопросы по тегам