将 pragma 扩展为注释(对于 doxygen)

Expand pragma to a comment (for doxygen)

在预处理器运行之前,注释通常会被转换为单个白色-space。但是,有一个引人注目的用例。

#pragma once   

#ifdef DOXYGEN
  #define DALT(t,f) t
#else
  #define DALT(t,f) f
#endif

#define MAP(n,a,d) \
  DALT ( COMMENT(| n | a | d |) \
       , void* mm_##n = a \
       )

/// Memory map table
/// | name | address | description |
/// |------|---------|-------------|
MAP (reg0  , 0       , foo         )
MAP (reg1  , 8       , bar         )

在这个例子中,当设置了 DOXYGEN 标志时,我想从宏中生成 doxygen 标记。如果不是,我想生成变量。在这种情况下,所需的行为是在宏中生成注释。有什么想法吗?

我试过 /##/ 和另一个更间接的例子

#define COMMENT SLASH(/)
#define SLASH(s) /##s

两者都不起作用。

ISO C 标准将预处理器的输出描述为 预处理标记 的流,而不是文本。注释不是预处理标记;在标记化发生之前,它们会从输入中剥离。因此,在语言的标准设施内,预处理输出根本不可能包含注释或任何类似的东西。

特别考虑

#define EMPTY
#define NOT_A_COMMENT_1(text) /EMPTY/EMPTY/ text
#define NOT_A_COMMENT_2(text) / / / text
NOT_A_COMMENT_1(word word word)
NOT_A_COMMENT_2(word word word)

经过第四阶段翻译后,上面的第四行和第五行都将成为六令牌序列

[/][/][/][word][word][word]

其中方括号表示令牌边界。没有 // 令牌这样的东西,因此您无法使预处理器生成令牌。

现在,ISO C 标准没有指定 doxygen 的行为。然而,如果 doxygen 正在重用某个人的 C 编译器附带的预处理器,那么编写该预处理器的人可能认为文本预处理器输出首先应该是 "compiler proper" 将接收的标记序列的准确反映。这意味着它将在必要时强行插入空格,以使单独的标记保持独立。例如,上面的例子 test.c

$ gcc -E test.c
...
/ / / word word word
/ / / word word word

(我在我们感兴趣的输出之上删除了一些无关紧要的内容。)

如果有办法解决这个问题,您很可能会在 doxygen 手册中找到它。例如,可能有一些配置选项告诉它应该理解某些宏来定义符号,以及这些符号是什么,以及它们应该有什么文档。

在 doxygen 中,可以在将源输入到 doxygen 内核之前对它们执行 运行 命令。在 Doxyfile 中有一些 FILTER 可能性。在这种情况下:INPUT_FILTER 该行应显示为:

INPUT_FILTER = "sed -e 's%^ *MAP *(\([^,]*\),\([^,]*\),\([^)]*\))%/// | | | |%'"

此外,整个 #if 结构可能会消失,一个可能只需要:

#define MAP(n,a,d) void* mm_##n = a