[Top][All Lists]

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

limitations of $(( )) ?

From: Eric Blake
Subject: limitations of $(( )) ?
Date: Fri, 31 Dec 2004 16:20:54 -0700
User-agent: Mozilla Thunderbird 1.0 (Windows/20041206)

Hash: SHA1

The autoconf manual mentions nothing about the limitations of $(( ))
arithmetic expansion, other than the fact that $( ) command substition can
be confused with it when using subshells.  POSIX requires arithmetic
expansion, but not all historical shells had it.  I think it should be
mentioned in the shell substitutions section (10.5) of the manual, since
ash (the current default cygwin /bin/sh) has an unusual behavior, and
since Solaris 8 /bin/sh rejects it.  I encountered this when investigating
failures of shell scripts generated as part of the autogen package.
However I don't have an assignment on file or enough experience with
texinfo to write up a decent patch.

$ bash -c 'echo "x$((1+1))" | cat -A' # bash 2.05b
$ ash -c 'echo "x$((1+1))" | cat -A' # cygwin /bin/sh: ash compiled Jan 2004
$ ash -c 'echo x$((1+1)) | cat -A'
xM-^F 1+1M-^G$
$ ... # switch to Solaris
$ sh -c 'echo "x$((1+1))"|cat -A' # Solaris 8
$ sh -c 'echo x$((1+1))|cat -A'
/bin/sh: syntax error at line 1: `(' unexpected
$ /usr/xpg4/bin/sh -c 'echo x$((1+1))|cat -A'

Notice that ash emits 8-bit wrapper characters around the enclosed literal
text, along with an indication of the current quoting level, rather than
an arithmetic evaluation!  Likewise, Solaris chokes on the syntax when
unquoted, but treats it as a literal when quoted; although the xpg4 sh
appears to be POSIX compliant.  None of the respective man pages of ash,
/bin/sh, and /usr/xpg4/bin/sh mention $(( )) behavior.

Am I correct that the only portable way to do arithmetic evaluation is to
use expr in a subshell?  In other words, this example idiom from POSIX
2004, section 2.6.4:
# repeat a command 100 times
while [ $x -gt 0 ]
~    command;    x=$(($x-1))

should be portably rewritten:
while [ $x -gt 0 ]
~  command; x=`expr $x - 1`

Are there any portability arithmetic limitations of expr to be aware of?
(The manual only focused on string matching with expr :.)  Fortunately, a
quick grep of the autoconf tree didn't turn up any current uses of '\$((',
other than in documentation.  Still, you may want to add checks to ensure
that it doesn't slip in during future development.  Or, it may be worth
adding an m4sh idiom for optimzed arithmetic evaluation (done in m4 if
literal, in $(( )) if supported, else in subshell with `expr`).  Something
like 'AS_VAR_SET([myvar], [AS_EXPR([AS_VAR_GET([myvar])+1])])' could
potentially be useful.

- --
Life is short - so eat dessert first!

Eric Blake             address@hidden
Version: GnuPG v1.4.0 (Cygwin)
Comment: Using GnuPG with Thunderbird -


reply via email to

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