summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rw-r--r--bin/sh/main.c4
-rw-r--r--bin/sh/parser.c23
-rw-r--r--bin/sh/sh.14
-rw-r--r--bin/sh/var.c7
-rw-r--r--bin/sh/var.h3
5 files changed, 37 insertions, 4 deletions
diff --git a/bin/sh/main.c b/bin/sh/main.c
index d3250eb..d962920 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -76,7 +76,7 @@ __FBSDID("$FreeBSD$");
int rootpid;
int rootshell;
struct jmploc main_handler;
-int localeisutf8;
+int localeisutf8, initial_localeisutf8;
static void read_profile(const char *);
static char *find_dot_file(char *);
@@ -97,7 +97,7 @@ main(int argc, char *argv[])
char *shinit;
(void) setlocale(LC_ALL, "");
- updatecharset();
+ initcharset();
state = 0;
if (setjmp(main_handler.loc)) {
switch (exception) {
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index 5133d67..cc1860d 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -1219,6 +1219,29 @@ readcstyleesc(char *out)
if (v == 0 || (v >= 0xd800 && v <= 0xdfff))
synerror("Bad escape sequence");
/* We really need iconv here. */
+ if (initial_localeisutf8 && v > 127) {
+ CHECKSTRSPACE(4, out);
+ /*
+ * We cannot use wctomb() as the locale may have
+ * changed.
+ */
+ if (v <= 0x7ff) {
+ USTPUTC(0xc0 | v >> 6, out);
+ USTPUTC(0x80 | (v & 0x3f), out);
+ return out;
+ } else if (v <= 0xffff) {
+ USTPUTC(0xe0 | v >> 12, out);
+ USTPUTC(0x80 | ((v >> 6) & 0x3f), out);
+ USTPUTC(0x80 | (v & 0x3f), out);
+ return out;
+ } else if (v <= 0x10ffff) {
+ USTPUTC(0xf0 | v >> 18, out);
+ USTPUTC(0x80 | ((v >> 12) & 0x3f), out);
+ USTPUTC(0x80 | ((v >> 6) & 0x3f), out);
+ USTPUTC(0x80 | (v & 0x3f), out);
+ return out;
+ }
+ }
if (v > 127)
v = '?';
break;
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 5710060..838cafe 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -463,8 +463,8 @@ The Unicode code point
(eight hexadecimal digits)
.El
.Pp
-The sequences for Unicode code points currently only provide useful results
-for values below 128.
+The sequences for Unicode code points are currently only useful with
+UTF-8 locales.
They reject code point 0 and UTF-16 surrogates.
.Pp
If an escape sequence would produce a byte with value 0,
diff --git a/bin/sh/var.c b/bin/sh/var.c
index 33890db..84b6dea 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -517,6 +517,13 @@ updatecharset(void)
localeisutf8 = !strcmp(charset, "UTF-8");
}
+void
+initcharset(void)
+{
+ updatecharset();
+ initial_localeisutf8 = localeisutf8;
+}
+
/*
* Generate a list of exported variables. This routine is used to construct
* the third argument to execve when executing a program.
diff --git a/bin/sh/var.h b/bin/sh/var.h
index 323ddc2..ff21c7d 100644
--- a/bin/sh/var.h
+++ b/bin/sh/var.h
@@ -83,6 +83,8 @@ extern struct var vterm;
#endif
extern int localeisutf8;
+/* The parser uses the locale that was in effect at startup. */
+extern int initial_localeisutf8;
/*
* The following macros access the values of the above variables.
@@ -116,6 +118,7 @@ char *bltinlookup(const char *, int);
void bltinsetlocale(void);
void bltinunsetlocale(void);
void updatecharset(void);
+void initcharset(void);
char **environment(void);
int showvarscmd(int, char **);
int exportcmd(int, char **);
OpenPOWER on IntegriCloud