我們繼承了一個非常複雜的項目(500kloc),其中大部分已不再相關,並且我想清理它,其中lot預處理器條件邏輯。使用預處理器部分處理文件
我可以使用預處理器¹僅擴展條件邏輯的的一些,並將所有其他預處理器宏,定義和單獨包括在輸出中嗎?在這裏,「預處理器」,我的意思是「任何工具」,無論是標準的C預處理器,我可以安裝的東西,甚至是一個黑客一起的Perl或Python腳本。
舉例來說,假設我們有這套代碼:
#include <foo>
#define baz
#define bar(a) do{(a)+1} \
while(0)
#ifdef X
#if Y > 20
#if Z > 5
so_far_so_good = true;
#endif
#ifdef baz
something();
#endif
#else
otherthing();
#endif
#else
#if Z > 10
wow().this.is.bad;
#endif
#endif
的工具,我想(和可能需要的,如果不存在的話寫)將是一個版本CPP的接受不僅是特定調用的定義列表,而且是擴展期間要尊重的定義列表。任何不在第二個列表中的預處理器符號完全保留。一個例子是爲了:
cpptreadlight -DY=22 --only=Y
會產生:
#include <foo>
#define baz
#define bar(a) do{(a)+1} \
while(0)
#ifdef X
#if Z > 5
so_far_so_good = true;
#endif
#ifdef baz
something();
#endif
#else
#if Z > 10
wow().this.is.bad;
#endif
#endif
和:
cpptreadlight -DY=22 -DZ=8 -DX --only=Y,baz,Z
會給我:
#include <foo>
#define bar(a) do{(a)+1} \
while(0)
#ifdef X
so_far_so_good = true;
something();
#else
#endif
注意,即使X
定義,它被拋在後面,因爲它沒有出現在--only
列表中。還請注意,在列表中,baz
的值爲,因此在源中定義它之後進行擴展。
我嘗試了黑客的解決方案:逃避使用如下管道無趣的東西(我自己GSUB工具被使用,但它確實你所期望的):
function escape_tr() {
gsub "#(define|include)" '@@@\1' < $1 |
(echo '#include "simple.h"' && gsub '\\$' "%%%") |
cpp -C -P -DY=301 -DZ > $1.new
}
現在我可以過濾掉很多東西,然後把我希望預處理器擴展的東西放在simple.h
中。留下評論,#line
指令被遺漏。
這個差不多沒有訣竅,因爲那裏面沒有拉入,#define
塊沒有定義,所以沒有擴展到正文中。但是,它當然不會讓我指定我想要保留在輸出中的一組條件邏輯。那很糟。其中一些重要的是保持有條件。
#if
巢穴,和#else
和#endif
令牌不從詞彙上匹配,使問題超出正則表達式管道。我需要一個全面的解析器,與cpp本身幾乎完全相同,但是對擴展的內容進行了更精細的控制。
因此,在挖掘預處理器來實現它之前,我想我會問是否有人解決過這個問題。我不可能是唯一一個繼承了一個充滿死枝的預處理意大利麪條巢。
很快。謝謝! – clord 2010-11-10 19:02:38
確認這與原始問題中的'escape_tr' shell腳本相結合可以執行我想在此源代碼基礎上完成的所有操作。謝謝保羅。 雖然像'cpptreadlight'應該存在。它概括了'unifdef'和'cpp'。 – clord 2010-11-10 19:47:06
我不知道爲什麼你需要'escape_tr',但可能我錯過了一些東西。 – 2010-11-10 20:38:38