Есть ли препроцессор C, который устраняет блоки #ifdef на основе значений, определенных / неопределенных? - PullRequest
32 голосов
/ 08 февраля 2009

Оригинальный вопрос

То, что я хотел бы, это не стандартный препроцессор C, а его вариант, который будет принимать откуда-то - возможно, командную строку через опции -DNAME1 и -UNAME2 - спецификацию того, какие макросы определены, и будет ли затем удалите мертвый код.

Может быть легче понять, что я ищу, с некоторыми примерами:

#ifdef NAME1
#define ALBUQUERQUE "ambidextrous"
#else
#define PHANTASMAGORIA "ghostly"
#endif

Если команда была запущена с '-DNAME1', результат будет:

#define ALBUQUERQUE "ambidextrous"

Если команда была запущена с '-UNAME1', результат будет:

#define PHANTASMAGORIA "ghostly"

Если команда была выполнена без какой-либо опции, выходные данные были бы такими же, как и входные.

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

Для иллюстрации на реальном, но все еще простом примере:

#ifdef USE_VOID
#ifdef PLATFORM1
#define VOID void
#else
#undef VOID
typedef void    VOID;
#endif /* PLATFORM1 */
typedef void *  VOIDPTR;
#else
typedef mint     VOID;
typedef char *  VOIDPTR;
#endif /* USE_VOID */

Я бы хотел запустить команду с -DUSE_VOID -UPLATFORM1 и получить вывод:

#undef VOID
typedef void    VOID;
typedef void *  VOIDPTR;

Другой пример:

#ifndef DOUBLEPAD
#if (defined NT) || (defined OLDUNIX)
#define DOUBLEPAD 8
#else
#define DOUBLEPAD 0
#endif /* NT */
#endif /* !DOUBLEPAD */

В идеале я хотел бы запустить с -UOLDUNIX и получить вывод:

#ifndef DOUBLEPAD
#if (defined NT)
#define DOUBLEPAD 8
#else
#define DOUBLEPAD 0
#endif /* NT */
#endif /* !DOUBLEPAD */

Это может быть моей удачей!

Мотивация: большая древняя кодовая база с большим количеством условного кода. Многие из условий больше не применяются - например, платформа OLDUNIX больше не создается и больше не поддерживается, поэтому нет необходимости иметь ссылки на нее в коде. Другие условия всегда верны. Например, функции добавляются с условной компиляцией, так что одна версия кода может использоваться как для более старых версий программного обеспечения, где функция недоступна, так и для более новых версий, где она доступна (более или менее). В конце концов, старые версии без этой функции больше не поддерживаются - все используют эту функцию - поэтому необходимо удалить условие о том, присутствует эта функция или нет, и удалить код «когда функция отсутствует». Мне бы хотелось иметь инструмент для автоматического выполнения этой работы, потому что он будет быстрее и надежнее, чем делать это вручную (что весьма важно, когда база кода включает 21 500 исходных файлов).

(Действительно умная версия инструмента может прочитать #include d-файлы, чтобы определить, определены ли в этих файлах макросы управления - те, которые указаны в командной строке -D или -U). Я не уверен действительно ли это полезно, кроме как для диагностики резервных копий. Однако, что бы он ни делал, псевдопроцессор не должен дословно расширять макросы или включать файлы. Выходные данные должны быть похожи на исходный код, но обычно проще, чем на входной код.)

Отчет о состоянии (год спустя)

После года использования я очень доволен ' sunifdef ', рекомендованным выбранным ответом. Это еще не сделало ошибку, и я не ожидаю этого. Единственное, что я могу сказать - это стилистика. Учитывая ввод, такой как:

#if (defined(A) && defined(B)) || defined(C) || (defined(D) && defined(E))

и запустить с '-UC' (C никогда не определяется), вывод:

#if defined(A) && defined(B) || defined(D) && defined(E)

Это технически правильно, потому что '&&' связывает крепче, чем '||', но это открытое приглашение к путанице. Я бы предпочел включить скобки вокруг наборов условий & &, как в оригинале:

#if (defined(A) && defined(B)) || (defined(D) && defined(E))

Однако, учитывая неясность некоторых кодов, с которыми мне приходится работать, для этого быть самым большим придиркой - сильный комплимент; это ценный инструмент для меня.


Новый малыш на блоке

Проверив URL-адрес для включения в приведенную выше информацию, я вижу, что (как и предполагалось) существует новая программа под названием Coan , которая является преемницей sunifdef. Он доступен на SourceForge и работает с января 2010 года. Я проверю его ... дальнейшие отчеты позже в этом году, или, может быть, в следующем году, или когда-нибудь, или никогда.

Ответы [ 5 ]

23 голосов
/ 08 февраля 2009

Я абсолютно ничего не знаю о C, но, похоже, вы ищете что-то вроде unifdef. Обратите внимание, что он не обновлялся с 2000 года, но есть преемник под названием "Сын unifdef" (sunifdef) .

4 голосов
/ 20 июня 2013

Также вы можете попробовать этот инструмент http://coan2.sourceforge.net/

что-то вроде этого удалит блоки ifdef:

источник коана -UYOUR_FLAG --фильтр c, h - recurse YourSourceTree

4 голосов
/ 08 февраля 2009

Я использовал unifdef несколько лет назад только для той проблемы, которую вы описываете, и она работала нормально. Даже если он не обновлялся с 2000 года, синтаксис препроцессора ifdefs с тех пор существенно не изменился, поэтому я ожидаю, что он все равно будет делать то, что вы хотите. Я предполагаю, что могут быть некоторые проблемы с компиляцией, хотя пакеты появляются недавно.

Я никогда не использовал sunifdef, поэтому я не могу прокомментировать это напрямую.

3 голосов
/ 08 февраля 2009

Примерно в 2004 году я написал инструмент, который сделал именно то, что вы ищете. Я никогда не удосужился распространять инструмент, но код можно найти здесь:

http://casey.dnsalias.org/exifdef-0.2.zip (это ссылка dsl)

Он содержит около 1,7 тыс. Строк и реализует достаточно грамматики языка Си для анализа операторов, комментариев и строк препроцессора с использованием bison и flex.

2 голосов
/ 10 февраля 2009

Если вам нужно что-то похожее на препроцессор, гибкое решение - Wave (от boost). Это библиотека, предназначенная для создания инструментов, подобных C-препроцессору (включая такие вещи, как препроцессоры C ++ 03 и C ++ 0x). Поскольку это библиотека, вы можете подключиться к ее входному и выходному коду.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...