From c538d5bcc304d1ac99783de2337937c70a7013c7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Aug 2014 09:57:44 +0200 Subject: hush: make ${#var} unicode-aware This mimics bash Signed-off-by: Denys Vlasenko --- shell/hush.c | 29 +++++++++++++++++++---------- shell/hush_test/hush-misc/unicode1.right | 3 +++ shell/hush_test/hush-misc/unicode1.tests | 13 +++++++++++++ 3 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 shell/hush_test/hush-misc/unicode1.right create mode 100755 shell/hush_test/hush-misc/unicode1.tests (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index e1d0ece29..7d3547110 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1976,6 +1976,22 @@ static struct variable *set_vars_and_save_old(char **strings) } +/* + * Unicode helper + */ +static void reinit_unicode_for_hush(void) +{ + /* Unicode support should be activated even if LANG is set + * _during_ shell execution, not only if it was set when + * shell was started. Therefore, re-check LANG every time: + */ + const char *s = get_local_var_value("LC_ALL"); + if (!s) s = get_local_var_value("LC_CTYPE"); + if (!s) s = get_local_var_value("LANG"); + reinit_unicode(s); +} + + /* * in_str support */ @@ -2042,15 +2058,7 @@ static void get_user_input(struct in_str *i) /* Enable command line editing only while a command line * is actually being read */ do { - /* Unicode support should be activated even if LANG is set - * _during_ shell execution, not only if it was set when - * shell was started. Therefore, re-check LANG every time: - */ - const char *s = get_local_var_value("LC_ALL"); - if (!s) s = get_local_var_value("LC_CTYPE"); - if (!s) s = get_local_var_value("LANG"); - reinit_unicode(s); - + reinit_unicode_for_hush(); G.flag_SIGINT = 0; /* buglet: SIGINT will not make new prompt to appear _at once_, * only after . (^C will work) */ @@ -5028,8 +5036,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha /* Handle any expansions */ if (exp_op == 'L') { + reinit_unicode_for_hush(); debug_printf_expand("expand: length(%s)=", val); - val = utoa(val ? strlen(val) : 0); + val = utoa(val ? unicode_strlen(val) : 0); debug_printf_expand("%s\n", val); } else if (exp_op) { if (exp_op == '%' || exp_op == '#') { diff --git a/shell/hush_test/hush-misc/unicode1.right b/shell/hush_test/hush-misc/unicode1.right new file mode 100644 index 000000000..d3bbbf697 --- /dev/null +++ b/shell/hush_test/hush-misc/unicode1.right @@ -0,0 +1,3 @@ +1 +1 +Ok diff --git a/shell/hush_test/hush-misc/unicode1.tests b/shell/hush_test/hush-misc/unicode1.tests new file mode 100755 index 000000000..8788ba910 --- /dev/null +++ b/shell/hush_test/hush-misc/unicode1.tests @@ -0,0 +1,13 @@ +LANG=en_US.UTF-8 + +# A combining character U+300 +a=`printf "\xcc\x80"` +# Should print 1 +echo ${#a} + +# A Japanese katakana charachter U+30a3 +a=`printf "\xe3\x82\xa3"` +# Should print 1 +echo ${#a} + +echo Ok -- cgit v1.2.3-55-g6feb From 841f8331d79c642b4268dae52c382fab2da9cddc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Aug 2014 10:09:49 +0200 Subject: ash,hush: run reinit_unicode() only if makes sense With static Unicode support, no need to check $LANG et al. Signed-off-by: Denys Vlasenko --- shell/ash.c | 4 +++- shell/hush.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index dc7a9bf4f..3b8aac553 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9661,7 +9661,9 @@ preadfd(void) * _during_ shell execution, not only if it was set when * shell was started. Therefore, re-check LANG every time: */ - { + if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV + || ENABLE_UNICODE_USING_LOCALE + ) { const char *s = lookupvar("LC_ALL"); if (!s) s = lookupvar("LC_CTYPE"); if (!s) s = lookupvar("LANG"); diff --git a/shell/hush.c b/shell/hush.c index 7d3547110..92d790180 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1985,10 +1985,14 @@ static void reinit_unicode_for_hush(void) * _during_ shell execution, not only if it was set when * shell was started. Therefore, re-check LANG every time: */ - const char *s = get_local_var_value("LC_ALL"); - if (!s) s = get_local_var_value("LC_CTYPE"); - if (!s) s = get_local_var_value("LANG"); - reinit_unicode(s); + if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV + || ENABLE_UNICODE_USING_LOCALE + ) { + const char *s = get_local_var_value("LC_ALL"); + if (!s) s = get_local_var_value("LC_CTYPE"); + if (!s) s = get_local_var_value("LANG"); + reinit_unicode(s); + } } -- cgit v1.2.3-55-g6feb From e9ab07c211b283c0f798628858eaaef93a4893aa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Aug 2014 18:00:08 +0200 Subject: ash: make ${#var} unicode-aware Signed-off-by: Denys Vlasenko --- shell/ash.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 3b8aac553..4ead6f990 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2121,6 +2121,22 @@ lookupvar(const char *name) return NULL; } +static void reinit_unicode_for_ash(void) +{ + /* Unicode support should be activated even if LANG is set + * _during_ shell execution, not only if it was set when + * shell was started. Therefore, re-check LANG every time: + */ + if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV + || ENABLE_UNICODE_USING_LOCALE + ) { + const char *s = lookupvar("LC_ALL"); + if (!s) s = lookupvar("LC_CTYPE"); + if (!s) s = lookupvar("LANG"); + reinit_unicode(s); + } +} + /* * Search the environment of a builtin command. */ @@ -6798,7 +6814,15 @@ evalvar(char *p, int flags, struct strlist *var_str_list) varunset(p, var, 0, 0); if (subtype == VSLENGTH) { - cvtnum(varlen > 0 ? varlen : 0); + ssize_t n = varlen; + if (n > 0) { + reinit_unicode_for_ash(); + if (unicode_status == UNICODE_ON) { + const char *val = lookupvar(var); + n = unicode_strlen(val); + } + } + cvtnum(n > 0 ? n : 0); goto record; } @@ -9657,18 +9681,7 @@ preadfd(void) # if ENABLE_FEATURE_TAB_COMPLETION line_input_state->path_lookup = pathval(); # endif - /* Unicode support should be activated even if LANG is set - * _during_ shell execution, not only if it was set when - * shell was started. Therefore, re-check LANG every time: - */ - if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV - || ENABLE_UNICODE_USING_LOCALE - ) { - const char *s = lookupvar("LC_ALL"); - if (!s) s = lookupvar("LC_CTYPE"); - if (!s) s = lookupvar("LANG"); - reinit_unicode(s); - } + reinit_unicode_for_ash(); nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout); if (nr == 0) { /* Ctrl+C pressed */ -- cgit v1.2.3-55-g6feb From 2ec34969e73c5262e20d3b4599196ff03913e66e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Sep 2014 16:52:39 +0200 Subject: ash: factor out ASH_HELP config option It used to be aliased to !FEATURE_SH_EXTRA_QUIET for ash, while hush had it separate from FEATURE_SH_EXTRA_QUIET. Bring ash in line with hush. Signed-off-by: Denys Vlasenko --- shell/ash.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 4ead6f990..293f15147 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -143,6 +143,13 @@ //config: help //config: Enable support for test builtin in ash. //config: +//config:config ASH_HELP +//config: bool "help builtin" +//config: default y +//config: depends on ASH +//config: help +//config: Enable help builtin in ash. +//config: //config:config ASH_CMDCMD //config: bool "'command' command to override shell builtins" //config: default y @@ -8804,8 +8811,8 @@ setinteractive(int on) if (!did_banner) { /* note: ash and hush share this string */ out1fmt("\n\n%s %s\n" - "Enter 'help' for a list of built-in commands." - "\n\n", + IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n") + "\n", bb_banner, "built-in shell (ash)" ); @@ -9058,7 +9065,7 @@ static int exportcmd(int, char **) FAST_FUNC; #if ENABLE_ASH_GETOPTS static int getoptscmd(int, char **) FAST_FUNC; #endif -#if !ENABLE_FEATURE_SH_EXTRA_QUIET +#if ENABLE_ASH_HELP static int helpcmd(int, char **) FAST_FUNC; #endif #if MAX_HISTORY @@ -9134,7 +9141,7 @@ static const struct builtincmd builtintab[] = { { BUILTIN_REGULAR "getopts" , getoptscmd }, #endif { BUILTIN_NOSPEC "hash" , hashcmd }, -#if !ENABLE_FEATURE_SH_EXTRA_QUIET +#if ENABLE_ASH_HELP { BUILTIN_NOSPEC "help" , helpcmd }, #endif #if MAX_HISTORY @@ -12611,10 +12618,7 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) /* ============ Builtins */ -#if !ENABLE_FEATURE_SH_EXTRA_QUIET -/* - * Lists available builtins - */ +#if ENABLE_ASH_HELP static int FAST_FUNC helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { @@ -12632,7 +12636,7 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) col = 0; } } -#if ENABLE_FEATURE_SH_STANDALONE +# if ENABLE_FEATURE_SH_STANDALONE { const char *a = applet_names; while (*a) { @@ -12644,11 +12648,11 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) a += strlen(a) + 1; } } -#endif +# endif out1fmt("\n\n"); return EXIT_SUCCESS; } -#endif /* FEATURE_SH_EXTRA_QUIET */ +#endif #if MAX_HISTORY static int FAST_FUNC -- cgit v1.2.3-55-g6feb From 07f7ea70edd0fdc7ad7da36df3f487111e14d0d1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Sep 2014 17:21:52 +0200 Subject: ash: fix off-by-one in "jobs %4" handling. closes 7310 Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 293f15147..705fe9fa4 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3647,7 +3647,7 @@ getjob(const char *name, int getctl) if (is_number(p)) { num = atoi(p); - if (num < njobs) { + if (num <= njobs) { jp = jobtab + num - 1; if (jp->used) goto gotit; -- cgit v1.2.3-55-g6feb