2013-12-16 149 views
2

我需要擴大單預處理指令,例如: 具有源文件和兩個頭,我想只有一個define從一個特定的頭部擴展,使所有其他includedefine完整。擴展一個C預處理指令

主要思想是,鑑於類似的代碼如下:

的defs.h:

#define FOO(X,op) int X(int a,int b) { return a op b; } 

other_file.h:

#define ONE 1 
#define TWO 2 
#define THREE 3 
#define FOUR 4 
#define FIVE 5 

的main.c:

"file: main.c " 
#include <stdio.h> 
#include "defs.h" 
#include "other_file.h" 
FOO(add,+) 
FOO(sub,-) 
FOO(mul,*) 
FOO(div,/) 

int main() 

{ 

    printf("%d\n",add(ONE,TWO)); 
    printf("%d\n",sub(THREE,FOUR)); 
    printf("%d\n",mul(FIVE,FIVE)); 
    printf("%d\n",div(25,FIVE)); 
    return 0; 
} 

我會有main.c輸出與包括相同,但將FOO擴展到創建的函數。我知道這個例子很愚蠢,但我打算在更大的代碼數據庫上運行它。

這樣做的動機是在宏中定義的函數中運行cccc。運行它的最簡單方法是展開這些宏。我也歡迎替代方法來做到這一點。

+1

你不能這樣做(除非對源文件進行了大量的預處理)。我會用一個更簡單的正則表達式的方法來做到這一點(只需用你喜歡的腳本語言編寫你自己的預處理器,perl?) –

+0

好吧,我更喜歡python。將「函數」(使用正則表達式)轉換爲臨時文件,運行預處理器並將其放回處理文件的想法太難看了嗎? –

+0

不,沒關係,但我不會覆蓋原始文件。例如,您可以將源文件從.C重命名爲.raw.C,並且您的預處理器可能會讀取所有.raw.C文件以生成純C文件。如果你不得不改變某些東西...... –

回答

1

你可以玩GCC的-E-nostdinc,-nostdinc++-fpreprocessed參數。

對於你的榜樣,你可以運行:

gcc -E -nostdinc -fpreprocessed main.c 

和輸出是:

# 1 "main.c" 
#include <stdio.h> 
#include "defs.h" 
#include "other_file.h" 
FOO(add,+) 
FOO(sub,-) 
FOO(mul,*) 
FOO(div,/) 

int main() 

{ 
    printf("%d\n",add(ONE,TWO)); 
    printf("%d\n",sub(THREE,FOUR)); 
    printf("%d\n",mul(FIVE,FIVE)); 
    printf("%d\n",div(25,FIVE)); 
    return 0; 
} 

如果頭沒有那麼複雜,就像在你的榜樣,您可以強制海灣合作委員會預處理整個文件,即使有一些丟失的宏。例如: -

cp other_file.h other_file.h_orig 
echo "" > other_file.h 
gcc -E -nostdinc main.c 

輸出:

# 1 "main.c" 
# 1 "<command-line>" 
# 1 "main.c" 
main.c:1:19: error: no include path in which to search for stdio.h 
#include <stdio.h> 
       ^

# 1 "defs.h" 1 
# 3 "main.c" 2 
# 1 "other_file.h" 1 
# 4 "main.c" 2 
int add(int a,int b) { return a + b; } 
int sub(int a,int b) { return a - b; } 
int mul(int a,int b) { return a * b; } 
int div(int a,int b) { return a/b; } 

int main() 

{ 
    printf("%d\n",add(ONE,TWO)); 
    printf("%d\n",sub(THREE,FOUR)); 
    printf("%d\n",mul(FIVE,FIVE)); 
    printf("%d\n",div(25,FIVE)); 
    return 0; 
} 

它將刪除標題夾雜物,雖然...並且將打印您性病頭一個錯誤,即到stderr,而不是標準輸出。

這適用於你的小例子,但在更大的代碼庫,你可能會面臨一些問題...

下面是參數從手動(海合會4.8.2)的簡短摘要:

-E:在預處理階段後停止;不要運行編譯器。輸出採用預處理源代碼的形式,將 發送到標準輸出。

-fpreprocessed:向預處理器指示輸入文件已被預處理。這抑制了諸如宏 擴展,三元圖轉換,換行換行和 處理大多數指令。

-nostdinc:不要搜索標準系統目錄中的頭文件。只有你用-I選項指定的目錄。

-nostdinC++:不要搜索特定於C++的標準目錄中的頭文件,而是仍然搜索其他標準目錄 。

-1

我們的DMS Software Reengineering Toolkit及其C Front End將做到這一點。

DMS提供通用程序解析/分析基礎結構。 C前端在此基礎上提供了一個全功能的C前端,並配有C預處理器。

通常情況下,DMS C預處理器的行爲與標準處理器一樣:它預處理所有內容,生成替代的令牌流。通常情況下,它可以配置爲不處理條件(這是全有或全無),或者僅擴展指定的宏。特別是,它接受聲明宏應該(不)擴展的自定義#pragma

我不清楚這是值得付出的努力。是的,如果您認爲該宏應該是非透明的,那麼在某些宏使用頻率較高的地方,衡量指標工具可能會產生更準確的答案。如果你認爲這個宏本質上只是一個有趣的子程序,那麼擴展這個宏就像內聯了一個函數體,而你不會那麼做計算度量。