c - 如何编写与#ifdef...#else...#endif C 预处理器宏匹配的 awk 程序?
问题描述
我有大量具有以下代码块的 C 程序语料库。
100. #ifdef DEBUG1
.
.
.
102. #else
.
.
.
105. #endif
或者,
200. #ifdef DEBUG2
.
.
.
206. #endif
此外,单个文件可能包含多个#DEBUG
宏。我想提取与宏对应的行号。假设代码片段中的数字是源文件中的行号,我希望输出采用以下格式:
FILE - MACRO_NAME - IFDEF - ELIF - ENDIF
----------------------------------------
prog.c - DEBUG1 - 100 - 102 - 105
prog.c - DEBUG2 - 200 - X - 206
我怎样才能编写一个awk
程序来实现相同的目标?如果awk
不是合适的工具,我可以使用什么工具?
解决方案
awk 实际上有关联数组,所以我会采取的方法是:
对于每个
#ifdef
(或等价物,例如#if 1
),增加一个变量,然后使用它来存储if
行号,将else
和endif
行号设置为 -1。对于
#else
一行,使用当前变量来设置else
行号。对于
#endif
, 输出您对行号的任何详细信息,然后递减变量。对于 an
#elif
,您需要组合#else
和#if
操作并确保相关#end
关闭所有行#if/#elif
。
例如,这是一个独立的bash
脚本,展示了它是如何工作的:
#!/usr/bin/env bash
# Use this script as input file as well, luckily C preprocessor
# macros look like bash comments.
#ifdef XYZZY
# Some text inside the first ifdef
#if 0
# This is the inner bit.
#endif
#if 1
# blah blah blah
#elif defined TWISTY
# yada yada yada
#elif defined PASSAGES
# run out of phrases
#else
# still got nothing
#endif
#else
#ifdef PLUGH
# This is the plugh stuff
#else
# This is the anti-plugh stuff
#endif
#endif
awk <$0 '
$1 == "#ifdef" || $1 == "#if" {
level++
line_mac[level] = $0
gsub(/^[ \t]+/, "", line_mac[level])
line_if[level] = NR
line_else[level] = "X"
line_end[level] = "X"
typ_elif[level] = 0
next
}
$1 == "#elif" {
line_else[level] = NR
level++
line_mac[level] = $0
gsub(/^[ \t]+/, "", line_mac[level])
line_if[level] = NR
line_else[level] = "X"
line_end[level] = "X"
typ_elif[level] = 1
next
}
$1 == "#else" {
line_else[level] = NR
next
}
$1 == "#endif" {
while (typ_elif[level] == 1) {
printf "if-line %-4s, else-line %-4s, endif-line %-4s, macro '%s'\n", line_if[level], line_else[level], NR, line_mac[level]
level--
}
printf "if-line %-4s, else-line %-4s, endif-line %-4s, macro '%s'\n", line_if[level], line_else[level], NR, line_mac[level]
level--
}
'
的输出(带有用于检查的文件中的编号行)是:
1: #!/usr/bin/env bash
2:
3: # Use this script as input file as well, luckily C preprocessor
4: # macros look like bash comments.
5:
6: #ifdef XYZZY
7: # Some text inside the first ifdef
8: #if 0
9: # This is the inner bit.
10: #endif
11: #if 1
12: # blah blah blah
13: #elif defined TWISTY
14: # yada yada yada
15: #elif defined PASSAGES
16: # run out of phrases
17: #else
18: # still got nothing
19: #endif
20: #else
21: #ifdef PLUGH
22: # This is the plugh stuff
23: #else
24: # This is the anti-plugh stuff
25: #endif
26: #endif
if-line 8 , else-line X , endif-line 10 , macro #if 0
if-line 15 , else-line 17 , endif-line 19 , macro #elif defined PASSAGES
if-line 13 , else-line 15 , endif-line 19 , macro #elif defined TWISTY
if-line 11 , else-line 13 , endif-line 19 , macro #if 1
if-line 21 , else-line 23 , endif-line 25 , macro #ifdef PLUGH
if-line 6 , else-line 20 , endif-line 26 , macro #ifdef XYZZY
推荐阅读
- php - 尝试将 PDF 发票上传到亚马逊 MWS 会导致错误:“上传发票时请仅提供一个有效的商城”
- nginx - Nginx - 将许多子域重定向到静态本地 IP
- python - PyRFC 中超过 200 个对话的最大数量错误
- java - 如何在此视图中添加 toast onFinishInflate
- python - SeqLog 无法获取本地颁发者证书
- javascript - 在 ReactJs 中干涸/重构组件
- c - 重新分配内存时的分段错误
- azure-sql-data-warehouse - 单个用户的最大并发槽数
- android - 如何将连续数据从活动传递到适配器?
- javascript - 谷歌标签管理器 - 变量 - Javascript