Создание списка глобальных переменных из исходного файла C++

Сейчас я работаю над проблемой, ее постановкой - сгенерировать текстовый файл со списком всех объявленных глобальных переменных в файле .CPP.

У меня появилось несколько идей, первая:

Попробуйте использовать ctags, поэтому я написал небольшой скрипт:

while read line
do
echo $line
printf "%s" $line >> report.txt
ctags -x --c++-kinds=v --file-scope=no "{$line}" | sort | sed "/const/d" | awk '{printf " %s", $1}' >> report.txt
printf "\n" >> report.txt
done < cpp_source_file_list.txt

Этот фрагмент кода получает имя исходного файла .cpp из cpp_source_file_list.txt, сканирует его на наличие глобальных переменных (игнорируя const) и записывает отчет «имя файла [список переменных]. Основная проблема, с которой я столкнулся, заключается в том, что ctags ведет себя очень странно, игнорируя в некоторых случаях типы STL.

Например, он может исключать строку типа "vector v;", но включать "std::vector v;".

Есть ли способы исправить такую ​​проблему? Попытка использовать дополнительный ключ ctags -I ./id.txt и вручную составить список идентификаторов для переопределения, но это также приводит к неверным результатам.

Второй способ:

Используйте команду nm, например:

nm builtsource.o | grep '[0-9A-Fa-f]* [BCDGRS]'

Но в этом случае я получаю ненужную информацию, например:

0000000000603528 B M 
0000000000603548 B N 
0000000000603578 B _ZSt3cin@@GLIBCXX_3.4 <- (!)
0000000000603579 B _ZSt4cout@@GLIBCXX_3.4 <- (!)
0000000000603748 B t 

И теперь я понятия не имею, как улучшить один из этих методов, чтобы получить правильную информацию о списке объявленных глобальных переменных из произвольного исходного файла .cpp. Буду рад услышать любые предложения по этой проблеме.


person Twd1024    schedule 18.01.2012    source источник
comment
C++ довольно сложно анализировать, поэтому необходимо использовать внешний инструмент, такой как ctags. Однако sedding для 'const' не приблизит вас к игнорированию const global, это может быть неконстантный указатель на const или даже имя типа 'constant'.   -  person Kos    schedule 18.01.2012
comment
Конечно, я согласен с регулярным выражением, это было своего рода наивным решением.   -  person Twd1024    schedule 18.01.2012
comment
Вы бы чувствовали себя как дома с хорошим синтаксическим анализатором C++, который может дать вам полный AST. Eclipse CDT имеет достойный синтаксический анализатор, но он не предназначен для автономной работы (по причинам, которые ускользают от меня). Вам нужно будет сделать подключаемый модуль Eclipse, чтобы использовать его. Интересно, насколько сложно было бы сгенерировать AST, используя внутренности GCC или Clang?   -  person Kos    schedule 18.01.2012
comment
Я был недалек с Clang! clang.llvm.org/doxygen/group__CINDEX__CPP.html это может вам помочь (может подробностей не скажу, так как не пользовался)   -  person Kos    schedule 18.01.2012
comment
Спасибо! Буду пробовать все способы ^)   -  person Twd1024    schedule 18.01.2012


Ответы (3)


Вы можете использовать Doxygen для реализации этого. Doxygen может анализировать файл C++ и генерировать файл XML, который фиксирует все переменные, встречающиеся в файле. В частности, если вы установите следующие параметры конфигурации:

EXTRACT_ALL= YES
GENERATE_TAGFILE= doxygen.tag

Учитывая входной файл, например:

#include <vector>

using namespace std;

std::vector<int> s1;
vector s2;

Вы можете создать выходной файл doxygen.tag со следующим содержимым:

<?xml version='1.0' encoding='ISO-8859-1' standalone='yes' ?>
<tagfile>
  <compound kind="file">
    <name>input.cpp</name>
    <path>C:/Users/haney/tmp/tmp55/</path>
    <filename>input_8cpp</filename>
    <namespace>std</namespace>
    <member kind="variable">
      <type>std::vector&lt; int &gt;</type>
      <name>s1</name>
      <anchorfile>input_8cpp.html</anchorfile>
      <anchor>93b3bd32f5b6bff31bc4052716ddd444</anchor>
      <arglist></arglist>
    </member>
    <member kind="variable">
      <type>vector</type>
      <name>s2</name>
      <anchorfile>input_8cpp.html</anchorfile>
      <anchor>8feb4a508135e43a72f227568b755a07</anchor>
      <arglist></arglist>
    </member>
  </compound>
  <compound kind="namespace">
    <name>std</name>
    <filename>namespacestd.html</filename>
  </compound>
</tagfile>

Получив XML-файл, вы сможете извлечь из него нужную информацию.

person DRH    schedule 31.01.2012
comment
Спасибо за отличное рабочее решение. Есть ли способ заставить Doxy не распечатывать блоки с атрибутом вида, отличным от файла или переменной? Бывают ситуации, когда вы получаете тонны блоков с типами элементов, равными функции, typedef и т. д. Было бы неплохо избавиться от них в файле .tag. - person fyodorananiev; 24.05.2012
comment
Обратите внимание: Doxygento распознает переменную, объявленную как int a(0); как функцию с ‹список_аргументов›(0)‹/список_аргументов›. - person fyodorananiev; 24.05.2012

Другая возможность — разработать подключаемый модуль GCC или расширение MELT именно для этой цели. Вам нужно будет понять некоторые детали внутренних представлений GCC (Gimmple и Tree).

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

person Basile Starynkevitch    schedule 18.01.2012

Вы можете использовать GCC-XML, возможно, с чем-то еще сверху (например, pygccxml), чтобы упростить навигацию. Я успешно использовал эту комбинацию для аналогичных целей извлечения кода.

person jjlin    schedule 31.01.2012