summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-09-02 09:00:23 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-09-02 09:00:23 +0000
commita2e1eea189981e03b2590c2cd59b9ae65a9cea4f (patch)
treeb60ca60a9413444dd2847c320eaa38ea0ec00e93
parentb424930e4ea971ff8675c30d5dc4445c173b2b1a (diff)
downloadbusybox-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.c47
-rwxr-xr-xtestsuite/awk.tests1
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
684static 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
686static xhash *iamarray(var *v) 698static 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 */
820static 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
807static var *copyvar(var *dest, const var *src) 831static 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"
20testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n" 20testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n"
21testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n" 21testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n"
22testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n" 22testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n"
23testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n"
23 24
24tar xjf awk_t1.tar.bz2 25tar xjf awk_t1.tar.bz2
25testing "awk 'gcc build bug'" \ 26testing "awk 'gcc build bug'" \