2009-07-18 4 views
2

Он должен превратить этотЕсть ли инструмент, который позволяет мне вставлять одну строку кода во все функции и методы в исходный файл C++?

int Yada (int yada) 
{ 
    return yada; 
} 

в этом

int Yada (int yada) 
{ 
    SOME_HEIDEGGER_QUOTE; 
    return yada; 
} 

, но и для всех (или, по крайней мере, большой пучок) синтаксически правовой C/C++ - функции и метод построения.

Возможно, вы слышали о некоторой библиотеке Perl, которая позволит мне выполнять эти операции в виде строк кода.

Моя цель - добавить трассировщик в старый, но большой проект на C++, чтобы иметь возможность отлаживать его без отладчика.

+3

Примечание: код C++ не является обычным языком, поэтому требование «для всех синтаксически законных C/C++» не достигается посредством регулярных выражений. – Svante

+2

«Регулярные выражения» на языке Perl на самом деле не являются регулярными выражениями. Однако синтаксический анализ C++ все еще тяжелый. – jrockway

+0

@svante: Это не вопрос. Регулу не нужно проверять, является ли код синтаксически законным. Он должен только найти определения функций и предположить, что весь код является законным. – Niki

ответ

10

Try Aspect C++ (www.aspectc.org). Вы можете определить Аспект, который подберет каждое исполнение метода.

В самом деле, Quickstart имеет в значительной степени именно то, что вы после того, как определено в качестве примера: http://www.aspectc.org/fileadmin/documentation/ac-quickref.pdf

+0

@Phil Я не знаю, связаны ли вы с AspectC++ каким-либо образом, но если вы предоставляете (или предоставляете им) одну ссылку HTML, которая кратко описывает, что она делает. PDF-файл, который вы связали, является быстрой ссылкой (бесполезно, если вы не понимаете, что это такое). и я не могу найти ничего лучшего на веб-сайте. – 2009-07-18 20:39:23

+0

http://en.wikipedia.org/wiki/AspectC%2B%2B имеет достойное объяснение того, что такое AspectC++. На самом деле, вы, вероятно, захотите начать с http://en.wikipedia.org/wiki/Aspect-oriented_programming, если вы не знакомы с аспектно-ориентированным программированием. – dancavallaro

+0

Извините, я никак не связан с AspectC++. Стоит обойти вокруг Аспектно-ориентированного программирования. Это может быть удивительно мощным. – Phil

1

Я использую это регулярное выражение,

"(?<=[\\s:~])(\\w+)\\s*\\([\\w\\s,<>\\[\\].=&':/*]*?\\)\\s*(const)?\\s*{" 

найти функции и добавить дополнительные строки кода.

С этим регулярным выражением я также получаю имя функции (группа 1) и аргументы (группа 2).
Примечание: вы должны отфильтровать имена, например, "while", "do", "for", "switch".

+0

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

+0

Вы правы, регулярные выражения не являются * правильными * для синтаксического анализа. Мое регулярное выражение является своего рода эвристическим *. Он найдет много функций (или методов), но не все из них. –

+0

+1 для того, чтобы быть достаточно близко для джаза, хотя :-) –

2

Нет такого инструмента, о котором я знаю. Чтобы распознать правильную точку вставки, инструмент должен включать полный синтаксический анализатор C++. Для этого недостаточно регулярных выражений.

Но поскольку существует множество парсеров FOSS C++, такой инструмент, безусловно, может быть написан - своего рода интеллектуальное sed для кода на C++. Самой большой проблемой, вероятно, будет разработка языка спецификаций для операции insert/update/delete - регулярные выражения, очевидно, не являются ответом, хотя они обязательно должны быть включены в язык каким-то образом.

Люди всегда задают здесь идеи для проектов - как насчет этого для одного?

+0

