diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2010-10-05 13:22:11 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2010-10-05 13:22:11 +0200 |
commit | d527e0c81d2efe98f258f1e1516a0e9cbe879154 (patch) | |
tree | 104ab5a0d550ea60151891848581880c0eca7e9a | |
parent | 5b3430017895001e134b6c37a0ea4d2c082ba209 (diff) | |
download | busybox-w32-d527e0c81d2efe98f258f1e1516a0e9cbe879154.tar.gz busybox-w32-d527e0c81d2efe98f258f1e1516a0e9cbe879154.tar.bz2 busybox-w32-d527e0c81d2efe98f258f1e1516a0e9cbe879154.zip |
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>
-rw-r--r-- | editors/awk.c | 48 | ||||
-rwxr-xr-x | testsuite/awk.tests | 6 |
2 files changed, 46 insertions, 8 deletions
diff --git a/editors/awk.c b/editors/awk.c index f47d1ab02..d9f9e0f6e 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -17,10 +17,14 @@ | |||
17 | /* If you comment out one of these below, it will be #defined later | 17 | /* If you comment out one of these below, it will be #defined later |
18 | * to perform debug printfs to stderr: */ | 18 | * to perform debug printfs to stderr: */ |
19 | #define debug_printf_walker(...) do {} while (0) | 19 | #define debug_printf_walker(...) do {} while (0) |
20 | #define debug_printf_eval(...) do {} while (0) | ||
20 | 21 | ||
21 | #ifndef debug_printf_walker | 22 | #ifndef debug_printf_walker |
22 | # define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__)) | 23 | # define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__)) |
23 | #endif | 24 | #endif |
25 | #ifndef debug_printf_eval | ||
26 | # define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__)) | ||
27 | #endif | ||
24 | 28 | ||
25 | 29 | ||
26 | 30 | ||
@@ -700,14 +704,27 @@ static ALWAYS_INLINE int isalnum_(int c) | |||
700 | 704 | ||
701 | static double my_strtod(char **pp) | 705 | static double my_strtod(char **pp) |
702 | { | 706 | { |
707 | char *cp = *pp; | ||
703 | #if ENABLE_DESKTOP | 708 | #if ENABLE_DESKTOP |
704 | if ((*pp)[0] == '0' | 709 | if (cp[0] == '0') { |
705 | && ((((*pp)[1] | 0x20) == 'x') || isdigit((*pp)[1])) | 710 | /* Might be hex or octal integer: 0x123abc or 07777 */ |
706 | ) { | 711 | char c = (cp[1] | 0x20); |
707 | return strtoull(*pp, pp, 0); | 712 | if (c == 'x' || isdigit(cp[1])) { |
713 | unsigned long long ull = strtoull(cp, pp, 0); | ||
714 | if (c == 'x') | ||
715 | return ull; | ||
716 | c = **pp; | ||
717 | if (!isdigit(c) && c != '.') | ||
718 | return ull; | ||
719 | /* else: it may be a floating number. Examples: | ||
720 | * 009.123 (*pp points to '9') | ||
721 | * 000.123 (*pp points to '.') | ||
722 | * fall through to strtod. | ||
723 | */ | ||
724 | } | ||
708 | } | 725 | } |
709 | #endif | 726 | #endif |
710 | return strtod(*pp, pp); | 727 | return strtod(cp, pp); |
711 | } | 728 | } |
712 | 729 | ||
713 | /* -------- working with variables (set/get/copy/etc) -------- */ | 730 | /* -------- working with variables (set/get/copy/etc) -------- */ |
@@ -817,17 +834,21 @@ static double getvar_i(var *v) | |||
817 | v->number = 0; | 834 | v->number = 0; |
818 | s = v->string; | 835 | s = v->string; |
819 | if (s && *s) { | 836 | if (s && *s) { |
837 | debug_printf_eval("getvar_i: '%s'->", s); | ||
820 | v->number = my_strtod(&s); | 838 | v->number = my_strtod(&s); |
839 | debug_printf_eval("%f (s:'%s')\n", v->number, s); | ||
821 | if (v->type & VF_USER) { | 840 | if (v->type & VF_USER) { |
822 | s = skip_spaces(s); | 841 | s = skip_spaces(s); |
823 | if (*s != '\0') | 842 | if (*s != '\0') |
824 | v->type &= ~VF_USER; | 843 | v->type &= ~VF_USER; |
825 | } | 844 | } |
826 | } else { | 845 | } else { |
846 | debug_printf_eval("getvar_i: '%s'->zero\n", s); | ||
827 | v->type &= ~VF_USER; | 847 | v->type &= ~VF_USER; |
828 | } | 848 | } |
829 | v->type |= VF_CACHED; | 849 | v->type |= VF_CACHED; |
830 | } | 850 | } |
851 | debug_printf_eval("getvar_i: %f\n", v->number); | ||
831 | return v->number; | 852 | return v->number; |
832 | } | 853 | } |
833 | 854 | ||
@@ -849,6 +870,7 @@ static var *copyvar(var *dest, const var *src) | |||
849 | if (dest != src) { | 870 | if (dest != src) { |
850 | clrvar(dest); | 871 | clrvar(dest); |
851 | dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR)); | 872 | dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR)); |
873 | debug_printf_eval("copyvar: number:%f string:'%s'\n", src->number, src->string); | ||
852 | dest->number = src->number; | 874 | dest->number = src->number; |
853 | if (src->string) | 875 | if (src->string) |
854 | dest->string = xstrdup(src->string); | 876 | dest->string = xstrdup(src->string); |
@@ -2347,18 +2369,25 @@ static var *evaluate(node *op, var *res) | |||
2347 | opn = (opinfo & OPNMASK); | 2369 | opn = (opinfo & OPNMASK); |
2348 | g_lineno = op->lineno; | 2370 | g_lineno = op->lineno; |
2349 | op1 = op->l.n; | 2371 | op1 = op->l.n; |
2372 | debug_printf_eval("opinfo:%08x opn:%08x XC:%x\n", opinfo, opn, XC(opinfo & OPCLSMASK)); | ||
2350 | 2373 | ||
2351 | /* execute inevitable things */ | 2374 | /* execute inevitable things */ |
2352 | if (opinfo & OF_RES1) | 2375 | if (opinfo & OF_RES1) |
2353 | L.v = evaluate(op1, v1); | 2376 | L.v = evaluate(op1, v1); |
2354 | if (opinfo & OF_RES2) | 2377 | if (opinfo & OF_RES2) |
2355 | R.v = evaluate(op->r.n, v1+1); | 2378 | R.v = evaluate(op->r.n, v1+1); |
2356 | if (opinfo & OF_STR1) | 2379 | if (opinfo & OF_STR1) { |
2357 | L.s = getvar_s(L.v); | 2380 | L.s = getvar_s(L.v); |
2358 | if (opinfo & OF_STR2) | 2381 | debug_printf_eval("L.s:'%s'\n", L.s); |
2382 | } | ||
2383 | if (opinfo & OF_STR2) { | ||
2359 | R.s = getvar_s(R.v); | 2384 | R.s = getvar_s(R.v); |
2360 | if (opinfo & OF_NUM1) | 2385 | debug_printf_eval("R.s:'%s'\n", R.s); |
2386 | } | ||
2387 | if (opinfo & OF_NUM1) { | ||
2361 | L_d = getvar_i(L.v); | 2388 | L_d = getvar_i(L.v); |
2389 | debug_printf_eval("L_d:%f\n", L_d); | ||
2390 | } | ||
2362 | 2391 | ||
2363 | switch (XC(opinfo & OPCLSMASK)) { | 2392 | switch (XC(opinfo & OPCLSMASK)) { |
2364 | 2393 | ||
@@ -2526,6 +2555,7 @@ static var *evaluate(node *op, var *res) | |||
2526 | break; | 2555 | break; |
2527 | 2556 | ||
2528 | case XC( OC_MOVE ): | 2557 | case XC( OC_MOVE ): |
2558 | debug_printf_eval("MOVE\n"); | ||
2529 | /* if source is a temporary string, jusk relink it to dest */ | 2559 | /* if source is a temporary string, jusk relink it to dest */ |
2530 | //Disabled: if R.v is numeric but happens to have cached R.v->string, | 2560 | //Disabled: if R.v is numeric but happens to have cached R.v->string, |
2531 | //then L.v ends up being a string, which is wrong | 2561 | //then L.v ends up being a string, which is wrong |
@@ -2777,6 +2807,7 @@ static var *evaluate(node *op, var *res) | |||
2777 | case XC( OC_BINARY ): | 2807 | case XC( OC_BINARY ): |
2778 | case XC( OC_REPLACE ): { | 2808 | case XC( OC_REPLACE ): { |
2779 | double R_d = getvar_i(R.v); | 2809 | double R_d = getvar_i(R.v); |
2810 | debug_printf_eval("BINARY/REPLACE: R_d:%f opn:%c\n", R_d, opn); | ||
2780 | switch (opn) { | 2811 | switch (opn) { |
2781 | case '+': | 2812 | case '+': |
2782 | L_d += R_d; | 2813 | L_d += R_d; |
@@ -2805,6 +2836,7 @@ static var *evaluate(node *op, var *res) | |||
2805 | L_d -= (int)(L_d / R_d) * R_d; | 2836 | L_d -= (int)(L_d / R_d) * R_d; |
2806 | break; | 2837 | break; |
2807 | } | 2838 | } |
2839 | debug_printf_eval("BINARY/REPLACE result:%f\n", L_d); | ||
2808 | res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, L_d); | 2840 | res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, L_d); |
2809 | break; | 2841 | break; |
2810 | } | 2842 | } |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 9e5e5a0f1..56b11ca46 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -24,6 +24,12 @@ testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" | |||
24 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" | 24 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" |
25 | SKIP= | 25 | SKIP= |
26 | 26 | ||
27 | # check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN | ||
28 | testing "awk floating const with leading zeroes" \ | ||
29 | "awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \ | ||
30 | "0.123000 9.123000\n" \ | ||
31 | "" "\n" | ||
32 | |||
27 | # long field seps requiring regex | 33 | # long field seps requiring regex |
28 | testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ | 34 | testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ |
29 | "2 0 \n3 0 \n4 0 \n5 0 \n" \ | 35 | "2 0 \n3 0 \n4 0 \n5 0 \n" \ |