読者です 読者をやめる 読者になる 読者になる

m4に入門した

内容はなんとなく分かりましたが、どう使ったらいいのかまだよく分かりません。わたしは言語の分類とかあまり詳しくないので雰囲気だけでもーと思うのですが……よく分かりません。再帰的なアレです。SQLのサブクエリとCASEを駆使してものすごい集計表をひとつのSQLで完成させたアノSQLのようなイメージ。どんなイメージやねんという-。

テキトウに雰囲気を

$ m4

とすると起動します。m4の出力は先頭に「=>」をつけます(実際にはつきません)。

define
マクロを定義
define(`x', `y')
x 
=> y
define(`y', 10)
x
=> 10
y
=> 10

という感じです。x→y→10, y→10と展開されてます。展開された結果もまだ展開できるなら展開されます。
ifがあるので駆使すれば再起関数(再起展開?)でループも書けます。

$#
引数の個数。
$N
N番目の引数。$1ならひとつ目の引数。
ifelse(string-1, string-2, equal, ...., opt not-equal)
string-1とstring-2が同じならequalに展開。
shift
引数リストを引数の先頭要素以外に展開。
eval
計算結果に展開。
define(`sum', `ifelse($#, 0, 0, $#, 1, $1, `eval(sum(shift($@)) + $1)')')
sum
=> 0
sum(1)
=> 1
sum(2, 3)
=> 5
sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
=> 55

展開後の結果がまた展開されて〜となってくると分けわかんなくなってきます。
そこでマクロのトレース機能が使えます。

debugmode
デバッグモードを変更(a=>実引数表示, e=>展開後テキスト表示など)。
traceon
マクロのトレースをon。traceon(sum)とするとsumだけをトレースする。
debugmode(`ac')
traceon
sum(1, 2, 3)
=> m4trace: -1- sum(1, 2, 3) -> ifelse(3, 0, 0, 3, 1, 1, `eval(sum(shift(`1',`2',`3')) + 1)')
=> m4trace: -1- ifelse(3, 0, 0, 3, 1, 1, eval(sum(shift(`1',`2',`3')) + 1)) -> eval(sum(shift(`1',`2',`3')) + 1)
=> m4trace: -3- shift(1, 2, 3) -> `2',`3'
=> m4trace: -2- sum(2, 3) -> ifelse(2, 0, 0, 2, 1, 2, `eval(sum(shift(`2',`3')) + 2)')
=> m4trace: -2- ifelse(2, 0, 0, 2, 1, 2, eval(sum(shift(`2',`3')) + 2)) -> eval(sum(shift(`2',`3')) + 2)
=> m4trace: -4- shift(2, 3) -> `3'
=> m4trace: -3- sum(3) -> ifelse(1, 0, 0, 1, 1, 3, `eval(sum(shift(`3')) + 3)')
=> m4trace: -3- ifelse(1, 0, 0, 1, 1, 3, eval(sum(shift(`3')) + 3)) -> 3
=> m4trace: -2- eval(3 + 2) -> 5
=> m4trace: -1- eval(5 + 1) -> 6
=> 6

『-1-』などの数値は展開の深さです。
あとシステムコマンドも使えたり、

esyscmd
コマンドを実行して出力を取り込む。
esyscmd(`date')
=> Sun Jul  1 01:22:16     2007

define(`Sun', `Kyoufu no Hi')

esyscmd(`date')
=> Kyoufu no Hi Jul  1 01:23:12     2007

なにかできそうな、できなさそうな。
configure.acがM4マクロだということが分かったので、とりあえずは満足です。