2013-02-12 33 views
4

我有一個代碼生成器,它將採取一些用戶編寫的代碼並將其塊嵌入到更大的生成文件中。我希望底層編譯器在用戶代碼存在缺陷時提供良好的診斷,但是我也不希望生成的代碼中的缺陷在它們不應該被錯誤地分配給源代碼時。重置C/C++預處理器#line物理文件/行

我打算在每個用戶編寫的代碼塊開始時發出#line lineNum "sourceFile"指令。但是,我找不到#line指令的任何文檔,它提到了一旦我離開用戶提供的代碼時,將「__LINE__」和「__FILE__」重置回生成文件中的實際行的技術。理想的解決方案將類似於C#預處理器的#line default指令。

我是否需要跟蹤自己寫了多少行並手動重置了自己?或者有沒有更好的方法,某種重置指令或標記值可以傳遞給#line以消除與用戶代碼的關聯?

看起來這可能是posed before,雖然沒有可靠的答案。爲了區分這一點,我還要問,C++ 11中是否存在缺少答案。

+0

您打算提供已經預處理的代碼嗎? – 2013-02-12 01:30:41

+0

不,它是從提供一些RPC接口定義和更高級別控制流的輸入生成更多有用的輸出。說明性(如果大的話)示例輸入是[this](http://charm.cs.illinois.edu/cgi-bin/gitweb2.cgi?p=charmlu.git;a=blob;f=lu.ci;h = 5d84a2f02a9d1e4d77767037b68078ff583bea57; HB = HEAD)。尋找用戶編寫的C++代碼的'原子'塊,這些代碼將逐字發送,我希望參考。輸出實際上在其他C++源文件中獲得'#include',並作爲這些文件的一部分進行預處理和編譯。 – Novelocrat 2013-02-12 01:34:48

+0

您是否可以在文件末尾發出用戶代碼,以便您不必切換行號/文件名稱? – 2013-02-12 01:38:59

回答

5

我以前使用過的一種技術是讓我的代碼生成器在想要重置行指令時自行輸出#,然後使用簡單的awk腳本對文件進行後處理並將其更改爲正確行指令:

#!/bin/awk -f 
/^#$/ { printf "#line %d \"%s\"\n", NR+1, FILENAME; next; } 
{ print; } 
0

是的,您需要跟蹤您輸出的行數,並且您需要知道要輸出的文件的名稱。請記住,您指定的行號是下一行的行號。所以,如果你寫12行,到目前爲止,你需要輸出#line 14 "filename",因爲#line指令會在第13行,所以下一行是14

有一個在C#line預處理指令沒有區別和C++

+0

'#line'指令的語法是'#line * digit-sequence *「* s-char-sequence *」'(或者只是'#line * digit_sequence *')。 – 2013-02-12 02:07:24

+0

@DavidHammen哎呀,的確,我把它們排錯了順序,修好了。我將它更改爲「文件名」,因爲它更像文字。沒有文件名的版本是,我認爲,沒有意義,因爲OP想切換文件名。 – rici 2013-02-12 02:10:58

0

假設輸入到代碼生成器,「user.code」,包含以下內容:

int foo() { 
    return error1(); 
} 

int bar() { 
    return error2(); 
} 

假設你要以擴大此,所以它看起來基本上是這樣的:

int foo() { 
    return error1(); 
} 

int generated_foo() { 
    return generated_error1(); 
} 

int bar() { 
    return error2(); 
} 

int generated_bar() { 
    return generated_error2(); 
} 

除非你不想那樣。您希望將#line指令添加到生成的代碼中,以便編譯器消息指示錯誤/警告是來自用戶代碼還是自動生成的代碼。 #line指令指示下一行代碼的源(而不是包含#line指令的行)。

#line 1 "user.code" 
int foo() { 
    return error1(); 
} 

#line 7 "generated_code.cpp" // NOTE: This is line #6 of generated_code.cpp 
int generated_foo() { 
    return generated_error1(); 
} 

#line 5 "user.code" 
int bar() { 
    return error2(); 
} 

#line 17 "generated_code.cpp" // NOTE: This is line #16 of generated_code.cpp 
int generated_bar() { 
    return generated_error2(); 
} 
-1

你嘗試過什麼__LINE____FILE__給你?我相信他們是從你的#line指令中獲得的(如果不是,那將是什麼意思?)。

(gcc-4.7.2和clang-3.1的快速測試證實了我的預感)。

+0

'#line'指令明確記錄爲準確重置這些宏。由於預處理器是一個懶惰的評估器,因此無法將它們'保存'到宏定義中以便以後恢復。 – Novelocrat 2013-02-12 04:13:48

0

@Novelocrat,

here之前問過這個問題,並沒有堅實的答案被張貼,但我想通了,如果行指令插入自動生成的代碼點到用戶代碼,然後這使得自動生成的代碼難以搬遷。您必須將自動生成的用戶代碼保留在編譯器可以找到它們以報告錯誤的位置。我認爲最好在生成的代碼中插入用戶代碼的文件名和行號。在優秀的文本編輯器中,通過將光標放在文件名上可以跳轉到文件中的某一行,這只是一些按鍵操作。

例如:在vim中將光標放在文件名上並按g-f將您帶到該文件,然後:42將您帶到出現錯誤的第42行(說)。

只要在這裏發佈這一點,讓別人提出相同的問題也可以考慮這個選擇。