aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2012-06-22 18:41:01 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2012-06-22 18:41:01 +0200
commitea664dde87d8e52df7d4003d988352a66562a945 (patch)
tree76de10da36e3d53809538f42fd1267ff90b44b83
parent440a509849391f2dc8ec720a136577ede3306fa8 (diff)
downloadbusybox-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.c26
-rwxr-xr-xtestsuite/awk.tests5
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 */
713static void unescape_string_in_place(char *s1)
714{
715 char *s = s1;
716 while ((*s1 = nextchar(&s)) != '\0')
717 s1++;
718}
719
707static ALWAYS_INLINE int isalnum_(int c) 720static 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 */
2993static int is_assignment(const char *expr) 3006static 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
46testing "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.
48testing "awk gsub falls back to non-extended-regex" \ 53testing "awk gsub falls back to non-extended-regex" \