m4-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Changes to m4/doc/m4.texinfo,v


From: Eric Blake
Subject: Changes to m4/doc/m4.texinfo,v
Date: Sat, 06 Jan 2007 19:56:55 +0000

CVSROOT:        /sources/m4
Module name:    m4
Changes by:     Eric Blake <ericb>      07/01/06 19:56:54

Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -b -r1.88 -r1.89
--- doc/m4.texinfo      3 Jan 2007 14:44:11 -0000       1.88
+++ doc/m4.texinfo      6 Jan 2007 19:56:53 -0000       1.89
@@ -508,6 +508,7 @@
 m4 extensions), and @samp{traditional} (for compatibility with System V
 m4).  @xref{Modules}.
 
address@hidden numbers
 All macro arguments in @code{m4} are strings, but some are given
 special interpretation, e.g., as numbers, file names, regular
 expressions, etc.  The documentation for each macro will state how the
@@ -812,6 +813,7 @@
 exists to allow overriding @option{--traditional}.
 
 @item -G
address@hidden --posix
 @itemx --traditional
 Suppress all the extensions made in this implementation, compared to the
 System V version.  @xref{Compatibility}, for a list of these.  This
@@ -4646,6 +4648,7 @@
 @acronym{GNU} @code{m4} allows included files to be found in other directories
 than the current working directory.
 
address@hidden @env{M4PATH}
 If the @option{--prepend-include} or @option{-B} command-line option was
 provided (@pxref{Preprocessor features, , Invoking m4}), those
 directories are searched first, in reverse order that those options were
@@ -4667,6 +4670,7 @@
 reinserted into the output stream, @dfn{undiverted}, again at a later
 time.
 
address@hidden @env{TMPDIR}
 Numbered diversions are counted from 0 upwards, diversion number 0
 being the normal output stream.  The number of simultaneous diversions
 is limited mainly by the memory used to describe them, because @acronym{GNU}
@@ -5741,29 +5745,32 @@
 
 @deffn {Builtin (m4)} eval (@var{expression}, @dvar{radix, 10}, @ovar{width})
 Expands to the value of @var{expression}.  The expansion is empty
-if an error is encountered while parsing the arguments.  If specified,
address@hidden and @var{width} control the format of the output.  An error
-is issued if division by zero is attempted.
+if a problem is encountered while parsing the arguments.  If specified,
address@hidden and @var{width} control the format of the output.
 
-The macro @code{eval} is recognized only with parameters.
address@hidden deffn
+Calculations are done with signed numbers, using at least 31-bit
+precision, but as a @acronym{GNU} extension, @code{m4} will use wider
+integers if available.  Precision is finite, based on the platform's
+notion of @code{intmax_t}, and overflow silently results in wraparound.
+A warning is issued if division by zero is attempted, or if
address@hidden could not be parsed.
 
 Expressions can contain the following operators, listed in order of
 decreasing precedence.
 
address@hidden @code
address@hidden @samp
 @item ()
-Parenthesis
+Parentheses
 @item +  -  ~  !
 Unary plus and minus, and bitwise and logical negation
 @item **
 Exponentiation
address@hidden *  /  %
-Multiplication, division, and modulo
address@hidden *  /  %  \
+Multiplication, division, modulo, and ratio
 @item +  -
 Addition and subtraction
address@hidden <<  >>
-Shift left or right
address@hidden <<  >>  >>>
+Shift left, shift right, unsigned shift right
 @item >  >=  <  <=
 Relational operators
 @item ==  !=
@@ -5778,31 +5785,42 @@
 Logical and
 @item ||
 Logical or
address@hidden ?:
+Conditional ternary
address@hidden ,
+Sequential evaluation
 @end table
 
-All operators, except exponentiation, are left associative.  C
+The macro @code{eval} is recognized only with parameters.
address@hidden deffn
+
+All binary operators, except exponentiation, are left associative.  C
 operators that perform variable assignment, such as @samp{=} or
address@hidden, are forbidden, since @code{eval} only operates on constants,
-not variables.
address@hidden, are forbidden by @acronym{POSIX}, since @code{eval} only
+operates on constants, not variables.  Attempting to use them results
+in an error.
address@hidden fixme If XCU ERN 137 is approved, then we could provide an
address@hidden extension that supported assignment operators.
 
 Note that some older @code{m4} implementations use @samp{^} as an
 alternate operator for the exponentiation, although @acronym{POSIX}
 requires the C behavior of bitwise exclusive-or.  The precedence of the
 negation operators, @samp{~} and @samp{!}, was traditionally lower than
