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マクロだということが分かったので、とりあえずは満足です。