将 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
在预处理器运行之前,注释通常会被转换为单个白色-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