diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2022-01-08 22:42:35 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2022-01-08 22:42:35 +0100 |
commit | e2952dfaff67f3641d3a6d3226753356170ff808 (patch) | |
tree | 6d77f7f379ba14fbc86bc8ef362fccefa8039f70 | |
parent | 84a1305888ffcd0f4e47cfc4c6fc57918b97bdda (diff) | |
download | busybox-w32-e2952dfaff67f3641d3a6d3226753356170ff808.tar.gz busybox-w32-e2952dfaff67f3641d3a6d3226753356170ff808.tar.bz2 busybox-w32-e2952dfaff67f3641d3a6d3226753356170ff808.zip |
awk: input numbers are never octal or hex (only program consts can be)
function old new delta
next_token 825 930 +105
getvar_i 114 129 +15
nextchar 49 53 +4
my_strtod 138 - -138
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 3/0 up/down: 124/-138) Total: -14 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 29 | ||||
-rwxr-xr-x | testsuite/awk.tests | 12 |
2 files changed, 33 insertions, 8 deletions
diff --git a/editors/awk.c b/editors/awk.c index f6314ac72..079d0bde5 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -848,7 +848,7 @@ static char *nextword(char **s) | |||
848 | static char nextchar(char **s) | 848 | static char nextchar(char **s) |
849 | { | 849 | { |
850 | char c, *pps; | 850 | char c, *pps; |
851 | 851 | again: | |
852 | c = *(*s)++; | 852 | c = *(*s)++; |
853 | pps = *s; | 853 | pps = *s; |
854 | if (c == '\\') | 854 | if (c == '\\') |
@@ -859,8 +859,11 @@ static char nextchar(char **s) | |||
859 | */ | 859 | */ |
860 | if (c == '\\' && *s == pps) { /* unrecognized \z? */ | 860 | if (c == '\\' && *s == pps) { /* unrecognized \z? */ |
861 | c = *(*s); /* yes, fetch z */ | 861 | c = *(*s); /* yes, fetch z */ |
862 | if (c) | 862 | if (c) { /* advance unless z = NUL */ |
863 | (*s)++; /* advance unless z = NUL */ | 863 | (*s)++; |
864 | if (c == '\n') /* \<newline>? eat it */ | ||
865 | goto again; | ||
866 | } | ||
864 | } | 867 | } |
865 | return c; | 868 | return c; |
866 | } | 869 | } |
@@ -882,7 +885,13 @@ static ALWAYS_INLINE int isalnum_(int c) | |||
882 | static double my_strtod(char **pp) | 885 | static double my_strtod(char **pp) |
883 | { | 886 | { |
884 | char *cp = *pp; | 887 | char *cp = *pp; |
885 | if (ENABLE_DESKTOP && cp[0] == '0') { | 888 | return strtod(cp, pp); |
889 | } | ||
890 | #if ENABLE_DESKTOP | ||
891 | static double my_strtod_or_hexoct(char **pp) | ||
892 | { | ||
893 | char *cp = *pp; | ||
894 | if (cp[0] == '0') { | ||
886 | /* Might be hex or octal integer: 0x123abc or 07777 */ | 895 | /* Might be hex or octal integer: 0x123abc or 07777 */ |
887 | char c = (cp[1] | 0x20); | 896 | char c = (cp[1] | 0x20); |
888 | if (c == 'x' || isdigit(cp[1])) { | 897 | if (c == 'x' || isdigit(cp[1])) { |
@@ -901,6 +910,9 @@ static double my_strtod(char **pp) | |||
901 | } | 910 | } |
902 | return strtod(cp, pp); | 911 | return strtod(cp, pp); |
903 | } | 912 | } |
913 | #else | ||
914 | # define my_strtod_or_hexoct(p) my_strtod(p) | ||
915 | #endif | ||
904 | 916 | ||
905 | /* -------- working with variables (set/get/copy/etc) -------- */ | 917 | /* -------- working with variables (set/get/copy/etc) -------- */ |
906 | 918 | ||
@@ -1014,6 +1026,7 @@ static double getvar_i(var *v) | |||
1014 | if (s && *s) { | 1026 | if (s && *s) { |
1015 | debug_printf_eval("getvar_i: '%s'->", s); | 1027 | debug_printf_eval("getvar_i: '%s'->", s); |
1016 | v->number = my_strtod(&s); | 1028 | v->number = my_strtod(&s); |
1029 | /* ^^^ hex/oct NOT allowed here! */ | ||
1017 | debug_printf_eval("%f (s:'%s')\n", v->number, s); | 1030 | debug_printf_eval("%f (s:'%s')\n", v->number, s); |
1018 | if (v->type & VF_USER) { | 1031 | if (v->type & VF_USER) { |
1019 | //TODO: skip_spaces() also skips backslash+newline, is it intended here? | 1032 | //TODO: skip_spaces() also skips backslash+newline, is it intended here? |
@@ -1125,10 +1138,10 @@ static uint32_t next_token(uint32_t expected) | |||
1125 | if (*p == '\0') { | 1138 | if (*p == '\0') { |
1126 | tc = TC_EOF; | 1139 | tc = TC_EOF; |
1127 | debug_printf_parse("%s: token found: TC_EOF\n", __func__); | 1140 | debug_printf_parse("%s: token found: TC_EOF\n", __func__); |
1128 | } else if (*p == '\"') { | 1141 | } else if (*p == '"') { |
1129 | /* it's a string */ | 1142 | /* it's a string */ |
1130 | char *s = t_string = ++p; | 1143 | char *s = t_string = ++p; |
1131 | while (*p != '\"') { | 1144 | while (*p != '"') { |
1132 | char *pp; | 1145 | char *pp; |
1133 | if (*p == '\0' || *p == '\n') | 1146 | if (*p == '\0' || *p == '\n') |
1134 | syntax_error(EMSG_UNEXP_EOS); | 1147 | syntax_error(EMSG_UNEXP_EOS); |
@@ -1166,7 +1179,8 @@ static uint32_t next_token(uint32_t expected) | |||
1166 | } else if (*p == '.' || isdigit(*p)) { | 1179 | } else if (*p == '.' || isdigit(*p)) { |
1167 | /* it's a number */ | 1180 | /* it's a number */ |
1168 | char *pp = p; | 1181 | char *pp = p; |
1169 | t_double = my_strtod(&pp); | 1182 | t_double = my_strtod_or_hexoct(&pp); |
1183 | /* ^^^ awk only allows hex/oct consts in _program_, not in _input_ */ | ||
1170 | p = pp; | 1184 | p = pp; |
1171 | if (*p == '.') | 1185 | if (*p == '.') |
1172 | syntax_error(EMSG_UNEXP_TOKEN); | 1186 | syntax_error(EMSG_UNEXP_TOKEN); |
@@ -3503,6 +3517,7 @@ static var *evaluate(node *op, var *res) | |||
3503 | i = (Ld == 0); | 3517 | i = (Ld == 0); |
3504 | break; | 3518 | break; |
3505 | } | 3519 | } |
3520 | debug_printf_eval("COMPARE result: %d\n", (i == 0) ^ (opn & 1)); | ||
3506 | setvar_i(res, (i == 0) ^ (opn & 1)); | 3521 | setvar_i(res, (i == 0) ^ (opn & 1)); |
3507 | break; | 3522 | break; |
3508 | } | 3523 | } |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index bcaafe8fd..93e25d8c1 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -102,9 +102,13 @@ testing "awk unused function args are evaluated" \ | |||
102 | optional DESKTOP | 102 | optional DESKTOP |
103 | testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4294967295\n" "" "\n" | 103 | testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4294967295\n" "" "\n" |
104 | testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2147483649\n" "" "\n" | 104 | testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2147483649\n" "" "\n" |
105 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" | 105 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" |
106 | SKIP= | 106 | SKIP= |
107 | 107 | ||
108 | # check that "hex/oct integer" heuristic doesn't kick in on input | ||
109 | # (must be done only when parsing program text) | ||
110 | testing "awk input is never oct" "awk '{ print \$1, \$1+1 }'" "011 12\n" "" "011\n" | ||
111 | |||
108 | # check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN | 112 | # check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN |
109 | testing "awk floating const with leading zeroes" \ | 113 | testing "awk floating const with leading zeroes" \ |
110 | "awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \ | 114 | "awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \ |
@@ -469,4 +473,10 @@ testing 'awk printf %% prints one %' \ | |||
469 | "%\n" \ | 473 | "%\n" \ |
470 | '' '' | 474 | '' '' |
471 | 475 | ||
476 | testing 'awk backslash+newline eaten with no trace' \ | ||
477 | "awk 'BEGIN { printf \"Hello\\ | ||
478 | world\n\" }'" \ | ||
479 | "Hello world\n" \ | ||
480 | '' '' | ||
481 | |||
472 | exit $FAILCOUNT | 482 | exit $FAILCOUNT |