2011-11-15 102 views
5

我想知道如何使用GCC作爲庫來解析我的程序的C/C++/Java/Objective C/Ada代碼。 我想繞過預處理,併爲用戶使用前綴My編寫的所有函數加上前綴。 像這樣Print();變成MyPrint();我也希望這樣做的變量。gcc解析代碼

+5

這是一個相當大的要求。你有什麼嘗試?你面臨哪些具體問題?你讀過海灣合作委員會鏈的手冊頁(沒有預處理和什麼)?此外,預處理可能不是獲取代碼在您的程序中工作所需的唯一步驟。你究竟想要做什麼? – Corbin

+0

我嘗試過使用鏗鏘聲,但我永遠無法得到它編譯。我不敢同情。什麼是海灣合作委員會鏈?我想跳過預處理,因爲我不想在文件中使用標題或宏。基本上我試圖做的是重命名函數和帶有前綴的變量。 – zeitue

+0

啊,我的意思是說gcc工具鏈。真的這是一個比我應該使用的更廣泛的術語。我應該剛剛說過gcc手冊頁,也許鏈接手冊頁取決於你在做什麼。 – Corbin

回答

3

你可以看這裏:
http://codesynthesis.com/~boris/blog/2010/05/03/parsing-cxx-with-gcc-plugin-part-1/

這是一個關於如何使用gcc的插件接口解析C++代碼的說明。其他語言應該以相同的方式處理。

您也可以從Mozilla的嘗試豬肉:
https://wiki.mozilla.org/Pork

當我想它(豬肉),我花了一小時左右,以解決編制問題,但後來 我可以編寫腳本是這樣的:

rewrite SyncPrimitiveUpgrade { 
    type PRLock* => Mutex* 
    call PR_NewLock() => new Mutex() 
    call PR_Lock(lock) => lock->Lock() 
    call PR_Unlock(lock) => lock->Unlock() 
    call PR_DestroyLock(lock) => delete lock 
} 

因此它找到所有類型的PRLock,並使用Mutex對它進行重新設定,並且它像PR_NewLock一樣搜索函數 的調用並將其替換爲「新Mutex」。

+0

我現在使用這個權利有麻煩我的代碼編譯可能是我的系統太新了。 – zeitue

+0

或者你的系統太舊了。gcc的插件支持是在gcc 4.5中引入的,所以如果你的gcc版本<4.5 ... – fghj

+0

我的系統是Ubuntu 11.10 gcc gcc-3.3 gcc-3.4 gcc-4.0 gcc-4.2 gcc-4.3 gcc-4.4 gcc- 4.5 gcc-4.6 – zeitue

2

您可能希望調查sparse C語法分析器。它理解很多C(Linux內核源代碼中使用的所有C,這是合法的ANSI-C和GNU-C擴展的相當好的子集),並提供了一些樣本編譯器後端,以提供類似lint的靜態分析工具用於類型檢查。

雖然代碼看起來非常乾淨徹底,但您的任務可能會通過另一種機制輕鬆完成 - sparse源代碼中包含的example.c演示編譯器的長度爲1955行。

+0

稀疏看起來不錯,但它沒有縫隙有C++支持。 – zeitue

+0

而且肯定沒有Java/Objective C/Ada。 :)它做C和只有C。 – sarnold

+0

泰勒說,稀疏看起來不錯,但沒有任何下載鏈接或該wiki上的git回購鏈接似乎工作: – Necrolis

2

對於C,你不能可靠地做到這一點。如果你跳過預處理,你將會 - 一般 - 沒有有效的C代碼被解析。例如。

#define FOO 
#define BAR 
#define BAZ 

FOO void BAR qux BAZ(void) { } 

解析器應該如何在不進行預處理的情況下識別qux的函數定義?

+0

我的意思是我想跳過預處理它,我不希望擴大宏,我不想在最終的代碼中的標題。 – zeitue

2

首先,GCC不是一個庫,並且不是一個結構(與LLVM相反)。

爲什麼要解析C,C++,Ada源代碼?

我會考慮(假設GCC 4.6版本)延伸 GCC任一通用C語言編寫的插件,或優選地使用MELT,一個高電平域專用語言來擴展GCC(聲明:我的主要作者熔化)。

但是使用GCC作爲庫是不現實的。

我真的認爲,對於你想要達到的目標,MELT是正確的工具。但是,它記錄不完善。請使用[email protected]列表提問。

請注意,擴展GCC的確需要一定的工作量(可能超過一週),因爲您需要部分理解GCC內部表示。

+0

MELT看起來像它會工作,但我試圖留在C/C++代碼中,因爲我的項目的其餘部分是寫在那,儘管我也知道Java並且正在學習Python和Vala。 – zeitue

2

忘了GCC,它作爲一個編譯器的解析器,而不是分析解析器做,你會做的更好的方式使用類似libclang,一個C接口clang,它可以處理Ç& C++

+0

幾個GCC插件能夠做一些分析,所以我認爲它可能是一個相關的工具。 –

+0

Basile:問題在於它們是插件,clang是從頭開始構建的,作爲分析器和解析器,儘管我認爲插件會減少工具鏈長度,但是tbh,我建議最近在GCC上使用LLVM + clang – Necrolis

+0

正在一個**編譯器插件**不能被視爲問題,而是**具有決定性的優勢**:該插件完全在編譯器內部工作,所以正好看到編譯器看到什麼以及編譯器的工作原理。另外,使用編譯器插件比一些外部工具更具破壞性:您基本上只需將一系列參數添加到makefile的CFLAGS或CXXFLAGS中。 –

2

我們DMS Software Reengineering Toolkit可以用各種各樣的方言解析C,C++,Java和Ada代碼(目前不是Objective C),並對代碼進行轉換。 DMS的C and C++前端包含一個預處理器,因此您可以在解析之前進行預處理。

我可能不明白你想要做什麼,因爲用「My ....」前綴重命名每個函數和(global?)變量似乎很奇怪。但是你可以做到這一點與一些DMS規則(用戶功能重命名的草圖爲GCC3:

domain C~GCC3. 

rule rewrite_function_names(t: type_designator, i: IDENTIFIER, p: parameter_list, s: statements): 
     function_header->functionheader 
"\t \i(\p) { \s } " -> "\t \renamed\(\i\) (\p) { \s }" ; 

和一個輔助功能「重命名」充分利用了包含IDENTIFER樹節點,並返回一個樹節點重命名的標識符。

因爲DMS模式只能比對分析樹,你不會得到任何誤報。

你會需要一些額外的圖案,每個的langauge內處理各種不同的語法情況下(例如,對於C,「void」返回類型,因爲「void」在語法和全局變量聲明中不是類型指示符), d針對不同語言的不同規則(Ada的語法與C的語法不同)。

這可能看起來像是你的任務的重頭戲,但如果你真的堅持以可靠的方式對各種語言進行操作,似乎很難避免爲所有這些語言獲得體面的解析器的問題。 (如果你真的要爲所有這些語言做到這一點,DMS可以被教導來處理ObjectiveC,就像我們教它處理其他語言一樣)。

你的選擇是某種字符串黑客解決方案,它可能在95%的時間內工作。如果你能忍受,那麼Perl或類似的東西可能就是你的答案。

+0

看起來像一個很好的解決方案,但它看起來是專有軟件。我現在沒有錢購買軟件,而且我也不使用Windows,除非我會使用它。 – zeitue