2016-02-29 2 views
3

Я ищу способ поиска заданного термина в коде проекта C/C++, игнорируя любые вхождения в комментариях и строках.Как найти поисковый запрос в исходном коде

Как кодовая база довольно большая, я ищу способ автоматически определить строки кода, соответствующие моему поисковому запросу, так как они нуждаются в ручном осмотре.

Если возможно, я хотел бы выполнить поиск в моей системе linux.

фон

кодовая база в вопросе двигатель обработки сигналов в реальном масштабе времени с большим количеством плагинов 3rd партии. плагины реализованы на разных языках (в основном C, но также C++ и другие, в настоящее время я забочусь только об этих двух), стандарты не были соблюдены.

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

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

код также содержит статические приведения в стиле C до (float), поэтому полагаться на предупреждения компилятора для выявления несоответствий типов часто не является вариантом.

База кода состоит из более чем 3000 файлов (C и C++), аккумулирующих около 750000 строк кода.

код кросс-платформенный (linux, osx, w32 является основным объектом, но также freebsd и т. Д.) И скомпилирован с различными нативными компиляторами (gcc/g ++, clang/clang ++, VisualStudio, ...).

до сих пор ...

до сих пор я использую что-то уродливое, как:

grep "\bfloat\b" | sed -e 's|//.*||' -e 's|"[^"]*"||g' | grep "\bfloat\b" 

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

+1

Что делает ваш код? Каков его размер? Какой компилятор и платформа? Пожалуйста, ** отредактируйте свой вопрос **, чтобы улучшить его. –

+0

В зависимости от того, насколько велика ваша кодовая база, я могу просто сделать это вручную с помощью emacs. В противном случае я мог бы просто заменить их все и исправить ложные комментарии позже. Хотя я ленив. :) – erip

+1

BTW C/C++ не существует. Данная единица перевода кодируется для C++ (затем выбирает по крайней мере стандарт C++ 11) или для C (выберите C11, если возможно, или, по крайней мере, C99) –

ответ

5

ИМХО есть хорошие ответы на подобный вопрос в «Unix & Linux»:

Grep работает на чистом тексте и ничего о основного синтаксиса вашей программы C не знает. Поэтому, чтобы не искать внутри комментарии у вас есть несколько вариантов:

  1. Газа C-комментарии перед началом поиска, вы можете сделать это с помощью GCC -fpreprocessed -dd -E yourfile.с Для получения дополнительной информации, пожалуйста, см Remove comments from C/C++ code

  2. Записи/использовать несколько Hacky полулитых рабочих скриптов, как вы уже нашли (например, они работают, пропуская строки, начинающиеся с // или/*) для того, чтобы обрабатывать детали все возможные комментарии C/C++ (опять же, см. ссылку для некоторых страшных тестовых ящиков). Тогда у вас все еще могут быть ложные положительных результатов, но вам не нужно предварительно обрабатывать что-либо.

  3. Используйте более сложные инструменты для выполнения «семантического поиска» в коде. I нашли «coccigrep»: http://home.regit.org/software/coccigrep/ Этот инструмент позволяет искать какие-либо конкретные операторы языка (т. Е. Обновление структуры с заданным именем) и, конечно же, они отбросить комментарии.

https://unix.stackexchange.com/a/33136/158220

Хотя он не полностью прикрывать "не в строках" требование.

+1

Почему downvote? –

3

Это может зависеть от размера вашей базы кода и, возможно, от редактора, который вы обычно используете. Я предлагаю использовать GNU emacs (если это возможно на Linux с недавнего GCC компилятором ...)

Для малого и среднего размера кода (например, менее чем 300KLOC), я предложил бы использовать grep mode из Emacs. Затем (при условии, что вы связали функцию Emacs с некоторым ключом, возможно, с (global-set-key [f10] 'next-error) в вашем ~/.emacs ...), вы можете быстро сканировать каждое вхождение float (даже внутри строк или комментариев, но вы очень быстро пропустите такие случаи. .). Через несколько часов вам будет сделан исходный код среднего размера (и это быстрее, чем изучение того, как использовать новый инструмент).

Для большого размера кода (в миллионах строк) может оказаться целесообразным настроить какой-либо инструмент статического анализа или компилятор. Вы можете использовать GCC MELT для настройки вашего компилятора GCC в Linux. Его findgimple mode может быть вдохновляющим, и, возможно, даже полезно (вы, вероятно, хотите, чтобы найти все назначения Gimple ориентации на float)

Кстати, вы, вероятно, не хотите, чтобы заменить все вхождения бут только большинство сами по из float тип с double (возможно подходящим образом typedef -ed ...), потому что, возможно, вы используете некоторые внешние (или стандартные) функции , требующие a float.

Инструмент CADNA также может быть полезен, чтобы помочь вам оценить точность результатов (так что вы решаете, когда используете double разумно).

Использование семантических инструментов, как GCC MELT, CADNA, Coccinelle, Frama-C (или, возможно, Fluctuat или Coccigrep, упомянутые в g0hl1n's answer) будет давать более точные и соответствующие результаты, за счет того, чтобы тратить больше времени (возможно, дней!) В процессе обучения и настройку инструмента.

1

Надежный способ сделать это должно быть с cscope (http://cscope.sourceforge.net/) в режиме линейного ориентированного с помощью опции find this C symbol, но я не использовал, что на различных стандартов C, так что если что не работает для вас, или если вы не можете получить cscope то сделать это:

find . -type f -print | 
while IFS= read -r file 
do 
    sed 's/a/aA/g;s/__/aB/g;s/#/aC/g' "$file" | 
    gcc -P -E - | 
    sed 's/aC/#/g;s/aB/__/g;s/aA/a/g' | 
    awk -v file="$file" -v OFS=': ' '/\<float\>/{print file, $0}' 
done 

Первым sed заменяет весь хэш (#) и __ символов с уникальными строками идентификаторов, так что препроцессор не делает какие-либо расширений #include и т.д. но мы можем восстановить их после предварительной обработки.

gcc preprocesses вход для выделения комментариев.

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

awk действительно ищет float в границах слов и, если найден, печатает имя файла плюс строку, в которой он был найден. Это использует GNU awk для текстовых границ \< и \>.

Работа 2-го седала МОЖЕТ быть выполнена как часть команды awk, но мне нравится симметрия двух семян.

В отличие от, если вы используете cscope, этот подход sed/gcc/sed/awk НЕ будет избегать поиска ложных совпадений в строках, но, надеюсь, их очень мало, и вы можете вытеснить их во время постобработки вручную.

Он не будет работать для имен файлов, содержащих символы новой строки - если у вас есть те, которые вы можете, но тело в скрипте, и выполните его как find .. -print0 | xargs -0 script.

Измените командную строку gcc, добавив любую версию C или C++, которую вы используете, например. -ansi.

Смежные вопросы