[Gllug] Unsigned shell arithmetic

Nix nix at esperi.demon.co.uk
Wed Dec 5 08:34:15 UTC 2001


On Tue, 04 Dec 2001, tet at accucard.com uttered the following:
> Anyone know how I can force unsigned arithmetic in a shell?

You can't. The Single Unix Spec is not very clear on this :(

`Only integer arithmetic is required.' --- and no provision is made for
*unsigned* integer arithmetic.

> 	echo $((65536 * 65000))

Of course because there are no guaranteed bounds this might overflow
even if you added two and two ;)

> returns -35127296 both bash and pdksh, although genuine ksh on Solaris
> returns 4259840000, which in this instance is what I want (fortunate,

Undefined behaviour syndrome :(

> as the script is primarily going to be used on Solaris). pdksh has a
> -U option to typeset, which implies it'll do this, but it doesn't seem
> to work.

... and isn't portable :(

>          But I was more interested in whether or not it could be done
> in Bourne shell, rather than bash, pdksh, zsh or any of the other
> "enhanced" shells.

Not a chance. The Bourne shell isn't a POSIX shell and hence doesn't
have shell arithmetic at all. You'd have more luck in a POSIX shell, but
it doesn't seem that they have allowed for this either.

> Also, does anyone know of a way to do bitwise operations in a standard
> Bourne shell?

There is none, as there is no shell arithmetic. For POSIX shells, SuSv2
states

,----
| The arithmetic expression will be processed according to the rules of
| the ISO C standard, with the following exceptions:
| 
|     * Only integer arithmetic is required.
| 
|     * The sizeof() operator and the prefix and postfix ++ and --
|       operators are not required.
`----

I don't think bitwise manipulation is classifiable as `integer
arithmetic', somehow.

>               I can do it in ksh or bash with $((a & b)), but at least

Non-portable (assuming my reading of the spec to be correct; I'm not
confident of that).

> on Solaris, standard Bourne shell doesn't support that construct, and
> neither does expr.

Stick a #!/bin/ksh at the top of the script, and get the script to
reinvoke itself with ksh if some idiot starts it with `sh', viz

if [ "$(echo foo)" != "`echo foo`" ]; then
    exec $0 "$@"
    echo 'Error: needed shell (/bin/ksh) not found.' >&2
    exit 1
fi

(do that as close to the top of the script as you can, of course.)

> PS.  Yes, I know I can do arbitrary precision unsigned arithmetic in dc,
>      but dc doesn't have a bitwise AND operator, which unfortunately I need.

You'll have to either write C or implement bitwise arithmetic in dc or
sed in terms of decimal manipulations. This is definitely possible ---
see the seders mailing list archives for an implementation by (who else)
Greg Ubben --- but it's, er, hardly readable.

> PPS. No comments about how I should be using perl, python or any other

`You should be using Emacs Lisp.'

*stirs mud vigorously*

>                             It's not an option for this particular task.
>      The client has specified an unmolested Solaris 7 box, with no
>      additional software installed.

I think you'll need /bin/ksh, but that's always there, isn't it?

-- 
`The situation is completely under control. All of them were killed.'
     --- Alim Razim, for the Northern Alliance, demonstrating fine
         command of traditional Afghan prisoner control techniques.

-- 
Gllug mailing list  -  Gllug at linux.co.uk
http://list.ftech.net/mailman/listinfo/gllug




More information about the GLLUG mailing list