Если я не ошибаюсь, популярные редакторы используют регулярные выражения для определения подпрограмм (не всегда с успехом). Теперь, если вы не собираетесь создавать код * production *, и вы можете повторно настроить или исправить результаты из регулярного выражения, и если вы не хотите тратить время на сложные реальные парсеры, почему бы не использовать регулярное выражение? –

+0

Как вы говорите, не всегда с успехом.Это не большая проблема с интерактивными редакторами, так как вы можете выявить любые проблемы с помощью визуального контроля. Это проблема для пакетных операций на сотнях тысяч строк кода, где вы не можете. И если вы не собираетесь создавать код продукта, пойдите и сделайте что-нибудь еще. – 2009-07-18 13:36:16

+0

Вставка дополнительных (трассировка) кода после функций, т.е. для кода * изучения *, - это случай, когда вы можете выбросить этот код. Вот что я имел в виду с непродуктивным кодом. Даже с реальным парсером, как вы можете быть уверены, что у вас не будет проблем, когда вы собираетесь изменять сотни подпрограмм? –

5

Если вы строите с использованием GCC и -pg флаг, GCC будет автоматически выдавать вызов на mcount() функция в начале каждой функции. В этой функции вы можете проверить адрес возврата, чтобы выяснить, откуда вы были вызваны. Этот подход используется индикатором функции ядра Linux (CONFIG_FUNCTION_TRACER). Обратите внимание, что эта функция должна быть написана на ассемблере и будьте осторожны, чтобы сохранить все регистры!

Также обратите внимание, что это должно быть передано только в фазе сборки, а не в ссылке, или GCC будет добавлять в профилирующие библиотеки, которые обычно реализуют mcount.

+0

приятно знать. Великий. – elcuco

5

Я бы предложил использовать флаг gcc "-finstrument-functions". В принципе, он автоматически вызывает определенную функцию («__cyg_profile_func_enter») при входе в каждую функцию, а другая функция вызывается («__cyg_profile_func_exit») после выхода из функции. Каждой функции передается указатель на введенную/выведенную функцию и функцию, которая вызвала ее.

Вы можете отключить инструмент для каждой функции или для каждого файла ... подробнее см. В документах.

Функция восходит по крайней мере до версии 3.0.4 (с февраля 2002 года).

Предназначен для поддержки профилирования, но он не имеет побочных эффектов, таких как -pg (который компилирует код, подходящий для профилирования).

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

+0

/Gh и/GH для MSVC, вызывая _penter и _pexit – MSalters

0

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

DMS Software Reengineering Toolkit является общей программой преобразования программ и может использоваться со многими языками (C#, COBOL, Java, EcmaScript, Fortran, ..), а также специально с C++.

DMS анализирует исходный код (используя полный интерфейс langauge, в данном случае для C++), создает абстрактные деревья синтаксиса и позволяет применять шаблоны источника к источнику для преобразования кода из одной программы на C# в другую с помощью любые свойства, которые вы пожелаете. Правило преобразования для выполнения именно задачи вы определили бы:

domain CSharp. 

insert_trace():function->function 
    "\visibility \returntype \fnname(int \parametername) 
    { \body } " 
     -> 
    "\visibility \returntype \fnname(int \parametername) 
    { Heidigger(\CppString\(\methodname\), 
       \CppString\(\parametername\), 
       \parametername); 
     \body } " 

Кавычки (") не C++ кавычки, скорее, они являются„кавычки домена“, и указывает, что содержимое внутри кавычек это синтаксис C++ (потому что мы сказали «домен CSharp»). Обозначения \ foo являются метасигналистами.

Это правило соответствует AST, представляющему функцию, и переписывает AST в прослеживаемую форму. вернитесь в исходную форму, которую вы можете скомпилировать. Вероятно, вам нужны другие правила для обработки других комбинаций аргументов, на самом деле вы бы, вероятно, обобщили обработку аргументов, чтобы произвести (где практически) строковое значение для каждого sc alar аргумент.

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