(m4.info)Eval


Prev: Incr Up: Arithmetic

12.2 Evaluating integer expressions
===================================

Integer expressions are evaluated with `eval':

 -- Builtin: eval (EXPRESSION, [RADIX = `10'], [WIDTH])
     Expands to the value of EXPRESSION.  The expansion is empty if a
     problem is encountered while parsing the arguments.  If specified,
     RADIX and WIDTH control the format of the output.

     Calculations are done with 32-bit signed numbers.  Overflow
     silently results in wraparound.  A warning is issued if division
     by zero is attempted, or if EXPRESSION could not be parsed.

     Expressions can contain the following operators, listed in order of
     decreasing precedence.

    `()'
          Parentheses

    `+  -  ~  !'
          Unary plus and minus, and bitwise and logical negation

    `**'
          Exponentiation

    `*  /  %'
          Multiplication, division, and modulo

    `+  -'
          Addition and subtraction

    `<<  >>'
          Shift left or right

    `>  >=  <  <='
          Relational operators

    `==  !='
          Equality operators

    `&'
          Bitwise and

    `^'
          Bitwise exclusive-or

    `|'
          Bitwise or

    `&&'
          Logical and

    `||'
          Logical or

     The macro `eval' is recognized only with parameters.

   All binary operators, except exponentiation, are left associative.  C
