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]