Существует ли инструмент командной строки для извлечения typedef, структуры, перечисления, переменной, функции из файла C или C++?

Мне нужен инструмент командной строки для извлечения определения или объявления (typedef, структура, перечисление, переменная или функция) из исходного файла C или C++. Также был бы удобен способ замены существующего определения / объявления (после преобразования извлеченного определения с помощью пользовательского сценария). Имеется ли такой общий инструмент или есть какое-то достаточно близкое приближение к такому инструменту?

Здесь важна возможность написания сценариев и возможность подключения к созданным пользователем сценариям или программам, хотя мне также любопытны академические программы. Решения с открытым исходным кодом для лагеря Unix/Linux предпочтительны (хотя мне также интересны инструменты для Windows и OS X). Основными интересами языка являются C и C++, но более общее решение было бы еще лучше (я думаю, что нам не нужны сверхточные возможности синтаксического анализа для поиска, извлечения и замены определения в исходном файле программы).

Примеры использования (дополнительно - для любопытных):

  1. Учитывая глубоко вложенные structs и инициализации переменных (массивов) этих типов, предположим, что необходимо изменить определение структуры, добавив или переупорядочив поля или переписав определения переменных / массивов в более удобочитаемом формате без ошибок, возникающих в результате ручного труда. Это будет работать путем извлечения старых инициализаций с последующим использованием сценария / программы для записи новых инициализаций для замены старых.
  2. Для реализации инструмента просмотра кода - извлеките определение.
  3. Генерация декоративного кода (например, регистрация / возврат записей функций).
  4. Сценарий структурирования кода (например, извлечь то и это и поместить в другое место без изменений - комментарий коммита управления версиями может задокументировать команду для выполнения этой операции, чтобы сделать очевидным и проверяемым, что ничего не изменилось).

Альтернативная проблема: если есть инструмент для определения местоположения определения (будет достаточно начальной и конечной строки - мы можем даже предположить, что все интересующие нас определения / объявления находятся в отдельной строке), тогда это будет просто выполнение ловкость пальцев, чтобы написать программу

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

    • получить желаемые извлеченные определения из stdin (или из временного файла),
    • выполнить преобразование (редактирование) и
    • вывести новые определения в stdout (или сохраните их в указанном временном файле)

    быть замененным исполняющей программой.

Таким образом, главная, более сложная проблема - найти начало и конец определения.

Примечание о тегах: более точный тег, чем code-generation было бы code-transformation но его не существует.

3 ответа

Решение

Наш DMS Software Reengineering Toolkit пытается быть тем инструментом, о котором вы мечтаете. Но это продвигает современное состояние и не инструмент стиля нирваны. Это достаточно хорошо, чтобы делать настоящую, интересную работу.

DMS предоставляет общие средства для анализа, анализа и преобразования исходного кода.

Он использует явные грамматики для определения языков (таких как C и C++); грамматики управляют синтаксическими анализаторами, которые создают абстрактные синтаксические деревья (AST). Множество примитивов анализа предоставляют а) средства ["грамматики атрибутов" ATG] для сбора информации по древовидным путям информационных потоков, которые точно соответствуют форме AST, б) построение использования символов для карт определения символов ["таблиц символов"] c) контроль и анализ потока данных с использованием фактов, извлеченных ATG; d) анализ дальности; e) точечный анализ как локального, так и глобального. Эти примитивные анализаторы могут использоваться для составления фактов из AST, чтобы сделать выводы о коде, представленном AST (например, "это утверждение изменяет эти переменные"). Внешний интерфейс langauge объединяет грамматику и анализаторы для конкретного языка в многоразовый пакет. DMS имеет такие языковые интерфейсы разного уровня глубины и зрелости для самых разных языков.

[РЕДАКТИРОВАНИЕ 6/27: Внешние интерфейсы C и C++ поддерживают определенные диалекты C и C++: ANSIC, C99, GCC3/4 C, MS Visual C, ANSI C++98, ANSI C++11, GCC3/4. C++, MS Visual C++ 2005/2008/2010. Если вы хотите точного анализа кода, вы должны использовать "правильный" диалект для обработки вашего кода.]

