Пользовательский препроцессор gcc

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

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

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

Ответы

Ответ 1

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

Он выглядит следующим образом:

> cat cc1
#!/bin/sh

echo "My own special preprocessor -- [email protected]"

/usr/lib/gcc/i486-linux-gnu/4.3/cc1 [email protected]
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

Этот пример вызывает исходный препроцессор, но печатает дополнительное сообщение и параметры. Вы можете заменить script на собственный препроцессор.

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

Ответ 2

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

Наш DMS Software Reengineering Toolkit - такая система, которая может применяться ко многим языкам, включая C и, в частности, GCC 2/3/4 серии компиляторов.

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

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

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

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

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

  ... 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 weird escapes

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

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

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