awk: 00.123 is not a octal constant; neither is 009.123. fixing this
function old new delta my_strtod 80 113 +33 Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
This commit is contained in:
parent
5b34300178
commit
d527e0c81d
@ -17,10 +17,14 @@
|
|||||||
/* If you comment out one of these below, it will be #defined later
|
/* If you comment out one of these below, it will be #defined later
|
||||||
* to perform debug printfs to stderr: */
|
* to perform debug printfs to stderr: */
|
||||||
#define debug_printf_walker(...) do {} while (0)
|
#define debug_printf_walker(...) do {} while (0)
|
||||||
|
#define debug_printf_eval(...) do {} while (0)
|
||||||
|
|
||||||
#ifndef debug_printf_walker
|
#ifndef debug_printf_walker
|
||||||
# define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__))
|
# define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__))
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef debug_printf_eval
|
||||||
|
# define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -700,14 +704,27 @@ static ALWAYS_INLINE int isalnum_(int c)
|
|||||||
|
|
||||||
static double my_strtod(char **pp)
|
static double my_strtod(char **pp)
|
||||||
{
|
{
|
||||||
|
char *cp = *pp;
|
||||||
#if ENABLE_DESKTOP
|
#if ENABLE_DESKTOP
|
||||||
if ((*pp)[0] == '0'
|
if (cp[0] == '0') {
|
||||||
&& ((((*pp)[1] | 0x20) == 'x') || isdigit((*pp)[1]))
|
/* Might be hex or octal integer: 0x123abc or 07777 */
|
||||||
) {
|
char c = (cp[1] | 0x20);
|
||||||
return strtoull(*pp, pp, 0);
|
if (c == 'x' || isdigit(cp[1])) {
|
||||||
|
unsigned long long ull = strtoull(cp, pp, 0);
|
||||||
|
if (c == 'x')
|
||||||
|
return ull;
|
||||||
|
c = **pp;
|
||||||
|
if (!isdigit(c) && c != '.')
|
||||||
|
return ull;
|
||||||
|
/* else: it may be a floating number. Examples:
|
||||||
|
* 009.123 (*pp points to '9')
|
||||||
|
* 000.123 (*pp points to '.')
|
||||||
|
* fall through to strtod.
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return strtod(*pp, pp);
|
return strtod(cp, pp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------- working with variables (set/get/copy/etc) -------- */
|
/* -------- working with variables (set/get/copy/etc) -------- */
|
||||||
@ -817,17 +834,21 @@ static double getvar_i(var *v)
|
|||||||
v->number = 0;
|
v->number = 0;
|
||||||
s = v->string;
|
s = v->string;
|
||||||
if (s && *s) {
|
if (s && *s) {
|
||||||
|
debug_printf_eval("getvar_i: '%s'->", s);
|
||||||
v->number = my_strtod(&s);
|
v->number = my_strtod(&s);
|
||||||
|
debug_printf_eval("%f (s:'%s')\n", v->number, s);
|
||||||
if (v->type & VF_USER) {
|
if (v->type & VF_USER) {
|
||||||
s = skip_spaces(s);
|
s = skip_spaces(s);
|
||||||
if (*s != '\0')
|
if (*s != '\0')
|
||||||
v->type &= ~VF_USER;
|
v->type &= ~VF_USER;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
debug_printf_eval("getvar_i: '%s'->zero\n", s);
|
||||||
v->type &= ~VF_USER;
|
v->type &= ~VF_USER;
|
||||||
}
|
}
|
||||||
v->type |= VF_CACHED;
|
v->type |= VF_CACHED;
|
||||||
}
|
}
|
||||||
|
debug_printf_eval("getvar_i: %f\n", v->number);
|
||||||
return v->number;
|
return v->number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,6 +870,7 @@ static var *copyvar(var *dest, const var *src)
|
|||||||
if (dest != src) {
|
if (dest != src) {
|
||||||
clrvar(dest);
|
clrvar(dest);
|
||||||
dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR));
|
dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR));
|
||||||
|
debug_printf_eval("copyvar: number:%f string:'%s'\n", src->number, src->string);
|
||||||
dest->number = src->number;
|
dest->number = src->number;
|
||||||
if (src->string)
|
if (src->string)
|
||||||
dest->string = xstrdup(src->string);
|
dest->string = xstrdup(src->string);
|
||||||
@ -2347,18 +2369,25 @@ static var *evaluate(node *op, var *res)
|
|||||||
opn = (opinfo & OPNMASK);
|
opn = (opinfo & OPNMASK);
|
||||||
g_lineno = op->lineno;
|
g_lineno = op->lineno;
|
||||||
op1 = op->l.n;
|
op1 = op->l.n;
|
||||||
|
debug_printf_eval("opinfo:%08x opn:%08x XC:%x\n", opinfo, opn, XC(opinfo & OPCLSMASK));
|
||||||
|
|
||||||
/* execute inevitable things */
|
/* execute inevitable things */
|
||||||
if (opinfo & OF_RES1)
|
if (opinfo & OF_RES1)
|
||||||
L.v = evaluate(op1, v1);
|
L.v = evaluate(op1, v1);
|
||||||
if (opinfo & OF_RES2)
|
if (opinfo & OF_RES2)
|
||||||
R.v = evaluate(op->r.n, v1+1);
|
R.v = evaluate(op->r.n, v1+1);
|
||||||
if (opinfo & OF_STR1)
|
if (opinfo & OF_STR1) {
|
||||||
L.s = getvar_s(L.v);
|
L.s = getvar_s(L.v);
|
||||||
if (opinfo & OF_STR2)
|
debug_printf_eval("L.s:'%s'\n", L.s);
|
||||||
|
}
|
||||||
|
if (opinfo & OF_STR2) {
|
||||||
R.s = getvar_s(R.v);
|
R.s = getvar_s(R.v);
|
||||||
if (opinfo & OF_NUM1)
|
debug_printf_eval("R.s:'%s'\n", R.s);
|
||||||
|
}
|
||||||
|
if (opinfo & OF_NUM1) {
|
||||||
L_d = getvar_i(L.v);
|
L_d = getvar_i(L.v);
|
||||||
|
debug_printf_eval("L_d:%f\n", L_d);
|
||||||
|
}
|
||||||
|
|
||||||
switch (XC(opinfo & OPCLSMASK)) {
|
switch (XC(opinfo & OPCLSMASK)) {
|
||||||
|
|
||||||
@ -2526,6 +2555,7 @@ static var *evaluate(node *op, var *res)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case XC( OC_MOVE ):
|
case XC( OC_MOVE ):
|
||||||
|
debug_printf_eval("MOVE\n");
|
||||||
/* if source is a temporary string, jusk relink it to dest */
|
/* if source is a temporary string, jusk relink it to dest */
|
||||||
//Disabled: if R.v is numeric but happens to have cached R.v->string,
|
//Disabled: if R.v is numeric but happens to have cached R.v->string,
|
||||||
//then L.v ends up being a string, which is wrong
|
//then L.v ends up being a string, which is wrong
|
||||||
@ -2777,6 +2807,7 @@ static var *evaluate(node *op, var *res)
|
|||||||
case XC( OC_BINARY ):
|
case XC( OC_BINARY ):
|
||||||
case XC( OC_REPLACE ): {
|
case XC( OC_REPLACE ): {
|
||||||
double R_d = getvar_i(R.v);
|
double R_d = getvar_i(R.v);
|
||||||
|
debug_printf_eval("BINARY/REPLACE: R_d:%f opn:%c\n", R_d, opn);
|
||||||
switch (opn) {
|
switch (opn) {
|
||||||
case '+':
|
case '+':
|
||||||
L_d += R_d;
|
L_d += R_d;
|
||||||
@ -2805,6 +2836,7 @@ static var *evaluate(node *op, var *res)
|
|||||||
L_d -= (int)(L_d / R_d) * R_d;
|
L_d -= (int)(L_d / R_d) * R_d;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
debug_printf_eval("BINARY/REPLACE result:%f\n", L_d);
|
||||||
res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, L_d);
|
res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, L_d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,12 @@ testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" ""
|
|||||||
testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n"
|
testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n"
|
||||||
SKIP=
|
SKIP=
|
||||||
|
|
||||||
|
# check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN
|
||||||
|
testing "awk floating const with leading zeroes" \
|
||||||
|
"awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \
|
||||||
|
"0.123000 9.123000\n" \
|
||||||
|
"" "\n"
|
||||||
|
|
||||||
# long field seps requiring regex
|
# long field seps requiring regex
|
||||||
testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \
|
testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \
|
||||||
"2 0 \n3 0 \n4 0 \n5 0 \n" \
|
"2 0 \n3 0 \n4 0 \n5 0 \n" \
|
||||||
|
Loading…
Reference in New Issue
Block a user