ctags是否支持GCC的固定原型功能?

时间:2012-12-23 02:04:58

标签: gcc vim ctags

我发现gcc支持一个奇怪的函数定义,如:

static void add_define P3(char *, name, int, nargs, char *, exps)

使用-D__USE_FIXED_PROTOTYPES__进行编译。而我的vim taglist插件无法给出正确的结果。我试图弄清楚ctags的手册页,但我找不到它。

修改 是的,这很奇怪。宏是

#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)

并且评论告诉我这是

  

ANSI / K& R兼容性内容。

它打算安装AIX的c编译器xlc。

1 个答案:

答案 0 :(得分:3)

使用如下所示的宏定义:

#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文件应该不会太困难(尽管自动维护它可能很困难)。