Пользовательский препроцессор gcc - PullRequest
13 голосов
/ 23 августа 2010

Не могли бы вы привести пример написания собственного препроцессора gcc?

Моя цель - заменить одинаковые макросы SID ("foo") соответствующими вычисленными значениями CRC32.Для любого другого макроса я хотел бы использовать стандартный препроцессор cpp.

Похоже, что можно достичь этой цели, используя опции -no-integrated-cpp -B, однако я не могу найти простой пример их использования.

Ответы [ 2 ]

21 голосов
/ 07 сентября 2010

Предупреждение: опасный и некрасивый взлом. Закройте глаза сейчас Вы можете подключить свой собственный препроцессор, добавив ключи '-no-integrated-cpp' и '-B' в командную строку gcc. '-no-integrated-cpp' означает, что gcc выполняет поиск по пути '-B' своих препроцессоров, прежде чем он использует свой внутренний путь поиска. Вызовы препроцессора могут быть идентифицированы, если программы 'cc1', 'cc1plus' или 'cc1obj' (это компиляторы C, C ++ и Objective-c) вызываются с опцией '-E'. Вы можете выполнить свою собственную предварительную обработку, когда увидите эту опцию. Когда опция '-E' отсутствует, передайте все параметры исходным программам. Когда есть такая опция, вы можете выполнить свою собственную предварительную обработку и передать обработанный файл исходному компилятору.

Это выглядит так:

> cat cc1
#!/bin/sh

echo "My own special preprocessor -- $@"

/usr/lib/gcc/i486-linux-gnu/4.3/cc1 $@
exit $?

> chmod 755 cc1
> gcc -no-integrated-cpp -B$PWD x.c
My own special preprocessor -- -E -quiet x.c -mtune=generic -o /tmp/cc68tIbc.i
My own special preprocessor -- -fpreprocessed /tmp/cc68tIbc.i -quiet -dumpbase x.c -mtune=generic -auxbase x -o /tmp/cc0WGHdh.s

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

Плохой взлом окончен. Вы можете открыть глаза сейчас.

2 голосов
/ 10 сентября 2010

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

Наш инструментарий реинжиниринга программного обеспечения DMS представляет собой такую ​​систему, которая может применяться ко многим языкам, включая C и, в частности, к компиляторам серии GCC 2/3/4.

Чтобы реализовать эту идею с помощью DMS, вы должны запустить DMS с C внешним интерфейсом над вашим исходным кодом перед этапом компиляции. DMS может анализировать код без расширения директив препроцессора , build абстрактные синтаксические деревья, представляющие его, выполняют преобразования в AST, а затем выводят результат в виде скомпилированного текста на языке C.

Конкретное правило преобразования, которое вы бы использовали:

rule replace_SID_invocation(s:STRING):expression->expression
          = "SID(\s)" -> ComputeCRC32(s);

где ComputeCRC32 - это пользовательский код, который делает то, что говорит. (DMS включает реализацию CRC32, поэтому пользовательский код для этого довольно короткий.

DMS является большим молотком для этой задачи. Вы можете использовать PERL для реализации чего-то похожего. Разница с PERL (или каким-либо другим способом сопоставления / замены строк) заключается в том, что а) он может найти шаблон где-то, где вы не не хотите заменить, например,

  ... QSID("foo")... // this isn't a SID invocation

, который вы, вероятно, можете исправить, тщательно кодировав совпадение с шаблоном, b) не соответствует вызову SID, найденному при неожиданных обстоятельствах:

  ...   SID  ( /* master login id */  "Joel" )  ... // need to account for formatting and whitespace

и c) не могут обрабатывать различные виды escape-символов, которые отображаются в самой литеральной строке:

  ...   SID("f\no\072") ...  // need to handle all of GCC's weird escapes

Передний конец DMS C обрабатывает все побеги для вас; Приведенная выше функция ComputeCRC32 будет видеть строку, содержащую действительные предполагаемые символы, а не необработанный текст, который вы видите в исходном коде.

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

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

...