-equality.  The unary operators @samp{-} and @samp{+} could not be used
-more than once on the same term.  The traditional precedence of the
-equality operators @samp{==} and @samp{!=} was identical instead of
-lower than the relational operators such as @samp{<}, even in
address@hidden M4 1.4.x.  Starting with version 2.0, @acronym{GNU} M4
-correctly follows @acronym{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.
+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 @samp{==} and @samp{!=} was
+identical instead of lower than the relational operators such as
address@hidden<}, even through @acronym{GNU} M4 1.4.8.  Starting with version
+1.4.9, @acronym{GNU} M4 correctly follows @acronym{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 @code{m4} require explicit parenthesis to get the
+implementations of @code{m4} require explicit parentheses to get the
 correct result:
 
 @comment status: 1
@@ -5833,42 +5851,110 @@
 eval(`2 || 1 / 0')
 @result{}1
 eval(`0 || 1 / 0')
address@hidden:stdin:12: eval: divide by zero: 0 || 1 / 0
address@hidden:stdin:12: Warning: eval: divide by zero: 0 || 1 / 0
 @result{}
 eval(`0 && 1 % 0')
 @result{}0
 eval(`2 && 1 % 0')
address@hidden:stdin:14: eval: modulo by zero: 2 && 1 % 0
address@hidden:stdin:14: Warning: eval: modulo by zero: 2 && 1 % 0
address@hidden
address@hidden example
+
address@hidden @acronym{GNU} extensions
+As a @acronym{GNU} extension, @code{eval} supports several operators
+that do not appear in C.  A right-associative exponentiation operator
address@hidden computes the value of the left argument raised to the right,
+modulo the numeric precision width.  If evaluated, the exponent must be
+non-negative, and at least one of the arguments must be non-zero, or a
+warning is issued.  An unsigned shift operator @samp{>>>} allows
+shifting a negative number as though it were an unsigned bit pattern,
+which shifts in 0 bits rather than twos-complement sign-extension.  A
+ratio operator @samp{\} behaves like normal division @samp{/} on
+integers, but is provided for symmetry with @code{mpeval}.
+
address@hidden
+eval(`2 ** 3 ** 2')
address@hidden
+eval(`(2 ** 3) ** 2')
address@hidden
+eval(`0 ** 1')
address@hidden
+eval(`2 ** 0')
address@hidden
+eval(`0 ** 0')
address@hidden
address@hidden:stdin:5: Warning: eval: divide by zero: 0 ** 0
+eval(`4 ** -2')
address@hidden:stdin:6: Warning: eval: negative exponent: 4 ** -2
 @result{}
+eval(`2 || 4 ** -2')
address@hidden
+eval(`(-1 >> 1) == -1')
address@hidden
+eval(`(-1 >>> 1) > (1 << 30)')
address@hidden
+eval(`6 \ 3')
address@hidden
address@hidden example
+
+Furthermore, when you do not use the @option{--traditional} command line
+option (or @option{-G}, @pxref{Limits control, , Invoking m4}), the C
+operators @samp{,} and @samp{?:} are supported.  But in traditional
+mode, @acronym{POSIX} requires that the use of these two operators cause
+an error.
+
address@hidden
+$ @kbd{m4}
+eval(`1?2:3')
address@hidden
+eval(`0?2:3')
address@hidden
+eval(`1?2:1/0')
address@hidden
+eval(`0?1/0:3')
address@hidden
+eval(`4,5')
address@hidden
 @end example
 
-Numbers without special prefix are given decimal.  A simple @samp{0}
-prefix introduces an octal number.  @samp{0x} introduces a hexadecimal
-number.  @samp{0b} introduces a binary number.  @samp{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 any radix, the digits are
address@hidden, @samp{1}, @samp{2}, @dots{}.  Beyond @samp{9}, the digits are
address@hidden, @samp{b} @dots{} up to @samp{z}.  Lower and upper case letters
-can be used interchangeably in numbers prefixes and as number digits.
address@hidden options: -G
address@hidden status: 1
address@hidden
+$ @kbd{m4 --posix}
+eval(`1?2:3')
address@hidden:stdin:1: eval: invalid operator: 1?2:3
address@hidden
+eval(`4,5')
address@hidden:stdin:2: eval: invalid operator: 4,5
address@hidden
address@hidden example
 
-Calculations are done in at least 32 bit, but @code{m4} will use wider
-integers if available.
+Within @var{expression}, (but not @var{radix} or @var{width}), numbers
+without a special prefix are decimal.  A simple @samp{0} prefix
+introduces an octal number.  @samp{0x} introduces a hexadecimal number.
+As @acronym{GNU} extensions, @samp{0b} introduces a binary number.
address@hidden 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 @samp{1};
+for all other radices, the digits are @samp{0}, @samp{1}, @samp{2},
address@hidden  Beyond @samp{9}, the digits are @samp{a}, @samp{b} @dots{} up
+to @samp{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 @code{1}, and a false
 relation return @code{0}.
 
-The builtin macro @code{eval} is recognized only when given arguments.
-
 Here are a few examples of use of @code{eval}.
 
address@hidden status: 1
 @example
 eval(`-3 * 5')
 @result{}-15
 eval(index(`Hello world', `llo') >= 0)
 @result{}1
+eval(`0r1:0111 + 0b100 + 0r3:12')
address@hidden
 define(`square', `eval(`($1) ** 2')')
 @result{}
 square(`9')
@@ -5878,60 +5964,121 @@
 define(`foo', `666')
 @result{}
 eval(`foo / 6')
address@hidden:stdin:7: eval: bad expression: foo / 6
address@hidden:stdin:8: Warning: eval: bad expression: foo / 6
 @result{}
 eval(foo / 6)
 @result{}111
 @end example
 
-As the second to last example shows, @code{eval} does not handle macro
+As the last two lines show, @code{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 @code{eval}.
address@hidden update this if we add support for variables.
+
+Some calculations are not portable to other implementations, since they
+have undefined semantics in C, but @acronym{GNU} @code{m4} has
+well-defined behavior on overflow.  When shifting, an out-of-range shift
+amount is implicitly brought into the range of the precision using
+modulo arithmetic (for example, on 32-bit integers, this would be an
+implicit bit-wise and with 0x1f).  This example should work whether your
+platform uses 32-bit integers, 64-bit integers, or even some other
+atypical size.
+
address@hidden
+define(`max_int', eval(`-1 >>> 1'))
address@hidden
+define(`min_int', eval(max_int` + 1'))
address@hidden
+eval(min_int` < 0')
address@hidden
+eval(max_int` > 0')
address@hidden
+ifelse(eval(min_int` / -1'), min_int, `overflow occurred')
address@hidden occurred
+eval(`0x80000000 % -1')
address@hidden
+eval(`-4 >> 1')
address@hidden
+eval(`-4 >> 'eval(len(eval(max_int, `2'))` + 2'))
address@hidden
address@hidden example
 
 If @var{radix} is specified, it specifies the radix to be used in the
-expansion.  The default radix is 10.  The result of @code{eval} is
-always taken to be signed.  The @var{width} argument specifies a minimum
-output width.  The result is zero-padded to extend the expansion to the
-requested width.
+expansion.  The default radix is 10; this is also the case if
address@hidden is the empty string.  A warning results if the radix is
+outside the range of 1 through 36, inclusive.  The result of @code{eval}
+is always taken to be signed.  No radix prefix is output, and for
+radices greater than 10, the digits are lower case.  The @var{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
address@hidden or @var{width} is out of bounds, the expansion of
address@hidden is empty.
 
 @example
-eval(666, 10)
+eval(`666', `10')
 @result{}666
-eval(666, 11)
+eval(`666', `11')
 @result{}556
-eval(666, 6)
+eval(`666', `6')
 @result{}3030
-eval(666, 6, 10)
+eval(`666', `6', `10')
 @result{}0000003030
-eval(-666, 6, 10)
address@hidden
+eval(`-666', `6', `10')
address@hidden
+eval(`10', `', `0')
address@hidden
+`0r1:'eval(`10', `1', `11')
address@hidden:01111111111
+eval(`10', `16')
address@hidden
+eval(`1', `37')
address@hidden:stdin:9: Warning: eval: radix out of range: 37
address@hidden
+eval(`1', , `-1')
address@hidden:stdin:10: Warning: eval: negative width: -1
address@hidden
+eval()
address@hidden:stdin:11: Warning: eval: empty string treated as zero
address@hidden
 @end example
 
-Take note that @var{radix} cannot be larger than 36.
-
 @node Mpeval
 @section Multiple precision arithmetic
 
 When @code{m4} is compiled with a multiple precision arithmetic library
 (@pxref{Experiments}), a builtin @code{mpeval} is defined.
 
address@hidden {Builtin (mpeval)} mpeval (@var{expression}, @ovar{radix}, 
@ovar{width})
-It is almost identical to @code{eval}, except the calculations are done
-with infinite precision.  Numbers may be of any length.
-
address@hidden `:' as ratio conflicts with `?:' - is it worth using `\' instead?
-A new operator, @code{:}, is provided with the same precedence as
-division, and rationally divides two numbers and canonicalizes
-the result.  The @code{/} operator always returns the quotient of the
-division.  To convert a rational value to integral, divide (@code{/}) by
-1.  Some operators such as @code{%}, @code{<<}, @code{>>}, @code{~},
address@hidden&}, @code{|} and @code{^} operate only on integers and will
-truncate any rational remainder.  @code{**} assumes that the exponent is
-integral.
address@hidden {Builtin (mpeval)} mpeval (@var{expression}, @dvar{radix, 10}, @
+  @ovar{width})
+Behaves similarly to @code{eval}, except the calculations are done with
+infinite precision, and rational numbers are supported.  Numbers may be
+of any length.
+
+The macro @code{mpeval} is recognized only with parameters.
address@hidden deffn
+
+The ratio operator, @samp{\}, is provided with the same precedence as
+division, and rationally divides two numbers and canonicalizes the
+result, whereas the division operator @samp{/} always returns the
+integer quotient of the division.  To convert a rational value to
+integral, divide (@samp{/}) by 1.  Some operators, such as @samp{%},
address@hidden<<}, @samp{>>}, @samp{~}, @samp{&}, @samp{|} and @samp{^} operate
+only on integers and will truncate any rational remainder.  The unsigned
+shift operator, @samp{>>>}, behaves identically with regular right
+shifts, @samp{>>}, since with infinite precision, it is not possible to
+convert a negative number to a positive using shifts.  The
+exponentiation operator, @samp{**}, assumes that the exponent is
+integral, but allows negative exponents.  With the short-circuit logical
+operators, @samp{||} and @samp{&&}, a non-zero result preserves the
+value of the argument that ended evaluation, rather than collapsing to
address@hidden  The operators @samp{?:} and @samp{,} are always available,
+even in @acronym{POSIX} mode, since @code{mpeval} does not have to
+conform to the @acronym{POSIX} rules for @code{eval}.
 
-The builtin macro @code{mpeval} is recognized only when given arguments.
address@hidden deffn
address@hidden fixme - need some examples, but conditional on whether modules
address@hidden and mpeval are both supported
 
 @node Shell commands
 @chapter Macros for running shell commands
@@ -6003,7 +6150,7 @@
 @node Esyscmd
 @section Reading the output of commands
 
address@hidden GNU extensions
address@hidden @acronym{GNU} extensions
 @deffn {Builtin (gnu)} esyscmd (@var{shell-command})
 If you want @code{m4} to read the output of a shell command, use
 @code{esyscmd}, which expands to the standard output of the shell
@@ -6495,7 +6642,7 @@
 @cindex initialization, frozen state
 @cindex dumping into frozen file
 @cindex reloading a frozen file
address@hidden GNU extensions
address@hidden @acronym{GNU} extensions
 Reading the common base of a big application, over and over again, may
 be time consuming.  GNU @code{m4} offers some machinery to speed up
 the start of an application using lengthy common bases.  Presume the
@@ -6689,7 +6836,7 @@
 @node Extensions
 @section Extensions in @acronym{GNU} M4
 
address@hidden GNU extensions
address@hidden @acronym{GNU} extensions
 @cindex @acronym{POSIX}
 @cindex @env{POSIXLY_CORRECT}
 This version of @code{m4} contains a few facilities that do not exist
@@ -6954,7 +7101,6 @@
 not need to be passed to the helper @address@hidden
 
 @comment examples
address@hidden status: 1
 @example
 $ @kbd{m4 -I examples}
 undivert(`forloop2.m4')dnl
@@ -6979,7 +7125,7 @@
 forloop(`i', `5 + 5', `0xc', ` 0x`'eval(i, `16')')
 @result{} 0xa 0xb 0xc
 forloop(`i', `a', `b', `non-numeric bounds')
address@hidden:stdin:6: eval: bad input: (b) >= (a)
address@hidden:stdin:6: Warning: eval: bad input: (b) >= (a)
 @result{}
 @end example
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]