前: Incr, 上: Arithmetic


11.2 整数式を計算する

整数式はevalを使って計算します。

     eval(expression, opt radix, opt width)

このマクロはexpressionの値に展開されます。

式(expression)には次の演算子を含めることができます。 リストは優先順位の高い順に並んでいます。

-
単項差(unary minus)
**
累乗(exponentiation)
* / %
積(multiplication)、商(division)、剰余(modulo)
+ -
和(addition)、差(subtraction)
<< >>
左シフト(shift left)、右シフト(shift right)
== != > >= < <=
関係演算子(relational operator)
!
論理否定(logical negation)
~
ビットごとの論理否定(bitwise negation)
&
ビットごとの論理積(bitwise and)
^
ビットごとの排他的論理和(bitwise exclusive-or)
|
ビットごとの論理和(bitwise or)
&&
論理積(logical and)
||
論理和(logical or)

累乗(exponentiation)を除いたすべての演算子は左結合(left associative)をします。

m4の実装には`^'を累乗(exponentiation)演算子の代用として使うもの が多くありますが、`^'をビットごとの排他的論理和(bitwise exclusive-or) に使っている実装も多くあります。GNU m4では、かつて`^'は累乗を行う 演算子でしたが、動作の変更を行い、現在はビットごとの排他的論理和を行う 演算子になっています。

特別な接頭辞(prefix)がついていない数字は10進数となります。 `0'のみの接頭辞は8進数の始まりを表します。 `0x'は16進数の始まりを表します。 `0b'は2進数の始まりを表します。 `0r'は1から36までの任意の基数で表現した数字の始まりを表します。 `0r'の後には10進数で表現した基数、コロン(:)、 および数値を表す数字列を続けなくてはなりません。 いずれの基数で表すにしても数字としては`0', `1', `2', ...を使い、`9'から上は`a', `b' ... `z'までを 数字として使います。 アルファベットの大文字と小文字は基数を表す接頭辞および数値を表す数字列のなかで 区別なく使用することができます。

部分式をグループ化するために必要なときはカッコを使うことができます。 関係演算子は関係が真のときは1を返し、偽のときは0を返します。

evalの使用例をいくつか次に挙げます。

     eval(-3 * 5)
     =>-15
     eval(index(`Hello world', `llo') >= 0)
     =>1
     define(`square', `eval(($1)**2)')
     =>
     square(9)
     =>81
     square(square(5)+1)
     =>676
     define(`foo', `666')
     =>
     eval(`foo'/6)
     error-->51.eval:14: m4: Bad expression in eval: foo/6
     =>
     eval(foo/6)
     =>111

最後から2番目の例が示しているようにevalがマクロ名を勝手に展開することはありません。 例えそれらが有効な式(もしくは有効な式の一部)に展開されるにしてもです。 したがって全てのマクロはevalに渡される前に展開済である必要があります。

radixを指定すると展開後のテキストではその基数が使われます。 デフォルトの基数は10です。 evalの結果は常に符号付き(signed)の値であると解釈されます。 引数widthは最低限の出力幅を指定します。 展開後のテキストが要求された幅になるように 結果には0が埋め草(zero-padded)として付加されます。

     eval(666, 10)
     =>666
     eval(666, 11)
     =>556
     eval(666, 6)
     =>3030
     eval(666, 6, 10)
     =>0000003030
     eval(-666, 6, 10)
     =>-000003030

radixは36より大きくてはいけないことに注意してください。

組み込みマクロevalは引数を与えたときだけ認識されます。