diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2012-06-22 18:41:01 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2012-06-22 18:41:01 +0200 |
commit | ea664dde87d8e52df7d4003d988352a66562a945 (patch) | |
tree | 76de10da36e3d53809538f42fd1267ff90b44b83 | |
parent | 440a509849391f2dc8ec720a136577ede3306fa8 (diff) | |
download | busybox-w32-ea664dde87d8e52df7d4003d988352a66562a945.tar.gz busybox-w32-ea664dde87d8e52df7d4003d988352a66562a945.tar.bz2 busybox-w32-ea664dde87d8e52df7d4003d988352a66562a945.zip |
awk: make -F STR interpret escape sequences. Closes 5126
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 26 | ||||
-rwxr-xr-x | testsuite/awk.tests | 5 |
2 files changed, 24 insertions, 7 deletions
diff --git a/editors/awk.c b/editors/awk.c index 71abca215..d69720d64 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -696,6 +696,10 @@ static char nextchar(char **s) | |||
696 | pps = *s; | 696 | pps = *s; |
697 | if (c == '\\') | 697 | if (c == '\\') |
698 | c = bb_process_escape_sequence((const char**)s); | 698 | c = bb_process_escape_sequence((const char**)s); |
699 | /* Example awk statement: | ||
700 | * s = "abc\"def" | ||
701 | * we must treat \" as " | ||
702 | */ | ||
699 | if (c == '\\' && *s == pps) { /* unrecognized \z? */ | 703 | if (c == '\\' && *s == pps) { /* unrecognized \z? */ |
700 | c = *(*s); /* yes, fetch z */ | 704 | c = *(*s); /* yes, fetch z */ |
701 | if (c) | 705 | if (c) |
@@ -704,6 +708,15 @@ static char nextchar(char **s) | |||
704 | return c; | 708 | return c; |
705 | } | 709 | } |
706 | 710 | ||
711 | /* TODO: merge with strcpy_and_process_escape_sequences()? | ||
712 | */ | ||
713 | static void unescape_string_in_place(char *s1) | ||
714 | { | ||
715 | char *s = s1; | ||
716 | while ((*s1 = nextchar(&s)) != '\0') | ||
717 | s1++; | ||
718 | } | ||
719 | |||
707 | static ALWAYS_INLINE int isalnum_(int c) | 720 | static ALWAYS_INLINE int isalnum_(int c) |
708 | { | 721 | { |
709 | return (isalnum(c) || c == '_'); | 722 | return (isalnum(c) || c == '_'); |
@@ -2992,7 +3005,7 @@ static int awk_exit(int r) | |||
2992 | * otherwise return 0 */ | 3005 | * otherwise return 0 */ |
2993 | static int is_assignment(const char *expr) | 3006 | static int is_assignment(const char *expr) |
2994 | { | 3007 | { |
2995 | char *exprc, *val, *s, *s1; | 3008 | char *exprc, *val; |
2996 | 3009 | ||
2997 | if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) { | 3010 | if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) { |
2998 | return FALSE; | 3011 | return FALSE; |
@@ -3002,10 +3015,7 @@ static int is_assignment(const char *expr) | |||
3002 | val = exprc + (val - expr); | 3015 | val = exprc + (val - expr); |
3003 | *val++ = '\0'; | 3016 | *val++ = '\0'; |
3004 | 3017 | ||
3005 | s = s1 = val; | 3018 | unescape_string_in_place(val); |
3006 | while ((*s1 = nextchar(&s)) != '\0') | ||
3007 | s1++; | ||
3008 | |||
3009 | setvar_u(newvar(exprc), val); | 3019 | setvar_u(newvar(exprc), val); |
3010 | free(exprc); | 3020 | free(exprc); |
3011 | return TRUE; | 3021 | return TRUE; |
@@ -3118,8 +3128,10 @@ int awk_main(int argc, char **argv) | |||
3118 | opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, NULL); | 3128 | opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, NULL); |
3119 | argv += optind; | 3129 | argv += optind; |
3120 | argc -= optind; | 3130 | argc -= optind; |
3121 | if (opt & 0x1) | 3131 | if (opt & 0x1) { /* -F */ |
3122 | setvar_s(intvar[FS], opt_F); // -F | 3132 | unescape_string_in_place(opt_F); |
3133 | setvar_s(intvar[FS], opt_F); | ||
3134 | } | ||
3123 | while (list_v) { /* -v */ | 3135 | while (list_v) { /* -v */ |
3124 | if (!is_assignment(llist_pop(&list_v))) | 3136 | if (!is_assignment(llist_pop(&list_v))) |
3125 | bb_show_usage(); | 3137 | bb_show_usage(); |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index e67190757..d4c390d31 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -43,6 +43,11 @@ testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ | |||
43 | "" \ | 43 | "" \ |
44 | "a--\na--b--\na--b--c--\na--b--c--d--" | 44 | "a--\na--b--\na--b--c--\na--b--c--d--" |
45 | 45 | ||
46 | testing "awk -F handles escapes" "awk -F'\\x21' '{print \$1}'" \ | ||
47 | "a\n" \ | ||
48 | "" \ | ||
49 | "a!b\n" | ||
50 | |||
46 | # '@(samp|code|file)\{' is an invalid extended regex (unmatched '{'), | 51 | # '@(samp|code|file)\{' is an invalid extended regex (unmatched '{'), |
47 | # but gawk 3.1.5 does not bail out on it. | 52 | # but gawk 3.1.5 does not bail out on it. |
48 | testing "awk gsub falls back to non-extended-regex" \ | 53 | testing "awk gsub falls back to non-extended-regex" \ |