Поддерживает ли ctags исправленную функцию прототипа GCC?
Я обнаружил, что gcc поддерживает странное определение функции, например:
static void add_define P3(char *, name, int, nargs, char *, exps)
Который компилируется с -D__USE_FIXED_PROTOTYPES__. И мои плагины тегов vim не могли дать правильный результат. Я попытался выяснить в справочной странице ctags, но не смог найти ее.
РЕДАКТИРОВАТЬ Да, это странно. Макрос есть
#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)
и комментарий говорит, что это
Совместимость с ANSI/K&R.
Он предназначен для сборки xlc, c-компилятора AIX.
1 ответ
С определением макроса, как показано:
#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)
эта декларация:
static void add_define P3(char *, name, int, nargs, char *, exps);
(Я добавил конечную точку с запятой) расширяется до этого:
static void add_define(char *name, int nargs, char *exps);
который является совершенно обычным прототипом функции (при условии конечной точки с запятой).
Вероятно, есть альтернативная версия этого макроса, что-то вроде этого:
#define P3(t1, v1, t2, v2, t3, v3) \
(v1, v2, v3) \
t1 v1; \
t2 v2; \
t3 v3;
это расширилось бы до:
static void add_define(name, nargs, exps)
char *name;
int nargs;
char *exps
который является объявлением функции не-прототипа в стиле K&R.
Вероятно, есть что-то вроде:
#ifdef __STDC__
#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)
#else
#define P3(t1, v1, t2, v2, t3, v3) \
(v1, v2, v3) \
t1 v1; \
t2 v2; \
t3 v3;
#endif
наряду с аналогичными макросами P0, P1, P2 и т. д. для различного числа параметров. Или, как вы подразумеваете в своем вопросе, он использует определяемый пользователем макрос __USE_FIXED_PROTOTYPES__
скорее, чем __STDC__
,
Это позволит одному объявлению автоматически расширяться либо до современного прототипа, либо до объявления в стиле K&R; последнее будет необходимо только с очень старыми пре-ANSI компиляторами.
Чтобы ответить на вопрос в заголовке (наконец-то!), ctags
работает на необработанном C-источнике. Быстрый эксперимент с GNU ctags
показывает, что не очень умно интерпретировать макросы, которые скрывают основной синтаксис. Он сгенерирует записи тегов для самих определений макросов, но не распознает
static void add_define P3(char *, name, int, nargs, char *, exps) {
/* ... */
}
как определение функции. (Вы можете запустить исходный файл через препроцессор, но тогда теги будут ссылаться на предварительно обработанный файл, что не особенно полезно.) В принципе, ctags
должен понимать полный синтаксис C, включая препроцессор; на практике это не так.
Если вы хотите иметь ctags
генерировать теги для вашего исходного файла, вам нужно избавиться от макросов и написать узнаваемые прототипы. Вы не сможете скомпилировать модифицированный исходный код с помощью пре-ANSI-компилятора, но в наши дни это вряд ли станет проблемой. Если вы в состоянии сделать это, полученный код будет легче поддерживать.
Или, так как вывод генерируется ctags
достаточно просто, не должно быть слишком сложно вручную добавить соответствующие теги в tags
файл (хотя поддерживать его автоматически может быть сложно).