Go to the first, previous, next, last section, table of contents.


M4でのプログラミング

Autoconfは,二つのレイヤーのトップに書かれています.それは,純粋なM4プ ログラムで便利なマクロを提供しているM4sugarと,シェルスクリプト の生成に専念するマクロを提供するM4shです.

このバージョンのAutoconfでは,二つのレイヤーはまだ実験段階で,そのイン ターフェースは将来変更される可能性があります.実際問題,文章化さ れていないものは使用しないでください

M4の引用符

既存のマクロの最も一般的な問題は,不適当な引用符です.このセクションで は,Autoconfのユーザは飛ばすことができますが,マクロを書く人は読む 必要があり,最初にAutoconfで採択された引用符を利用する方法を正 当化し,最後に経験則を述べます.前者を理解すると後者で役立ちます.

アクティブな文字

適切な引用符の重要性を完全に理解するため,最初にAutoconfでの特殊な文字 が何かを知る必要があります.`#'はマクロ展開が実行されない内部コメ ントの導入で,`,'は引数のセパレータ,`['`]'はそれらの 引用符,そして最後は,(M4が対の一致を試みる)`('`)'です.

マクロ呼び出しの微妙な状況を理解するために,最初に明らかな失敗を紹介し なければならないでしょう.以下で"明確にされ"ていて,実生活でも見つか るでしょうが,それらは通常ごまかしです.

ハッシュと改行まで実行することで導入されるコメントは,トップレベルへの 不明瞭なトークンです.アクティブな文字はそうではなくなり,マクロの展開 もありません.

# define([def], ine)
=># define([def], ine)

マクロの展開があるごとに,引用符も展開されます.すなわち,第一レベルの 引用符は削除されます.

int tab[10];
=>int tab10;
[int tab[10];]
=>int tab[10];

これを覚えていなければ,読者は絶望しながらもマクロのarrayを使用 してみるでしょう.

define([array], [int tab[10];])
array
=>int tab10;
[array]
=>array

期待する結果を正しく出力するにはどうすれば良いでしょうか (2)

一つのマクロの呼び出し

さて,アクティブな文字と以下の単に最初の引数を返す小さなマクロを用いた マクロで,対話的に進めていきましょう.

define([car], [$1])

上記の二組の引用符はdefineの引数の一部ではありません.そうでは なく,defineの引数の検索が試みられるときに,それらはトップレベ ルで理解されます.そのため,それは以下のように書くことと等価です.

define(car, $1)

しかし,`configure.ac'が不必要な引用符を避けることは受け入れても かまいませんが,より強固で,完全な形式を提案する必要もあるAutoconfマク ロにとっては悪い慣習です.

トップレベルでは,二つの可能性があります.引用符で囲む,または囲まない での二つです.

car(foo, bar, baz)
=>foo
[car(foo, bar, baz)]
=>car(foo, bar, baz)

特殊文字に注目してみましょう.

car(#)
error-->EOF in argument list

閉じカッコはコメント内に隠れてしまいます.引用符を推測することで,トッ プレベルでは以下のように理解します.

car([#)]

適切な引用符は,もちろんこの問題を修正します.

car([#])
=>#

読者は,以下の例の方が理解しやすいかもしれません.

car(foo, bar)
=>foo
car([foo, bar])
=>foo, bar
car((foo, bar))
=>(foo, bar)
car([(foo], [bar)])
=>(foo
car([], [])
=>
car([[]], [[]])
=>[]

これを覚えていると,マクロがマクロを呼び出し,マクロがマクロを呼び出し ...となっているような状況も調査することが可能です.

引用符と入れ子状のマクロ

これ以降の例では,以下のマクロを使用しています.

define([car], [$1])
define([active], [ACT, IVE])
define([array], [int tab[10]])

追加の埋め込まれたマクロ呼び出しは,それぞれ興味深い引用符について,そ の他の可能性を導き出します.

car(active)
=>ACT
car([active])
=>ACT, IVE
car([[active]])
=>active

最初の状況では,トップレベルではcarの引数を探し,`active' が見つかります.M4はマクロを適用する前のその引数と等価なので, `active'は展開され,結果として以下のようになります.

car(ACT, IVE)
=>ACT

二番目の状況では,トップレベルはcarの最初で唯一の引数として `active'を与えるので,結果として以下のようになります.

active
=>ACT, IVE

すなわち,マクロが呼び出された後で,引数が評価されます.三番目 の状況では,car`[active]'を受けとり,結果として以下のよ うになります.

[active]
=>active

上記で見たものと同じですね.

より現実的な例を適用して,上記の例に与えてみましょう.

car(int tab[10];)
=>int tab10;
car([int tab[10];])
=>int tab10;
car([[int tab[10];]])
=>int tab[10];

う〜ん? 最初の状況は簡単に理解できますが,なぜ二番目が間違っていて, 三番目は正しいのでしょうか?それを理解するために,M4がマクロを展開した 後,結果として生じるテキストがすぐにマクロを展開に従って引用符が取り除 かれることを知っておく必要があります.これは,引用符の削除が二回行なわ れることを意味します -- 最初に引数としてcarマクロに渡されると き,二回目はcarマクロが最初の引数を展開するときです.

Autoconfマクロcarの作者として,ユーザがcarの引数を二重の 引用符にする必要があることは間違っていると考えるようにし,マクロを 修正してください.引用符で囲まれているcarに対して,それ をqarと呼ぶことにしましょう.

define([qar], [[$1]])

そして,qarが適切に修正されていることを調査してみます.

qar([int tab[10];])
=>int tab[10];

あぁ!そうした方が良さそうですね.

しかし,自分が行なったことに注意してください.現在その引数はリテラル文 字列ですが,引数を展開した結果をユーザが使用したい場合,引用符で 囲まれていないマクロを使用する必要があります.

qar(active)
=>ACT

carを用いて行なっていたことを再生成したい状況を考えます.

car([active])
=>ACT, IVE

まだ駄目ですね.cppマクロの組を生成するマクロを使用したい状況を 考えてみましょう.

define([my_includes], [#include <stdio.h>])
car([my_includes])
=>#include <stdio.h>
qar(my_includes)
error-->EOF in argument list

このマクロqarは,引数を二重に引用符で囲むので,ユーザはマクロの 呼び出しを引用符で囲まないままにしておくよう強制されるので,それは危険 です.カンマとその他のアクティブなシンボルは,マクロに渡される前にM4で 解釈され,それはユーザが期待している手法ではないことが多いものです.ま た,qarは,他のマクロとは異なる動作をするので,Autoconfでは避け るべき例外になります.

changequoteの弊害

特に夜も遅くなると,適切な引用符をバイパスする誘惑が大きくなることも多 いものです.そして,経験豊富なAutoconfのハッカーの多くは,最終的に暗黒 の力に支配され,最終兵器を持ち出します.それはchangequoteです.

M4組み込みのchangequoteは,言語の構文を必要に応じて調整すること を可能にするプリミティブの組に属しています.例えば,M4では引用符として デフォルトで``'`''を使用しますが,シェルプログラムの文脈 (そして,ほとんどの実際のプログラミング言語)では,それは利用可能なもの の中での最悪の選択です.シェルコードでの(`'this''``that`' のような)文字列とバッククオートされた式と,通常のプログラミング言語で 使用される(`'0''のような)リテラル文字のため,多くの対にならない ``'`''が存在します.そのような文脈での厳密なM4の引用符が (変更)不可能な場合は,悪夢になります.そのような文脈でM4を役立たせるた め,それを設計した人は別の引用符の組の選択を可能にする changequoteを装備しました.M4sugar,M4sh,Autoconf,そして Autotestでは,すべてのものが`['`]'の使用を選択しています. それらが滅多に使用されない文字という理由だけでなく,対にならない ことも滅多に無い文字という理由もあります

構文形式がコメントだということを指定するため(M4がHTMLページを生成する ために使用されるとき,`changecom(<!--, -->)'が一般的だと分かるで しょう)のchangecomと,それ以外の構文の詳細を変更するための changewordchangesyntax(n番目の引数を示す,デフォルトで `$'となっている文字や,引数の周りを囲むカッコなど)のような,それ 以外のマジックプリミティブもあります.

これらのプリミティブは,特定の分野に対してM4がより役に立つようにするた め,本当に意味があるものです.それらはコマンドラインオプションのように 考えるべきです.それらは,@option{--quotes},@option{--comments}, @option{--words},そして--syntaxのようなものです.それにもかか わらず,M4ライブラリ自身が含まれる(追加のオプションが必要無い)ように, M4の組み込みとして実装されています.

そこに問題があります@enddots{}

問題は,M4スクリプトの途中で,その初期化を目的としてそれを使用するとき に発生します.これは,あまり注意していない場合,甚大な影響があるはずで す.実行の途中で言語を変更しているようなものです.構文の変更と それからの復帰が十分でないことが多いものです.その間でマクロの呼び出し を行なった場合,現在の構文はおそらくマクロを実装していないので,これら のマクロは失われることになります.

四文字表記

Autoconfマクロを書いているとき,標準的なAutoconfの引用符の規則で表現す ることが難しい,特殊な文字を生成する必要が生じるかもしれません.例えば, `['以外の全ての文字に一致する正規表現`[^[]'を出力する必要が あるかもしれません.この表現は,対称ではないカッコを含んでいるので,M4 マクロの中に簡単に書き込むことはできません.

以下の四文字表記(quadrigraph)の一つを使用することで,この問題を 解決することが可能です.

`@<:@'
`['
`@:>@'
`]'
`@S|@'
`$'
`@%:@'
`#'
`@&t@'
何にも展開されません.

四文字表記は,@command{m4}が実行された後,変換処理の終りの段階で置換さ れるので,M4の引用符の邪魔になりません.例えば,文字列`[^@<:@]' は,その引用符で囲まれている状態に依存せず,出力では`[^[]'として 現れます.

空の四文字表記を使用することも可能です.

`@&t@'の名前はPaul Eggertの提案です.

私は,`@&t@'の語呂合わせに称賛を与えるべきでしょう.`&'は 私自身の発明ですが,`t'はSteve Bourne(Bourneシェルで有名です)によっ て書かれたALGOL68Cコンパイラのソースコードが由来となっていて,そ こでは空の文字列を示すために`mt'を使用しています.Cでは,それは以 下のようなものになるでしょう.

char const mt[] = "";

しかし,ソースコードは当然Algol 68で書かれています.

彼が`mt'を得た場所を,私は知りません.それは独自の発明かもしれま せんし,当時のケンブリッジ大学のコンピュータ研究所で,一般的な語呂合わ せだったのかもしれません.

引用符の経験則

終りに引用符の経験則を述べます.

カッコの組ごとに引用符の組

特にマクロ定義では,多過ぎる引用符もだめ,少な過ぎる引用符も駄目です. カッコを使用する必要があるマクロ(通常Cのプログラム文や正規表現の中)で は,適切に引数を引用符で囲んでください!

以下のような断片を用いたAutoconfプログラムを読むことはよくあります.

AC_TRY_LINK(
changequote(<<, >>)dnl
<<#include <time.h>
#ifndef tzname /* For SGI.  */
extern char *tzname[]; /* RS6000 and others reject char **tzname.  */
#endif>>,
changequote([, ])dnl
[atoi (*tzname);], ac_cv_var_tzname=yes, ac_cv_var_tzname=no)

それは,AC_TRY_LINKすでに二重に引用符で囲まれているの で, 全く無駄になり,実際は以下のようにするだけで十分です.

AC_TRY_LINK(
[#include <time.h>
#ifndef tzname /* For SGI.  */
extern char *tzname[]; /* RS6000 and others reject char **tzname.  */
#endif],
            [atoi (*tzname);],
            [ac_cv_var_tzname=yes],
            [ac_cv_var_tzname=no])

M4に親しんでいる読者は,M4が引数をまとめる(collect)ときに `changequote(<<, >>)'`<<' `>>'の両方を飲み込むので, これら二つの例が厳密に等価であることに注意してください.これらの引用符 は引数の一部ではありません!

単純にしてみると,上記の例は以下のようになります.

changequote(<<, >>)dnl
<<[]>>
changequote([, ])dnl

その代わりに単純に以下のようにします.

[[]]

引数を(規則で)二重に引用符で囲まないマクロを用いると,二重の引用は(危 険な)文字列になります.

AC_LINK_IFELSE([AC_LANG_PROGRAM(
[[#include <time.h>
#ifndef tzname /* For SGI.  */
extern char *tzname[]; /* RS6000 and others reject char **tzname.  */
#endif]],
                                [atoi (*tzname);])],
               [ac_cv_var_tzname=yes],
               [ac_cv_var_tzname=no])

引用符が十分でない状況で望みがなくなった場合どうすればいいかということ については,See section 四文字表記.

新たに書かれたマクロを用いて@command{configure}スクリプトを作成すると き,マクロにより多くの引用符を加える必要があるかどうかの調査は,気を付 けて吟味してください.一つ以上の単語がM4の出力に現れない場合,より多く の引用符が必要になります.迷ったときは引用符です.

しかし,引用符のレイヤーが多過ぎる可能性もあります.この場合は,結果と して得られる@command{configure}スクリプトは,展開されていないマクロが 含まれているでしょう.@command{autoconf}プログラムは,@samp{grep AC_ configure}を行なうことでこの問題を調査します.

@command{autom4te}の呼び出し

Autoconf自身のものに加え,M4sugar,M4sh,そしてAutotestを含めた Autoconfスイートは,M4にかなり依存しています.使い方が異なるこれらはす べて,@command{m4}の上のレイヤーに集約したいという共通の要求を具体化し ました.それは@command{autom4te}(3)です.

@command{autom4te}は,基本的に@command{m4}自身に置き換わるものとして考 慮されるべきです.

@command{autom4te}の呼び出し

コマンドライン引数は,M4のものをモデルにしています.

autom4te options files

ここでのfilesは,直接@command{m4}に渡すものです.正規の展開に加 え,それは四文字表記(see section 四文字表記)と,出力の現在の行の `__oline__'の置換を処理します.それは,filesに対して拡張さ れた構文もサポートしています.

`file.m4f'
このファイルは,M4を固めたファイルです.以前のファイルはすべて無 視されることに注意してください.正当性については,オプション @option{--melt}を参照してください.
`file?'
ライブラリパスで見つかった場合,fileは展開に含められ,それ以外で は,異常終了を発生する代わりに無視されます.

もちろん,それはAutoconfの一般的のオプションのサブセットをサポートして います.

@option{--help}
@option{-h}
コマンドラインオプションの概要を出力し,終了します.
@option{--version}
@option{-V}
Autoconfのバージョンナンバーを出力し,終了します.
@option{--verbose}
@option{-v}
処理しているステップを報告します.
@option{--debug}
@option{-d}
一時的なファイルを削除せず,さらに冗長になります.
@option{--include=dir}
@option{-I dir}
入力ファイルをdirでも探します.複数回の呼び出しは累積されます.
@option{--output=file}
@option{-o file}
(スクリプトやトレースの)出力をfileに保存します.ファイル @option{-}は標準出力を意味します.

@command{m4}の拡張として,それらは以下のオプションが含まれます.

@option{--warnings=category}
@option{-W category}
(実際にはカンマで分けられたリストになっている)categoryに関連する 警告を報告します.カテゴリの包括的なリストは,マクロAC_DIAGNOSE のSee section メッセージの報告. 以下の特殊な値が含まれます.
`all'
すべての警告を報告します.
`none'
何も報告しません.
`error'
警告をエラーとして扱います.
`no-category'
categoryに分類される警告を利用不可能にします.
`syntax'に関する警告は,デフォルトで利用可能で,カテゴリのカンマ で分離されたリストの環境変数WARNINGSは尊重されます. @command{autom4te -W category}は,実際に悪いことを実行したかのよ うに動作します.
autom4te --warnings=syntax,$WARNINGS,category
@command{autom4te}のデフォルトとWARNINGSを利用不可能にしたいけ れども,(例えば)時代遅れの構成物に関する警告は利用可能にしたい場合, @option{-W none,obsolete}を使用するべきでしょう. @command{autom4te}はエラーのバックトレースを表示しますが,警告は表示し ません.警告も表示したい場合,@option{-W error}を渡してください.例え ば以下のような`configure.ac'を考えます.
AC_DEFUN([INNER],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([exit (0)])])])

AC_DEFUN([OUTER],
[INNER])

AC_INIT
OUTER
以下のようになるでしょう.
$ autom4te -l autoconf -Wcross
configure.ac:8: warning: AC_RUN_IFELSE called without default \
to allow cross compiling
$ autom4te -l autoconf -Wcross,error -f
configure.ac:8: error: AC_RUN_IFELSE called without default \
to allow cross compiling
acgeneral.m4:3044: AC_RUN_IFELSE is expanded from...
configure.ac:2: INNER is expanded from...
configure.ac:5: OUTER is expanded from...
configure.ac:8: the top level
@option{--melt}
@option{-m}
固められたファイルを使用しません.すべての引数file.m4ffile.m4で置換されます.これは,ファイルが固められていると きだけに実行されるマクロ,通常はm4_defineの追跡で役に立ちます. 例えば以下のように実行します.
autom4te --melt 1.m4 2.m4f 3.m4 4.m4f input.m4
これは以下を実行したのと等価です.
m4 1.m4 2.m4 3.m4 4.m4 input.m4
一方,以下を実行した場合を考えます.
autom4te 1.m4 2.m4f 3.m4 4.m4f input.m4
これは以下と等価です.
m4 --reload-state=4.m4f input.m4
@option{--freeze}
@option{-f}
固まった状態のファイルを生成します.@command{autom4te}の固め方は,M4よ り厳密です.警告を生成させたり,空の行(空白行は空の行ではありま せん) とコメント(`#'で始まります)以外の出力を生成してはいけませ ん.@command{m4}とは異なり,このオプションは以下のように引数をとらない ことに注意してください.
autom4te 1.m4 2.m4 3.m4 --freeze --output=3.m4f
これは以下に対応します.
m4 1.m4 2.m4 3.m4 --freeze-state=3.m4f
@option{--mode=octal-mode}
@option{-m octal-mode}
octal-modeにトレース出力以外のモードを設定します.デフォルトは `0666'です.

それ以外の@command{m4}上の追加機能として,@command{autom4te}がその結果 をキャッシュするというものがあります.@acronym{GNU} M4は,標準出力を生 成すると同時にトレースすることが可能です.トレースは@acronym{GNU}ビル ドシステムで重点的に使用されています.@command{autoheader}は, `config.h.in'をビルドするために,@command{autoreconf}は,使用され ている@acronym{GNU}ビルドシステムの構成要素を決定するために, @command{automake}は`configure.ac'をパースするため等として使用し ています.@command{m4}の長い実行結果を保存するために,通常の展開を実行 している間,トレースはキャッシュされます(4).このキャッシュ(実際に は複数ある) は,ディレクトリ`autom4te.cache'に保存されます.いつ でも削除して大丈夫です(特に,理由があれば@command{autom4te}はそ れが捨てられてしまったと考えます).

@option{--cache=directory}
@option{-C directory}
結果をキャッシュするディレクトリの名前を指定します.空の値を渡すことで キャッシュが利用不可能になります.グローバルキャッシュがサポートされる ときまで,相対パスで渡してください.
@option{--no-cache}
結果をキャッシュしません.
@option{--force}
@option{-f}
キャッシュが使用されている場合,時代遅れだと考えません(しかし,それは いずれにせよ更新されます).

トレースは@acronym{GNU}ビルドシステムに重きをおいて実装されているので, @command{autom4te}は,M4と比較して高度なトレース機能を提供していて, キャッシュを利用する手助けとなります.

@option{--trace=macro[:format]}
@option{-t macro[:format]}
formatによって,macroの呼び出しをトレースします.複数の @option{--trace}引数は,いくつかのマクロリストを使用するために使用可能 です.単一マクロに対する複数の@option{--trace}引数は累積されません.そ の代わりに,必要な長さのformatにすべきです. formatは,必要なときは改行を用いていて,特殊なエスケープコードを も用いている通常の文字列です.デフォルトは`$f:$l:$n:$%'です.以下 の特殊なエスケープ文字が使用可能です.
`$$'
文字`$'
`$f'
macroが呼び出されているファイル名.
`$l'
macroが呼び出されている行番号.
`$d'
macro呼び出しの深さ.これはM4の技術的な詳細で,特に知りたいとは 思わないでしょう.
`$n'
macroの名前.
`$num'
macro呼び出しのnum番目の引数.
`$@'
`$sep@'
`${separator}@'
文字sepまたは文字列separatorで分離されている,マクロに渡さ れているすべての引数(デフォルトは`,').それぞれの引数は引用符で囲 まれています.すなわち,角カッコの組で囲まれています.
`$*'
`$sep*'
`${separator}*'
上と同じですが,引数は引用符で囲まれていません.
`$%'
`$sep%'
`${separator}%'
上と同じですが,引数は引用符で囲まれておらず,引数内部のすべての改行文 字は取り除かれていて,そして,デフォルトの分離子は`:'です. エスケープの`$%'は,(`separator'に改行を書き込まない限り)一 行のトレース出力を生成しますが,`$@'`$*'はそうではありま せん.
トレースの使用例はSee section @command{configure}を作成するため@command{autoconf}を使用する.
@option{--preselect=macro}
@option{-p macro}
macroのトレースをキャッシュしますが,キャッシュを利用可能にしま せん.これは特に,将来のCPUサイクルを無駄にしないために重要です.例え ば呼び出し時に,@command{m4}の実行でトレースする必要が無いように, @command{autoconf}は@command{autoheader},@command{automake}, @command{autoreconf}などがトレースするすべてのマクロを前もって選択しま す.キャッシュは十分です.これは結果として非常に高速になります.

最後に,@command{autom4te}は@dfn{Autom4teライブラリ(Autom4te libraries)}の概念を導入します.それらは,強力ですが非常にシンプルな機 能から成り立っています.コマンドライン引数の組み合わせの組です.

@option{--language=language}
@option{-l =language}
languageをAutom4teライブラリで使用します.現在の言語は以下のもの が含まれています.
M4sugar
M4sugar出力を作成します.
M4sh
M4shの実行可能なシェルスクリプトを作成します.
Autotest
Autotestの実行可能なテストスイートを作成します.
Autoconf
Autoconfの実行可能なコンフィグレーションスクリプトを作成します.
@option{--prepend-include=dir}
@option{-B dir}
検索パスにディレクトリdirを前置します.これは,サードパーティー のマクロの前に,言語指定ファイルを含めるために使用します.

例として,Autoconfがデフォルトの場所`/usr/local'にインストールさ れている場合,`autom4te -l m4sugar foo.m4'を実行することは, `autom4te --prepend-include /usr/local/share/autoconf m4sugar/m4sugar.m4f --warning syntax foo.m4'を実行することと厳密に等価 となります.再帰的な展開も適用します.`autom4te --language m4sh foo.m4'を実行することは,`autom4te --language M4sugar m4sugar/m4sh.m4f foo.m4'と同じで,すなわち,`autom4te --prepend-include /usr/local/share/autoconf m4sugar/m4sugar.m4f m4sugar/m4sh.m4f --mode 777 foo.m4'と同じになります.言語の定義は, `autom4te.cfg'に保存されます.

@command{autom4te}のカスタマイズ

`~/.autom4te.cfg' (すなわち,ユーザのホームディレクトリにあるとき) と,`./.autom4te.cfg' (すなわち,@command{autom4te}が実行されるディ レクトリにあるとき)で,@command{autom4te}をカスタマイズすることが可能 です.順番として,最初に`autom4te.cfg'を読み込み,そして `~/.autom4te.cfg',そして`./.autom4te.cfg',そして最後にコマ ンドライン引数を読み込みます.

これらのテキストファイルでは,コメントは#ではじまり,空の行は無 視されます.カスタマイズは,言語ごとを基本に実行され, `begin-language: "language"'`end-language: "language"'の組みで囲まれます.

言語のカスタマイズとは,現在の言語の定義にオプションを追加すること (see section @command{autom4te}の呼び出し)を意味します.オプションと一般的な引数は, `args: arguments'で始まります.argumentsを引用符で囲 むことによって伝統的なシェルの構文を使用してもかまいません.

例として,Autoconfのキャッシュ(`autom4te.cache')を大域的に利用不 可能にするため,以下の行を`~/.autom4te.cfg'に含めます.

@verbatim ## ------------------ ## ## User Preferences. ## ## ------------------ ##

begin-language: "Autoconf" args: --no-cache end-language: "Autoconf"

M4sugarでのプログラミング

M4自身は非常に小さいけれど十分な,汎用マクロの組を提供しています. M4sugarは,追加の一般的なマクロを導入しています.その名前は,Lars J. Aas によってつくり出されました:"Readability And Greater Understanding Stands 4 M4sugar".

M4マクロの再定義

いくつか例外がありますが,全てのM4ネイティブなマクロは,`m4_'疑似 名前空間に移動されていて,例えば,M4sugarではdefinem4_defineに名前を変えるなどのようになっています.

M4マクロには再定義されているものもあり,ネイティブな同義語とわずかに互 換性がなくなっています.

Macro: dnl
このマクロは,もともとの名前を維持しています.m4_dnlは定義され ていません.

Macro: m4_defn (macro)
M4組み込みのものと比較して,このマクロは,macroが定義されていな い場合は失敗します.m4_undefineを参照してください.

Macro: m4_exit (exit-status)
このマクロはm4exitに対応します.

Macro: m4_if (comment)
Macro: m4_if (string-1, string-2, equal, @ovar{not-equal})
Macro: m4_if (string-1, string-2, equal, ...)
このマクロはifelseに対応します.

Macro: m4_undefine (macro)
M4組み込みのものと比較して,このマクロは,macroが定義されていな い場合は失敗します.以下のように使用してください.
m4_ifdef([macro], [m4_undefine([macro])])

それで,組み込みのものの動作に復旧します.

Macro: m4_bpatsubst (string, regexp, @ovar{replacement})
このマクロはpatsubstに対応します.m4_patsubstの名前は, epatsubstで拡張した正規表現の構文を提供する,@acronym{GNU} M4の 最上位のM4shの将来のバージョンに対して残されています.

Macro: m4_popdef (macro)
M4組み込みのものと比較して,このマクロは,macroが定義されていな い場合は失敗します.m4_undefineを参照してください.

Macro: m4_bregexp (string, regexp, @ovar{replacement})
このマクロはregexpに対応しています.m4_regexpの名前は, eregexpで拡張した正規表現の構文を提供する,@acronym{GNU} M4の最 上位のM4shの将来のバージョンに対して残されています.

Macro: m4_wrap (text)
このマクロはm4wrapに対応しています.

二つの連続して呼び出されるm4_wrapが,そのままトークンとして渡さ れるという予期しない結果となる危険が無いように,text`[]' で終えることが推奨されます.

m4_define([foo], [Foo])
m4_define([bar], [Bar])
m4_define([foobar], [FOOBAR])
m4_wrap([bar])
m4_wrap([foo])
=>FOOBAR

マクロの評価

以下のマクロは,引用符のレベルを追加したり削除したりすることで,評価の 順序全体を制御するものです.それらは,ハードコアなM4プログラマに対して 意味があります.

Macro: m4_dquote (arg1, ...)
引用符で囲まれたリストを引用符で囲んだ引数を返します.

Macro: m4_quote (arg1, ...)
単一の要素として引数を返し,すなわち,一つの引用符の組でそれらを囲みま す.

以下の例は,(i)これらの例を使用していない,(ii)m4_quoteを使用し ている,(iii)m4_dquoteを使用している,といったそれぞれの間の差 を強調することを目的としています.

$ cat example.m4
# Overquote, so that quotes are visible.
m4_define([show], [$[]1 = [$1], $[]@ = [$@]])
m4_divert(0)dnl
show(a, b)
show(m4_quote(a, b))
show(m4_dquote(a, b))
$ autom4te -l m4sugar example.m4
$1 = a, $@ = [a],[b]
$1 = a,b, $@ = [a,b]
$1 = [a],[b], $@ = [[a],[b]]

禁止されているパターン

M4sugar提供の目的は,怪しげはパターン,つまり出力に現れるべきではない トークンを記述しているパターンを定義するためです.例えば,Autoconf `configure'スクリプトに`AC_DEFINE'`dnl'のようなトーク ンが含められている場合,おそらく何か問題が発生するでしょう(通常は,余 分な引用符のためにマクロが評価されていないためです).

M4sugarは,`^m4_'`^dnl$'に一致する全てのトークンを禁止しま す.

Macro: m4_pattern_forbid (pattern)
出力で見つかる必要のあるpatternにマッチするトークンを宣言しませ ん.コメントは調査されません.これは,例えば,`#include'より後に 展開されないまま残っているマクロがある場合に問題になるはずです.現在, Autoconf コミュニティでは合意がとおらず,コメント内で指名されているマ クロを有効にすべきだと考えている人もいるからです(`#'のコメントは 出力を説明するべきで,`dnl'コメントのように入力を説明するのではな いため,このドキュメントの著者には意味がありません).

もちろん,これらの一般的な規則の例外に遭遇する可能性もあり,例えば, `$m4_flags'を参照する必要があるかもしれません.

Macro: m4_pattern_allow (pattern)
patternに一致している全てのトークンが可能で,それには m4_pattern_forbidパターンに一致しているものも含まれます.

M4shでのプログラミング

M4shは,"mash"と発音し,移植性の高いBourneシェルスクリプトを生成する ことが狙いです.この名前はLars J. Aasが発明し,Webster's Revised Unabridged Dictionary (1913)にメモがあります(5)}.

Mash \Mash\, n. [Akin to G. meisch, maisch, meische, maische, mash, wash, and prob. to AS. miscian to mix. See "Mix".]

  1. 混合成分の塊を,こう解や圧搾でパルプ状に軟らかくして絞った@enddots{}
  2. 動物に与える粉餌やぬかと水を混ぜたもの.
  3. 混乱.トラブル. [Obs.] --Beau. & Fl.

今しばらくは,広範囲の使用に十分なほど熟していません.

M4shは,実験してみると残念ながら移植性が無い,一般的なシェルの構成に対 する移植性の高い代替物を提供しています.

Macro: AS_DIRNAME (pathname)
@acronym{POSIX}で要求されるアルゴリズムを使用しながら,pathname のディレクトリ部分を返します.これが返すものと,それが @command{dirname}コマンドより移植性が高い理由の詳細は, See section 通常のツールの制限.

Macro: AS_MKDIR_P (filename)
間に入る必要なディレクトリを含め,ディレクトリfilenameを作成しま す.これは`mkdir -p filename'と等価ですが,@option{-p}オプ ションが無い古いバージョンの@command{mkdir}に移植性を持たせます.


Go to the first, previous, next, last section, table of contents.