Оригинальный вопрос
То, что я хотел бы, это не стандартный препроцессор 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 года. Я проверю его ... дальнейшие отчеты позже в этом году, или, может быть, в следующем году, или когда-нибудь, или никогда.