Но "анализ" не в этом. Целью анализа является стимулирование изменений. DMS обеспечивает дополнительную поддержку для процедурного изменения AST, для изменения AST с помощью правил перезаписи от источника к источнику, написанных в поверхностном синтаксисе языка (оба обусловлены некоторым выбранным результатом анализа), или для группировки наборов процедурных и исходных данных. исходные тексты переписывают вместе, чтобы составлять сложные сложные переписки, которые могут нести огромные изменения кода, такие как реорганизация и т. д. После преобразования AST их можно использовать для регенерации ("prettyprint") синтаксически правильного кода в соответствующем конечный язык / диалект. [Изменяя AST для одного языка по кусочкам, пока у вас не появится AST для другого, вы можете создавать переводчики, но это не так просто, как подразумевает это предложение].

Все это работает в значительной степени, но все еще несколько блокируется некоторыми языковыми осложнениями. Для C и C++ известным усложнением является препроцессор; произвольно редактируя текст программы, условные выражения препроцессора могут сделать исходный код неразборчивым с помощью чего-либо, напоминающего стандартную технологию синтаксического анализа. Внешние интерфейсы DMS C и C++ несколько улучшают это и могут анализировать код с хорошо структурированными директивами препроцессора, включая некоторые странные случаи, которые большинство людей не называют структурированными, но это обычно происходит:

   #IF  cond
        if (abc)  {
   #ELSE
        if (def)  {
   #ENDIF

Мы добились интересного прогресса в разборе кода с произвольным размещением условий препроцессора. Но как только вы это сделаете, теперь все ваши анализаторы внезапно должны будут принять во внимание условия препроцессора, и мы внезапно окажемся в дураках, которые люди компилятора на самом деле не посетили.

DMS использовался для больших архитектурных сдвигов в больших программах на C++, преобразования из не-CORBA-стиля в CORBA-стиль с огромным количеством перемешивания кода, для извлечения кода по произвольным путям потока управления для генерации API в стиле SOW для существующего кода C, вставлять инструментарий в большие программы на Си для обнаружения ошибок указателя и т. д. [Он был применен к другим задачам во многих из этих других языков].

По нашему опыту, его все еще довольно сложно использовать. По нашему мнению, это в том же смысле, что демократия является худшей из всех систем правления, за исключением всех остальных; YMMV. На сайте есть много инструментов и дискуссий, основанных на DMS.

Фактически оно использовалось для извлечения функций (упражнение SOW гораздо более общее, чем это) и вставки функций (это обобщенный случай инструментирования).

Такие инструменты, как GCC-XML, являются тенями возможностей DMS. GCC-XML анализирует, создает таблицы символов и выводит объявления данных (не код), но не может вносить какие-либо изменения в код. Лязг лучше; он анализирует C и C++ в AST, может выполнять анализ промежуточного представления LLVM и имеет какой-то механизм выделения дополнительных исправлений для последующего применения к исходному тексту, вдохновленный желаемым изменением дерева. Я не знаю, может ли Clang выполнять масштабные преобразования кода, особенно те, в которых результат одного преобразования снова преобразуется (как вы модифицируете дерево для отложенного текстового патча?). DMS может делать это в течение всего дня, и может делать это для многих языков, кроме C и C++, и может делать это для произвольной смеси известных им языков.

До тех пор, пока проблема препроцессора с условными выражениями не будет решена, анализ / преобразование кода C и C++ не будет легким. Мы выполняем эти задачи на этих языках только благодаря силе воли и использованию самых мощных инструментов, которые мы можем создать. (У Java таких проблем нет, и DMS, соответственно, лучше анализирует / трансформирует).

При серьезном риске высокомерия, я считаю, что DMS - лучший инструмент для общего анализа и преобразования. Как его архитектор, я считаю своей долгосрочной работой сделать ее еще более сильной для этой задачи.

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

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

Вы можете проверить Clang. У них есть нетривиальные библиотеки обработки исходного кода.

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