m4: Eval
1
1 12.2 Evaluating integer expressions
1 ===================================
1
1 Integer expressions are evaluated with 'eval':
1
1 -- Builtin: eval (EXPRESSION, [RADIX = '10'], [WIDTH])
1 Expands to the value of EXPRESSION. The expansion is empty if a
1 problem is encountered while parsing the arguments. If specified,
1 RADIX and WIDTH control the format of the output.
1
1 Calculations are done with 32-bit signed numbers. Overflow
1 silently results in wraparound. A warning is issued if division by
1 zero is attempted, or if EXPRESSION could not be parsed.
1
1 Expressions can contain the following operators, listed in order of
1 decreasing precedence.
1
1 '()'
1 Parentheses
1 '+ - ~ !'
1 Unary plus and minus, and bitwise and logical negation
1 '**'
1 Exponentiation
1 '* / %'
1 Multiplication, division, and modulo
1 '+ -'
1 Addition and subtraction
1 '<< >>'
1 Shift left or right
1 '> >= < <='
1 Relational operators
1 '== !='
1 Equality operators
1 '&'
1 Bitwise and
1 '^'
1 Bitwise exclusive-or
1 '|'
1 Bitwise or
1 '&&'
1 Logical and
1 '||'
1 Logical or
1
1 The macro 'eval' is recognized only with parameters.
1
1 All binary operators, except exponentiation, are left associative. C
1 operators that perform variable assignment, such as '+=' or '--', are
1 not implemented, since 'eval' only operates on constants, not variables.
1 Attempting to use them results in an error. However, since traditional
1 implementations treated '=' as an undocumented alias for '==' as opposed
1 to an assignment operator, this usage is supported as a special case.
1 Be aware that a future version of GNU M4 may support assignment
1 semantics as an extension when POSIX mode is not requested, and that
1 using '=' to check equality is not portable.
1
1 eval(`2 = 2')
1 error->m4:stdin:1: Warning: recommend ==, not =, for equality operator
1 =>1
1 eval(`++0')
1 error->m4:stdin:2: invalid operator in eval: ++0
1 =>
1 eval(`0 |= 1')
1 error->m4:stdin:3: invalid operator in eval: 0 |= 1
1 =>
1
1 Note that some older 'm4' implementations use '^' as an alternate
1 operator for the exponentiation, although POSIX requires the C behavior
1 of bitwise exclusive-or. The precedence of the negation operators, '~'
1 and '!', was traditionally lower than equality. The unary operators
1 could not be used reliably more than once on the same term without
1 intervening parentheses. The traditional precedence of the equality
1 operators '==' and '!=' was identical instead of lower than the
1 relational operators such as '<', even through GNU M4 1.4.8. Starting
1 with version 1.4.9, GNU M4 correctly follows POSIX precedence rules. M4
1 scripts designed to be portable between releases must be aware that
1 parentheses may be required to enforce C precedence rules. Likewise,
1 division by zero, even in the unused branch of a short-circuiting
1 operator, is not always well-defined in other implementations.
1
1 Following are some examples where the current version of M4 follows C
1 precedence rules, but where older versions and some other
1 implementations of 'm4' require explicit parentheses to get the correct
1 result:
1
1 eval(`1 == 2 > 0')
1 =>1
1 eval(`(1 == 2) > 0')
1 =>0
1 eval(`! 0 * 2')
1 =>2
1 eval(`! (0 * 2)')
1 =>1
1 eval(`1 | 1 ^ 1')
1 =>1
1 eval(`(1 | 1) ^ 1')
1 =>0
1 eval(`+ + - ~ ! ~ 0')
1 =>1
1 eval(`2 || 1 / 0')
1 =>1
1 eval(`0 || 1 / 0')
1 error->m4:stdin:9: divide by zero in eval: 0 || 1 / 0
1 =>
1 eval(`0 && 1 % 0')
1 =>0
1 eval(`2 && 1 % 0')
1 error->m4:stdin:11: modulo by zero in eval: 2 && 1 % 0
1 =>
1
1 As a GNU extension, the operator '**' performs integral
1 exponentiation. The operator is right-associative, and if evaluated,
1 the exponent must be non-negative, and at least one of the arguments
1 must be non-zero, or a warning is issued.
1
1 eval(`2 ** 3 ** 2')
1 =>512
1 eval(`(2 ** 3) ** 2')
1 =>64
1 eval(`0 ** 1')
1 =>0
1 eval(`2 ** 0')
1 =>1
1 eval(`0 ** 0')
1 =>
1 error->m4:stdin:5: divide by zero in eval: 0 ** 0
1 eval(`4 ** -2')
1 error->m4:stdin:6: negative exponent in eval: 4 ** -2
1 =>
1
1 Within EXPRESSION, (but not RADIX or WIDTH), numbers without a
1 special prefix are decimal. A simple '0' prefix introduces an octal
1 number. '0x' introduces a hexadecimal number. As GNU extensions, '0b'
1 introduces a binary number. '0r' introduces a number expressed in any
1 radix between 1 and 36: the prefix should be immediately followed by the
1 decimal expression of the radix, a colon, then the digits making the
1 number. For radix 1, leading zeros are ignored, and all remaining
1 digits must be '1'; for all other radices, the digits are '0', '1', '2',
1 .... Beyond '9', the digits are 'a', 'b' ... up to 'z'. Lower and
1 upper case letters can be used interchangeably in numbers prefixes and
1 as number digits.
1
1 Parentheses may be used to group subexpressions whenever needed. For
1 the relational operators, a true relation returns '1', and a false
1 relation return '0'.
1
1 Here are a few examples of use of 'eval'.
1
1 eval(`-3 * 5')
1 =>-15
1 eval(`-99 / 10')
1 =>-9
1 eval(`-99 % 10')
1 =>-9
1 eval(`99 % -10')
1 =>9
1 eval(index(`Hello world', `llo') >= 0)
1 =>1
1 eval(`0r1:0111 + 0b100 + 0r3:12')
1 =>12
1 define(`square', `eval(`($1) ** 2')')
1 =>
1 square(`9')
1 =>81
1 square(square(`5')` + 1')
1 =>676
1 define(`foo', `666')
1 =>
1 eval(`foo / 6')
1 error->m4:stdin:11: bad expression in eval: foo / 6
1 =>
1 eval(foo / 6)
1 =>111
1
1 As the last two lines show, 'eval' does not handle macro names, even
1 if they expand to a valid expression (or part of a valid expression).
1 Therefore all macros must be expanded before they are passed to 'eval'.
1
1 Some calculations are not portable to other implementations, since
1 they have undefined semantics in C, but GNU 'm4' has well-defined
1 behavior on overflow. When shifting, an out-of-range shift amount is
1 implicitly brought into the range of 32-bit signed integers using an
1 implicit bit-wise and with 0x1f).
1
1 define(`max_int', eval(`0x7fffffff'))
1 =>
1 define(`min_int', incr(max_int))
1 =>
1 eval(min_int` < 0')
1 =>1
1 eval(max_int` > 0')
1 =>1
1 ifelse(eval(min_int` / -1'), min_int, `overflow occurred')
1 =>overflow occurred
1 min_int
1 =>-2147483648
1 eval(`0x80000000 % -1')
1 =>0
1 eval(`-4 >> 1')
1 =>-2
1 eval(`-4 >> 33')
1 =>-2
1
1 If RADIX is specified, it specifies the radix to be used in the
1 expansion. The default radix is 10; this is also the case if RADIX is
1 the empty string. A warning results if the radix is outside the range
1 of 1 through 36, inclusive. The result of 'eval' is always taken to be
1 signed. No radix prefix is output, and for radices greater than 10, the
1 digits are lower case. The WIDTH argument specifies the minimum output
1 width, excluding any negative sign. The result is zero-padded to extend
1 the expansion to the requested width. A warning results if the width is
1 negative. If RADIX or WIDTH is out of bounds, the expansion of 'eval'
1 is empty.
1
1 eval(`666', `10')
1 =>666
1 eval(`666', `11')
1 =>556
1 eval(`666', `6')
1 =>3030
1 eval(`666', `6', `10')
1 =>0000003030
1 eval(`-666', `6', `10')
1 =>-0000003030
1 eval(`10', `', `0')
1 =>10
1 `0r1:'eval(`10', `1', `11')
1 =>0r1:01111111111
1 eval(`10', `16')
1 =>a
1 eval(`1', `37')
1 error->m4:stdin:9: radix 37 in builtin `eval' out of range
1 =>
1 eval(`1', , `-1')
1 error->m4:stdin:10: negative width to builtin `eval'
1 =>
1 eval()
1 error->m4:stdin:11: empty string treated as 0 in builtin `eval'
1 =>0
1