awk: improve nadling of negative numbers in bitwise ops;
fix handling of octal costants. add test for it function old new delta getvar_i_int - 93 +93 my_strtod - 84 +84 qrealloc 33 36 +3 getvar_i 99 95 -4 next_token 979 919 -60 evaluate 6359 5627 -732 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 1/3 up/down: 180/-796) Total: -616 bytes
This commit is contained in:
parent
b424930e4e
commit
a2e1eea189
@ -681,6 +681,18 @@ static ALWAYS_INLINE int isalnum_(int c)
|
|||||||
return (isalnum(c) || c == '_');
|
return (isalnum(c) || c == '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double my_strtod(char **pp)
|
||||||
|
{
|
||||||
|
#if ENABLE_DESKTOP
|
||||||
|
if ((*pp)[0] == '0'
|
||||||
|
&& ((((*pp)[1] | 0x20) == 'x') || isdigit((*pp)[1]))
|
||||||
|
) {
|
||||||
|
return strtoull(*pp, pp, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return strtod(*pp, pp);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------- working with variables (set/get/copy/etc) -------- */
|
/* -------- working with variables (set/get/copy/etc) -------- */
|
||||||
|
|
||||||
static xhash *iamarray(var *v)
|
static xhash *iamarray(var *v)
|
||||||
@ -790,7 +802,7 @@ static double getvar_i(var *v)
|
|||||||
v->number = 0;
|
v->number = 0;
|
||||||
s = v->string;
|
s = v->string;
|
||||||
if (s && *s) {
|
if (s && *s) {
|
||||||
v->number = strtod(s, &s);
|
v->number = my_strtod(&s);
|
||||||
if (v->type & VF_USER) {
|
if (v->type & VF_USER) {
|
||||||
skip_spaces(&s);
|
skip_spaces(&s);
|
||||||
if (*s != '\0')
|
if (*s != '\0')
|
||||||
@ -804,6 +816,18 @@ static double getvar_i(var *v)
|
|||||||
return v->number;
|
return v->number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Used for operands of bitwise ops */
|
||||||
|
static unsigned long getvar_i_int(var *v)
|
||||||
|
{
|
||||||
|
double d = getvar_i(v);
|
||||||
|
|
||||||
|
/* Casting doubles to longs is undefined for values outside
|
||||||
|
* of target type range. Try to widen it as much as possible */
|
||||||
|
if (d >= 0)
|
||||||
|
return (unsigned long)d;
|
||||||
|
return - (long) (unsigned long) (-d);
|
||||||
|
}
|
||||||
|
|
||||||
static var *copyvar(var *dest, const var *src)
|
static var *copyvar(var *dest, const var *src)
|
||||||
{
|
{
|
||||||
if (dest != src) {
|
if (dest != src) {
|
||||||
@ -973,12 +997,7 @@ static uint32_t next_token(uint32_t expected)
|
|||||||
|
|
||||||
} else if (*p == '.' || isdigit(*p)) {
|
} else if (*p == '.' || isdigit(*p)) {
|
||||||
/* it's a number */
|
/* it's a number */
|
||||||
#if ENABLE_DESKTOP
|
t_double = my_strtod(&p);
|
||||||
if (p[0] == '0' && (p[1] | 0x20) == 'x')
|
|
||||||
t_double = strtoll(p, &p, 0);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
t_double = strtod(p, &p);
|
|
||||||
if (*p == '.')
|
if (*p == '.')
|
||||||
syntax_error(EMSG_UNEXP_TOKEN);
|
syntax_error(EMSG_UNEXP_TOKEN);
|
||||||
tc = TC_NUMBER;
|
tc = TC_NUMBER;
|
||||||
@ -2022,7 +2041,7 @@ static var *exec_builtin(node *op, var *res)
|
|||||||
n = awk_split(as[0], spl, &s);
|
n = awk_split(as[0], spl, &s);
|
||||||
s1 = s;
|
s1 = s;
|
||||||
clear_array(iamarray(av[1]));
|
clear_array(iamarray(av[1]));
|
||||||
for (i=1; i<=n; i++)
|
for (i = 1; i <= n; i++)
|
||||||
setari_u(av[1], i, nextword(&s1));
|
setari_u(av[1], i, nextword(&s1));
|
||||||
free(s);
|
free(s);
|
||||||
setvar_i(res, n);
|
setvar_i(res, n);
|
||||||
@ -2042,27 +2061,27 @@ static var *exec_builtin(node *op, var *res)
|
|||||||
/* Bitwise ops must assume that operands are unsigned. GNU Awk 3.1.5:
|
/* Bitwise ops must assume that operands are unsigned. GNU Awk 3.1.5:
|
||||||
* awk '{ print or(-1,1) }' gives "4.29497e+09", not "-2.xxxe+09" */
|
* awk '{ print or(-1,1) }' gives "4.29497e+09", not "-2.xxxe+09" */
|
||||||
case B_an:
|
case B_an:
|
||||||
setvar_i(res, (unsigned long)getvar_i(av[0]) & (unsigned long)getvar_i(av[1]));
|
setvar_i(res, getvar_i_int(av[0]) & getvar_i_int(av[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_co:
|
case B_co:
|
||||||
setvar_i(res, ~(unsigned long)getvar_i(av[0]));
|
setvar_i(res, ~getvar_i_int(av[0]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_ls:
|
case B_ls:
|
||||||
setvar_i(res, (unsigned long)getvar_i(av[0]) << (unsigned long)getvar_i(av[1]));
|
setvar_i(res, getvar_i_int(av[0]) << getvar_i_int(av[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_or:
|
case B_or:
|
||||||
setvar_i(res, (unsigned long)getvar_i(av[0]) | (unsigned long)getvar_i(av[1]));
|
setvar_i(res, getvar_i_int(av[0]) | getvar_i_int(av[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_rs:
|
case B_rs:
|
||||||
setvar_i(res, (unsigned long)getvar_i(av[0]) >> (unsigned long)getvar_i(av[1]));
|
setvar_i(res, getvar_i_int(av[0]) >> getvar_i_int(av[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_xo:
|
case B_xo:
|
||||||
setvar_i(res, (unsigned long)getvar_i(av[0]) ^ (unsigned long)getvar_i(av[1]));
|
setvar_i(res, getvar_i_int(av[0]) ^ getvar_i_int(av[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_lo:
|
case B_lo:
|
||||||
|
@ -20,6 +20,7 @@ testing "awk -F case 7" "awk -F '[#]' '{ print NF }'" "5\n" "" "z##abc##zz\n"
|
|||||||
testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n"
|
testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n"
|
||||||
testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n"
|
testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n"
|
||||||
testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n"
|
testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n"
|
||||||
|
testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n"
|
||||||
|
|
||||||
tar xjf awk_t1.tar.bz2
|
tar xjf awk_t1.tar.bz2
|
||||||
testing "awk 'gcc build bug'" \
|
testing "awk 'gcc build bug'" \
|
||||||
|
Loading…
Reference in New Issue
Block a user