aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-10-05 13:22:11 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-10-05 13:22:11 +0200
commitd527e0c81d2efe98f258f1e1516a0e9cbe879154 (patch)
tree104ab5a0d550ea60151891848581880c0eca7e9a
parent5b3430017895001e134b6c37a0ea4d2c082ba209 (diff)
downloadbusybox-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.c48
-rwxr-xr-xtestsuite/awk.tests6
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
701static double my_strtod(char **pp) 705static 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" ""
24testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" 24testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n"
25SKIP= 25SKIP=
26 26
27# check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN
28testing "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
28testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ 34testing "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" \