Hi,

Resubmitting the second change for review.

Recap:

+ Makes it able to use C-style radix prefixes to integers in order to do calculations in octal and hexadecimal. In the olden days, early '80:s to be specific, I worked at a company that produced a unix flavour called D-NIX, which had this neat feature in its expr(1). It makes it a breeze to make quick radix conversions, for example. And I guess the habit stuck with me, for to this day it frustrates me not to be able to use expr for that. :-) I hope others find it useful too. For example:

    skynet:/usr/src/bin/expr# expr 0x1ffff + 15
    131086
    skynet:/usr/src/bin/expr#

- Hexadecimal numbers (starting with 0x or 0X) is no longer recognized as strings. (The common construct expr 'X'$FOO = 'X' would still work as expected, of course.) Probably not a big concern.

- POSIX?

/Benny

(This diff is done relative to the first, so if that one is out but this one is in then I'll need to remake number 2.)

----8<--------8<--------8<--------8<--------8<---- (cut)
--- expr.c.diff1        Sat Jan 15 04:35:43 2011
+++ expr.c      Sat Jan 15 04:46:46 2011
@@ -96,7 +96,10 @@
 {
        char           *s;
        int64_t         neg;
-       int64_t         i;
+       int64_t         i, d;
+       int64_t         radix=10;
+       static char     *digits="0123456789abcdef";
+       char            *dp;

        if (vp->type == integer) {
                *r = vp->u.i;
@@ -105,7 +108,8 @@

        /*
         * POSIX.2 defines an "integer" as an optional unary minus
-        * followed by digits.
+        * followed by digits. We also consider C style octal and
+        * hexadecimal prefix notation part of an integer.
         */
        s = vp->u.s;
        i = 0;
@@ -113,14 +117,21 @@
        neg = (*s == '-');
        if (neg)
                s++;
+       if (*s=='0') {
+               radix=8; s++;
+               if (*s=='x' || *s=='X') {
+                       radix=16; s++;
+               }
+       }

        while (*s) {
-               if (!isdigit(*s))
+               if ((dp = strchr(digits, tolower(*s)))==NULL)
                        return 0;
+               if ((d = dp-digits) >= radix)
+                       return 0; /* Invalid digit for radix -> string */

-               i *= 10;
-               i += *s - '0';
-
+               i *= radix;
+               i += d;
                s++;
        }

@@ -501,6 +512,13 @@
        av = argv + 1;

        nexttoken(0);
+
+       /* In case there is only one operand, make sure it is validated
+        * as an integer as well, in case we for example want to print
+        * it in a different radix.
+        */
+       (void) to_integer(tokval);
+
        vp = eval0();

        if (token != EOI) {
----8<--------8<--------8<--------8<--------8<---- (cut)

--
internetlabbet.se     / work:   +46 8 551 124 80      / "Words must
Benny Lvfgren        /  mobile: +46 70 718 11 90     /   be weighed,
                    /   fax:    +46 8 551 124 89    /    not counted."
                   /    email:  [email protected]

Reply via email to