diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-09-02 09:00:23 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-09-02 09:00:23 +0000 |
commit | a2e1eea189981e03b2590c2cd59b9ae65a9cea4f (patch) | |
tree | b60ca60a9413444dd2847c320eaa38ea0ec00e93 | |
parent | b424930e4ea971ff8675c30d5dc4445c173b2b1a (diff) | |
download | busybox-w32-a2e1eea189981e03b2590c2cd59b9ae65a9cea4f.tar.gz busybox-w32-a2e1eea189981e03b2590c2cd59b9ae65a9cea4f.tar.bz2 busybox-w32-a2e1eea189981e03b2590c2cd59b9ae65a9cea4f.zip |
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
-rw-r--r-- | editors/awk.c | 47 | ||||
-rwxr-xr-x | testsuite/awk.tests | 1 |
2 files changed, 34 insertions, 14 deletions
diff --git a/editors/awk.c b/editors/awk.c index 72eca245f..74e3adce5 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -681,6 +681,18 @@ static ALWAYS_INLINE int isalnum_(int c) | |||
681 | return (isalnum(c) || c == '_'); | 681 | return (isalnum(c) || c == '_'); |
682 | } | 682 | } |
683 | 683 | ||
684 | static double my_strtod(char **pp) | ||
685 | { | ||
686 | #if ENABLE_DESKTOP | ||
687 | if ((*pp)[0] == '0' | ||
688 | && ((((*pp)[1] | 0x20) == 'x') || isdigit((*pp)[1])) | ||
689 | ) { | ||
690 | return strtoull(*pp, pp, 0); | ||
691 | } | ||
692 | #endif | ||
693 | return strtod(*pp, pp); | ||
694 | } | ||
695 | |||
684 | /* -------- working with variables (set/get/copy/etc) -------- */ | 696 | /* -------- working with variables (set/get/copy/etc) -------- */ |
685 | 697 | ||
686 | static xhash *iamarray(var *v) | 698 | static xhash *iamarray(var *v) |
@@ -790,7 +802,7 @@ static double getvar_i(var *v) | |||
790 | v->number = 0; | 802 | v->number = 0; |
791 | s = v->string; | 803 | s = v->string; |
792 | if (s && *s) { | 804 | if (s && *s) { |
793 | v->number = strtod(s, &s); | 805 | v->number = my_strtod(&s); |
794 | if (v->type & VF_USER) { | 806 | if (v->type & VF_USER) { |
795 | skip_spaces(&s); | 807 | skip_spaces(&s); |
796 | if (*s != '\0') | 808 | if (*s != '\0') |
@@ -804,6 +816,18 @@ static double getvar_i(var *v) | |||
804 | return v->number; | 816 | return v->number; |
805 | } | 817 | } |
806 | 818 | ||
819 | /* Used for operands of bitwise ops */ | ||
820 | static unsigned long getvar_i_int(var *v) | ||
821 | { | ||
822 | double d = getvar_i(v); | ||
823 | |||
824 | /* Casting doubles to longs is undefined for values outside | ||
825 | * of target type range. Try to widen it as much as possible */ | ||
826 | if (d >= 0) | ||
827 | return (unsigned long)d; | ||
828 | return - (long) (unsigned long) (-d); | ||
829 | } | ||
830 | |||
807 | static var *copyvar(var *dest, const var *src) | 831 | static var *copyvar(var *dest, const var *src) |
808 | { | 832 | { |
809 | if (dest != src) { | 833 | if (dest != src) { |
@@ -973,12 +997,7 @@ static uint32_t next_token(uint32_t expected) | |||
973 | 997 | ||
974 | } else if (*p == '.' || isdigit(*p)) { | 998 | } else if (*p == '.' || isdigit(*p)) { |
975 | /* it's a number */ | 999 | /* it's a number */ |
976 | #if ENABLE_DESKTOP | 1000 | t_double = my_strtod(&p); |
977 | if (p[0] == '0' && (p[1] | 0x20) == 'x') | ||
978 | t_double = strtoll(p, &p, 0); | ||
979 | else | ||
980 | #endif | ||
981 | t_double = strtod(p, &p); | ||
982 | if (*p == '.') | 1001 | if (*p == '.') |
983 | syntax_error(EMSG_UNEXP_TOKEN); | 1002 | syntax_error(EMSG_UNEXP_TOKEN); |
984 | tc = TC_NUMBER; | 1003 | tc = TC_NUMBER; |
@@ -2022,7 +2041,7 @@ static var *exec_builtin(node *op, var *res) | |||
2022 | n = awk_split(as[0], spl, &s); | 2041 | n = awk_split(as[0], spl, &s); |
2023 | s1 = s; | 2042 | s1 = s; |
2024 | clear_array(iamarray(av[1])); | 2043 | clear_array(iamarray(av[1])); |
2025 | for (i=1; i<=n; i++) | 2044 | for (i = 1; i <= n; i++) |
2026 | setari_u(av[1], i, nextword(&s1)); | 2045 | setari_u(av[1], i, nextword(&s1)); |
2027 | free(s); | 2046 | free(s); |
2028 | setvar_i(res, n); | 2047 | setvar_i(res, n); |
@@ -2042,27 +2061,27 @@ static var *exec_builtin(node *op, var *res) | |||
2042 | /* Bitwise ops must assume that operands are unsigned. GNU Awk 3.1.5: | 2061 | /* Bitwise ops must assume that operands are unsigned. GNU Awk 3.1.5: |
2043 | * awk '{ print or(-1,1) }' gives "4.29497e+09", not "-2.xxxe+09" */ | 2062 | * awk '{ print or(-1,1) }' gives "4.29497e+09", not "-2.xxxe+09" */ |
2044 | case B_an: | 2063 | case B_an: |
2045 | setvar_i(res, (unsigned long)getvar_i(av[0]) & (unsigned long)getvar_i(av[1])); | 2064 | setvar_i(res, getvar_i_int(av[0]) & getvar_i_int(av[1])); |
2046 | break; | 2065 | break; |
2047 | 2066 | ||
2048 | case B_co: | 2067 | case B_co: |
2049 | setvar_i(res, ~(unsigned long)getvar_i(av[0])); | 2068 | setvar_i(res, ~getvar_i_int(av[0])); |
2050 | break; | 2069 | break; |
2051 | 2070 | ||
2052 | case B_ls: | 2071 | case B_ls: |
2053 | setvar_i(res, (unsigned long)getvar_i(av[0]) << (unsigned long)getvar_i(av[1])); | 2072 | setvar_i(res, getvar_i_int(av[0]) << getvar_i_int(av[1])); |
2054 | break; | 2073 | break; |
2055 | 2074 | ||
2056 | case B_or: | 2075 | case B_or: |
2057 | setvar_i(res, (unsigned long)getvar_i(av[0]) | (unsigned long)getvar_i(av[1])); | 2076 | setvar_i(res, getvar_i_int(av[0]) | getvar_i_int(av[1])); |
2058 | break; | 2077 | break; |
2059 | 2078 | ||
2060 | case B_rs: | 2079 | case B_rs: |
2061 | setvar_i(res, (unsigned long)getvar_i(av[0]) >> (unsigned long)getvar_i(av[1])); | 2080 | setvar_i(res, getvar_i_int(av[0]) >> getvar_i_int(av[1])); |
2062 | break; | 2081 | break; |
2063 | 2082 | ||
2064 | case B_xo: | 2083 | case B_xo: |
2065 | setvar_i(res, (unsigned long)getvar_i(av[0]) ^ (unsigned long)getvar_i(av[1])); | 2084 | setvar_i(res, getvar_i_int(av[0]) ^ getvar_i_int(av[1])); |
2066 | break; | 2085 | break; |
2067 | 2086 | ||
2068 | case B_lo: | 2087 | case B_lo: |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index b3c076e4b..aa386361f 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -20,6 +20,7 @@ testing "awk -F case 7" "awk -F '[#]' '{ print NF }'" "5\n" "" "z##abc##zz\n" | |||
20 | testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n" | 20 | testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n" |
21 | testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n" | 21 | testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n" |
22 | testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n" | 22 | testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n" |
23 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" | ||
23 | 24 | ||
24 | tar xjf awk_t1.tar.bz2 | 25 | tar xjf awk_t1.tar.bz2 |
25 | testing "awk 'gcc build bug'" \ | 26 | testing "awk 'gcc build bug'" \ |