2016-04-23 165 views
2

我寫了用於測試的小型M4腳本(test.m4):爲什麼評估ifelse宏的「錯誤」表達?

define(`test', `ifelse(`$#', `1', `$1', test(shift([email protected])))') 
test(`arg1', `arg2') 

m4 test.m4 -t test -de 運行它。輸出是

m4trace: -1- test -> ifelse(`2', `1', `arg1', test(shift(`arg1',`arg2'))) 
m4trace: -2- test -> ifelse(`1', `1', `arg2', test(shift(`arg2'))) 
m4trace: -3- test -> ifelse(`1', `1', `', test(shift(`'))) 
m4trace: -4- test -> ifelse(`1', `1', `', test(shift(`'))) 
. 
. 
. 

直到由於超出遞歸限制而中止執行。我想知道爲什麼這樣,因爲實際上11應該比較相等,並且if else宏應評估爲`'

不過,我有創新的想法,把[not-equal]到引號,所以宏是這樣的:

define(`test', `ifelse(`$#', `1', `$1', `test(shift([email protected]))')') 
test(`arg1', `arg2') 

就萬事大吉了,它的工作就像一個魅力(即arg2是一起打印出來一個領先的換行符)。
輸出(具有相同的調用參數):

NL 
m4trace: -1- test -> ifelse(`2', `1', `arg1', `test(shift(`arg1',`arg2'))') 
m4trace: -1- test -> ifelse(`1', `1', `arg2', `test(shift(`arg2'))') 
arg2 

NL代表 「新行」)。

我的結論是:即使兩個比較的字符串實際上是相等的,但預處理器仍然評估[not-equal]分支。

這是否有任何特定的用途?國際海事組織,這只是不直觀的。或者我錯過了什麼?


-t test接通調試跟蹤用於在宏test-de將調用宏的定義添加到調試輸出中。

回答

3

雖然表達式相等(除引號之外),但它們的執行時間不同(由於引號)。

在第一種情況下,test宏在父代的test宏代理期間被執行。所以你會遇到一個遞歸:測試裏面的測試,等等。

第二種情況使表達式在AFTERWARDS後執行。所以你沒有遞歸。測試後測試後測試。

This behaviour is very well described in the manual.

節「16.3其它不兼容」:

在像這樣的,對於宏持有自己的名字會是一個無用的限制停職個案。當然,這爲GNU m4用戶留下了更多的 繩索!