operators that perform variable assignment, such as `+=' or `--', are
not implemented, since `eval' only operates on constants, not
variables.  Attempting to use them results in an error.  However, since
traditional implementations treated `=' as an undocumented alias for
`==' as opposed to an assignment operator, this usage is supported as a
special case.  Be aware that a future version of GNU M4 may support
assignment semantics as an extension when POSIX mode is not requested,
and that using `=' to check equality is not portable.

     eval(`2 = 2')
     error-->m4:stdin:1: Warning: recommend ==, not =, for equality operator
     =>1
     eval(`++0')
     error-->m4:stdin:2: invalid operator in eval: ++0
     =>
     eval(`0 |= 1')
     error-->m4:stdin:3: invalid operator in eval: 0 |= 1
     =>

   Note that some older `m4' implementations use `^' as an alternate
operator for the exponentiation, although POSIX requires the C behavior
of bitwise exclusive-or.  The precedence of the negation operators, `~'
and `!', was traditionally lower than equality.  The unary operators
could not be used reliably more than once on the same term without
intervening parentheses.  The traditional precedence of the equality
operators `==' and `!=' was identical instead of lower than the
relational operators such as `<', even through GNU M4 1.4.8.  Starting
with version 1.4.9, GNU M4 correctly follows POSIX precedence rules.
M4 scripts designed to be portable between releases must be aware that
parentheses may be required to enforce C precedence rules.  Likewise,
division by zero, even in the unused branch of a short-circuiting
operator, is not always well-defined in other implementations.

   Following are some examples where the current version of M4 follows C
precedence rules, but where older versions and some other
implementations of `m4' require explicit parentheses to get the correct
result:

     eval(`1 == 2 > 0')
     =>1
     eval(`(1 == 2) > 0')
     =>0
     eval(`! 0 * 2')
     =>2
     eval(`! (0 * 2)')
     =>1
     eval(`1 | 1 ^ 1')
     =>1
     eval(`(1 | 1) ^ 1')
     =>0
     eval(`+ + - ~ ! ~ 0')
     =>1
     eval(`2 || 1 / 0')
     =>1
     eval(`0 || 1 / 0')
     error-->m4:stdin:9: divide by zero in eval: 0 || 1 / 0
     =>
     eval(`0 && 1 % 0')
     =>0
     eval(`2 && 1 % 0')
     error-->m4:stdin:11: modulo by zero in eval: 2 && 1 % 0
     =>

   As a GNU extension, the operator `**' performs integral
exponentiation.  The operator is right-associative, and if evaluated,
the exponent must be non-negative, and at least one of the arguments
must be non-zero, or a warning is issued.

     eval(`2 ** 3 ** 2')
     =>512
     eval(`(2 ** 3) ** 2')
     =>64
     eval(`0 ** 1')
     =>0
     eval(`2 ** 0')
     =>1
     eval(`0 ** 0')
     =>
     error-->m4:stdin:5: divide by zero in eval: 0 ** 0
     eval(`4 ** -2')
     error-->m4:stdin:6: negative exponent in eval: 4 ** -2
     =>

   Within EXPRESSION, (but not RADIX or WIDTH), numbers without a
special prefix are decimal.  A simple `0' prefix introduces an octal
number.  `0x' introduces a hexadecimal number.  As GNU extensions, `0b'
introduces a binary number.  `0r' introduces a number expressed in any
radix between 1 and 36: the prefix should be immediately followed by
the decimal expression of the radix, a colon, then the digits making
the number.  For radix 1, leading zeros are ignored, and all remaining
digits must be `1'; for all other radices, the digits are `0', `1', `2',
....  Beyond `9', the digits are `a', `b' ... up to `z'.  Lower and
upper case letters can be used interchangeably in numbers prefixes and
as number digits.

   Parentheses may be used to group subexpressions whenever needed.
For the relational operators, a true relation returns `1', and a false
relation return `0'.

   Here are a few examples of use of `eval'.

     eval(`-3 * 5')
     =>-15
     eval(`-99 / 10')
     =>-9
     eval(`-99 % 10')
     =>-9
     eval(`99 % -10')
     =>9
     eval(index(`Hello world', `llo') >= 0)
     =>1
     eval(`0r1:0111 + 0b100 + 0r3:12')
     =>12
     define(`square', `eval(`($1) ** 2')')
     =>
     square(`9')
     =>81
     square(square(`5')` + 1')
     =>676
     define(`foo', `666')
     =>
     eval(`foo / 6')
     error-->m4:stdin:11: bad expression in eval: foo / 6
     =>
     eval(foo / 6)
     =>111

   As the last two lines show, `eval' does not handle macro names, even
if they expand to a valid expression (or part of a valid expression).
Therefore all macros must be expanded before they are passed to `eval'.

   Some calculations are not portable to other implementations, since
they have undefined semantics in C, but GNU `m4' has well-defined
behavior on overflow.  When shifting, an out-of-range shift amount is
implicitly brought into the range of 32-bit signed integers using an
implicit bit-wise and with 0x1f).

     define(`max_int', eval(`0x7fffffff'))
     =>
     define(`min_int', incr(max_int))
     =>
     eval(min_int` < 0')
     =>1
     eval(max_int` > 0')
     =>1
     ifelse(eval(min_int` / -1'), min_int, `overflow occurred')
     =>overflow occurred
     min_int
     =>-2147483648
     eval(`0x80000000 % -1')
     =>0
     eval(`-4 >> 1')
     =>-2
     eval(`-4 >> 33')
     =>-2

   If RADIX is specified, it specifies the radix to be used in the
expansion.  The default radix is 10; this is also the case if RADIX is
the empty string.  A warning results if the radix is outside the range
of 1 through 36, inclusive.  The result of `eval' is always taken to be
signed.  No radix prefix is output, and for radices greater than 10,
the digits are lower case.  The WIDTH argument specifies the minimum
output width, excluding any negative sign.  The result is zero-padded
to extend the expansion to the requested width.  A warning results if
the width is negative.  If RADIX or WIDTH is out of bounds, the
expansion of `eval' is empty.

     eval(`666', `10')
     =>666
     eval(`666', `11')
     =>556
     eval(`666', `6')
     =>3030
     eval(`666', `6', `10')
     =>0000003030
     eval(`-666', `6', `10')
     =>-0000003030
     eval(`10', `', `0')
     =>10
     `0r1:'eval(`10', `1', `11')
     =>0r1:01111111111
     eval(`10', `16')
     =>a
     eval(`1', `37')
     error-->m4:stdin:9: radix 37 in builtin `eval' out of range
     =>
     eval(`1', , `-1')
     error-->m4:stdin:10: negative width to builtin `eval'
     =>
     eval()
     error-->m4:stdin:11: empty string treated as 0 in builtin `eval'
     =>0


automatically generated by info2www