$'…' functionality, documentation improvements, fixes for backslash
expansion in all modes, regression tests for both kinds of backslash expansion; unbksl() revamp; make CTRL macro available globally
This commit is contained in:
parent
c8eb13a13f
commit
9fd4b9db41
122
check.t
122
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.306 2009/09/19 18:36:57 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.307 2009/09/19 21:54:42 tg Exp $
|
||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||
@ -25,7 +25,7 @@
|
||||
# http://www.research.att.com/~gsf/public/ifs.sh
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R39 2009/09/07
|
||||
@(#)MIRBSD KSH R39 2009/09/19
|
||||
description:
|
||||
Check version of shell.
|
||||
stdin:
|
||||
@ -5210,6 +5210,14 @@ stdin:
|
||||
expected-stdout:
|
||||
<däÛÛ€Û@>
|
||||
---
|
||||
name: print-bksl-c
|
||||
description:
|
||||
Check print builtin's \c escape
|
||||
stdin:
|
||||
print '\ca'; print b
|
||||
expected-stdout:
|
||||
ab
|
||||
---
|
||||
name: print-nul-chars
|
||||
description:
|
||||
Check handling of NUL characters for print and read
|
||||
@ -5223,6 +5231,116 @@ expected-stdout:
|
||||
4
|
||||
3 2
|
||||
---
|
||||
name: print-escapes
|
||||
description:
|
||||
Check backslash expansion by the print builtin
|
||||
stdin:
|
||||
print '\ \!\"\#\$\%\&'\\\''\(\)\*\+\,\-\.\/\0\1\2\3\4\5\6\7\8' \
|
||||
'\9\:\;\<\=\>\?\@\A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T' \
|
||||
'\U\V\W\X\Y\Z\[\\\]\^\_\`\a\b \d\e\f\g\h\i\j\k\l\m\n\o\p' \
|
||||
'\q\r\s\t\u\v\w\x\y\z\{\|\}\~' '\u20acd' '\U20acd' '\x123' \
|
||||
'\0x' '\0123' '\01234' | {
|
||||
typeset -Uui16 -Z11 pos=0
|
||||
typeset -Uui16 -Z5 hv
|
||||
typeset -i1 wc=0x0A
|
||||
dasc=
|
||||
nl=${wc#1#}
|
||||
while IFS= read -r line; do
|
||||
line=$line$nl
|
||||
while [[ -n $line ]]; do
|
||||
hv=1#${line::1}
|
||||
if (( (pos & 15) == 0 )); then
|
||||
(( pos )) && print "$dasc|"
|
||||
print -n "${pos#16#} "
|
||||
dasc=' |'
|
||||
fi
|
||||
print -n "${hv#16#} "
|
||||
if (( (hv < 32) || (hv > 126) )); then
|
||||
dasc=$dasc.
|
||||
else
|
||||
dasc=$dasc${line::1}
|
||||
fi
|
||||
(( (pos++ & 15) == 7 )) && print -n -- '- '
|
||||
line=${line:1}
|
||||
done
|
||||
done
|
||||
if (( (pos & 15) != 1 )); then
|
||||
while (( pos & 15 )); do
|
||||
print -n ' '
|
||||
(( (pos++ & 15) == 7 )) && print -n -- '- '
|
||||
done
|
||||
print "$dasc|"
|
||||
fi
|
||||
}
|
||||
expected-stdout:
|
||||
00000000 5C 20 5C 21 5C 22 5C 23 - 5C 24 5C 25 5C 26 5C 27 |\ \!\"\#\$\%\&\'|
|
||||
00000010 5C 28 5C 29 5C 2A 5C 2B - 5C 2C 5C 2D 5C 2E 5C 2F |\(\)\*\+\,\-\.\/|
|
||||
00000020 5C 31 5C 32 5C 33 5C 34 - 5C 35 5C 36 5C 37 5C 38 |\1\2\3\4\5\6\7\8|
|
||||
00000030 20 5C 39 5C 3A 5C 3B 5C - 3C 5C 3D 5C 3E 5C 3F 5C | \9\:\;\<\=\>\?\|
|
||||
00000040 40 5C 41 5C 42 5C 43 5C - 44 1B 5C 46 5C 47 5C 48 |@\A\B\C\D.\F\G\H|
|
||||
00000050 5C 49 5C 4A 5C 4B 5C 4C - 5C 4D 5C 4E 5C 4F 5C 50 |\I\J\K\L\M\N\O\P|
|
||||
00000060 5C 51 5C 52 5C 53 5C 54 - 20 5C 56 5C 57 5C 58 5C |\Q\R\S\T \V\W\X\|
|
||||
00000070 59 5C 5A 5C 5B 5C 5C 5D - 5C 5E 5C 5F 5C 60 07 08 |Y\Z\[\]\^\_\`..|
|
||||
00000080 20 20 5C 64 1B 0C 5C 67 - 5C 68 5C 69 5C 6A 5C 6B | \d..\g\h\i\j\k|
|
||||
00000090 5C 6C 5C 6D 0A 5C 6F 5C - 70 20 5C 71 0D 5C 73 09 |\l\m.\o\p \q.\s.|
|
||||
000000A0 0B 5C 77 5C 79 5C 7A 5C - 7B 5C 7C 5C 7D 5C 7E 20 |.\w\y\z\{\|\}\~ |
|
||||
000000B0 E2 82 AC 64 20 EF BF BD - 20 12 33 20 78 20 53 20 |...d ... .3 x S |
|
||||
000000C0 53 34 0A - |S4.|
|
||||
---
|
||||
name: dollar-quoted-strings
|
||||
description:
|
||||
Check backslash expansion by $'…' strings
|
||||
stdin:
|
||||
printf '%s\n' $'\ \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/ \1\2\3\4\5\6' \
|
||||
$'a\0b' $'a\01b' $'\7\8\9\:\;\<\=\>\?\@\A\B\C\D\E\F\G\H\I' \
|
||||
$'\J\K\L\M\N\O\P\Q\R\S\T\U1\V\W\X\Y\Z\[\\\]\^\_\`\a\b\d\e' \
|
||||
$'\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u1\v\w\x1\y\z\{\|\}\~ $x' \
|
||||
$'\u20acd' $'\U20acd' $'\x123' $'fn\x0rd' $'\0234' $'\234' \
|
||||
$'\2345' $'\ca' $'\c!' $'\c?' $'\c€' $'a\
|
||||
b' | {
|
||||
typeset -Uui16 -Z11 pos=0
|
||||
typeset -Uui16 -Z5 hv
|
||||
typeset -i1 wc=0x0A
|
||||
dasc=
|
||||
nl=${wc#1#}
|
||||
while IFS= read -r line; do
|
||||
line=$line$nl
|
||||
while [[ -n $line ]]; do
|
||||
hv=1#${line::1}
|
||||
if (( (pos & 15) == 0 )); then
|
||||
(( pos )) && print "$dasc|"
|
||||
print -n "${pos#16#} "
|
||||
dasc=' |'
|
||||
fi
|
||||
print -n "${hv#16#} "
|
||||
if (( (hv < 32) || (hv > 126) )); then
|
||||
dasc=$dasc.
|
||||
else
|
||||
dasc=$dasc${line::1}
|
||||
fi
|
||||
(( (pos++ & 15) == 7 )) && print -n -- '- '
|
||||
line=${line:1}
|
||||
done
|
||||
done
|
||||
if (( (pos & 15) != 1 )); then
|
||||
while (( pos & 15 )); do
|
||||
print -n ' '
|
||||
(( (pos++ & 15) == 7 )) && print -n -- '- '
|
||||
done
|
||||
print "$dasc|"
|
||||
fi
|
||||
}
|
||||
expected-stdout:
|
||||
00000000 20 21 22 23 24 25 26 27 - 28 29 2A 2B 2C 2D 2E 2F | !"#$%&'()*+,-./|
|
||||
00000010 20 01 02 03 04 05 06 0A - 61 0A 61 01 62 0A 07 38 | .......a.a.b..8|
|
||||
00000020 39 3A 3B 3C 3D 3E 3F 40 - 41 42 43 44 1B 46 47 48 |9:;<=>?@ABCD.FGH|
|
||||
00000030 49 0A 4A 4B 4C 4D 4E 4F - 50 51 52 53 54 01 56 57 |I.JKLMNOPQRST.VW|
|
||||
00000040 58 59 5A 5B 5C 5D 5E 5F - 60 07 08 64 1B 0A 0C 67 |XYZ[\]^_`..d...g|
|
||||
00000050 68 69 6A 6B 6C 6D 0A 6F - 70 71 0D 73 09 01 0B 77 |hijklm.opq.s...w|
|
||||
00000060 01 79 7A 7B 7C 7D 7E 20 - 24 78 0A E2 82 AC 64 0A |.yz{|}~ $x....d.|
|
||||
00000070 EF BF BD 0A C4 A3 0A 66 - 6E 0A 13 34 0A 9C 0A 9C |.......fn..4....|
|
||||
00000080 35 0A 01 0A 01 0A 7F 0A - 02 82 AC 0A 61 0A 62 0A |5...........a.b.|
|
||||
---
|
||||
name: dot-needs-argument
|
||||
description:
|
||||
check Debian #415167 solution: '.' without arguments should fail
|
||||
|
6
edit.c
6
edit.c
@ -25,7 +25,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.175 2009/08/28 20:30:54 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.176 2009/09/19 21:54:43 tg Exp $");
|
||||
|
||||
/* tty driver characters we are interested in */
|
||||
typedef struct {
|
||||
@ -964,10 +964,6 @@ utf_wctomb(char *dst, unsigned int wc)
|
||||
static Area aedit;
|
||||
#define AEDIT &aedit /* area for kill ring and macro defns */
|
||||
|
||||
#undef CTRL
|
||||
#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
|
||||
#define UNCTRL(x) ((x) ^ 0x40) /* ASCII */
|
||||
|
||||
/* values returned by keyboard functions */
|
||||
#define KSTD 0
|
||||
#define KEOL 1 /* ^M, ^J */
|
||||
|
25
funcs.c
25
funcs.c
@ -25,7 +25,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.132 2009/09/19 19:08:46 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.133 2009/09/19 21:54:44 tg Exp $");
|
||||
|
||||
#if HAVE_KILLPG
|
||||
/*
|
||||
@ -495,6 +495,10 @@ c_pwd(const char **wp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const char *s_ptr;
|
||||
static int s_get(void);
|
||||
static void s_put(int);
|
||||
|
||||
int
|
||||
c_print(const char **wp)
|
||||
{
|
||||
@ -604,7 +608,10 @@ c_print(const char **wp)
|
||||
while ((c = *s++) != '\0') {
|
||||
Xcheck(xs, xp);
|
||||
if ((flags & PO_EXPAND) && c == '\\') {
|
||||
if ((c = unbksl(&s, false)) == -1) {
|
||||
s_ptr = s;
|
||||
c = unbksl(false, s_get, s_put);
|
||||
s = s_ptr;
|
||||
if (c == -1) {
|
||||
/* rejected by generic function */
|
||||
switch ((c = *s++)) {
|
||||
case 'c':
|
||||
@ -618,7 +625,7 @@ c_print(const char **wp)
|
||||
default:
|
||||
Xput(xs, xp, '\\');
|
||||
}
|
||||
} else if (c > 0xFF) {
|
||||
} else if ((unsigned int)c > 0xFF) {
|
||||
/* generic function returned Unicode */
|
||||
char ts[4];
|
||||
|
||||
@ -678,6 +685,18 @@ c_print(const char **wp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
s_get(void)
|
||||
{
|
||||
return (*s_ptr++);
|
||||
}
|
||||
|
||||
static void
|
||||
s_put(int c __unused)
|
||||
{
|
||||
--s_ptr;
|
||||
}
|
||||
|
||||
int
|
||||
c_whence(const char **wp)
|
||||
{
|
||||
|
79
lex.c
79
lex.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.93 2009/08/28 22:39:09 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.94 2009/09/19 21:54:45 tg Exp $");
|
||||
|
||||
/*
|
||||
* states while lexing word
|
||||
@ -43,6 +43,7 @@ __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.93 2009/08/28 22:39:09 tg Exp $");
|
||||
#define SLETARRAY 13 /* inside =( ), just copy */
|
||||
#define SADELIM 14 /* like SBASE, looking for delimiter */
|
||||
#define SHERESTRING 15 /* parsing <<< string */
|
||||
#define SEQUOTE 16 /* inside $'' */
|
||||
|
||||
/* Structure to keep track of the lexing state and the various pieces of info
|
||||
* needed for each particular state. */
|
||||
@ -94,6 +95,12 @@ struct lex_state {
|
||||
#define ls_sadelim ls_info.u_sadelim
|
||||
} u_sadelim;
|
||||
|
||||
/* $'...' */
|
||||
struct sequote_info {
|
||||
bool got_NUL; /* ignore rest of string */
|
||||
#define ls_sequote ls_info.u_sequote
|
||||
} u_sequote;
|
||||
|
||||
Lex_state *base; /* used to point to next state block */
|
||||
} ls_info;
|
||||
};
|
||||
@ -107,6 +114,8 @@ static void readhere(struct ioword *);
|
||||
static int getsc__(void);
|
||||
static void getsc_line(Source *);
|
||||
static int getsc_bn(void);
|
||||
static int s_get(void);
|
||||
static void s_put(int);
|
||||
static char *get_brace_var(XString *, char *);
|
||||
static int arraysub(char **);
|
||||
static const char *ungetsc(int);
|
||||
@ -154,11 +163,10 @@ yylex(int cf)
|
||||
{
|
||||
Lex_state states[STATE_BSIZE], *statep, *s2, *base;
|
||||
State_info state_info;
|
||||
int c, state;
|
||||
int c, c2, state;
|
||||
XString ws; /* expandable output word */
|
||||
char *wp; /* output word pointer */
|
||||
char *sp, *dp;
|
||||
int c2;
|
||||
|
||||
Again:
|
||||
states[0].ls_state = -1;
|
||||
@ -427,6 +435,12 @@ yylex(int cf)
|
||||
*wp++ = '\0';
|
||||
*wp++ = CSUBST;
|
||||
*wp++ = 'X';
|
||||
} else if (c == '\'') {
|
||||
*wp++ = OQUOTE;
|
||||
ignore_backslash_newline++;
|
||||
PUSH_STATE(SEQUOTE);
|
||||
statep->ls_sequote.got_NUL = false;
|
||||
break;
|
||||
} else {
|
||||
*wp++ = CHAR, *wp++ = '$';
|
||||
ungetsc(c);
|
||||
@ -484,6 +498,33 @@ yylex(int cf)
|
||||
}
|
||||
break;
|
||||
|
||||
case SEQUOTE:
|
||||
if (c == '\'') {
|
||||
POP_STATE();
|
||||
*wp++ = CQUOTE;
|
||||
ignore_backslash_newline--;
|
||||
} else if (c == '\\') {
|
||||
if ((c2 = unbksl(true, s_get, s_put)) == -1)
|
||||
c2 = s_get();
|
||||
if (c2 == 0 || c2 == 0x100)
|
||||
statep->ls_sequote.got_NUL = true;
|
||||
if (!statep->ls_sequote.got_NUL) {
|
||||
char ts[4];
|
||||
|
||||
if ((unsigned int)c2 < 0x100)
|
||||
*wp++ = QCHAR, *wp++ = c2;
|
||||
else {
|
||||
c = utf_wctomb(ts, c2 - 0x100);
|
||||
ts[c] = 0;
|
||||
for (c = 0; ts[c]; ++c)
|
||||
*wp++ = QCHAR, \
|
||||
*wp++ = ts[c];
|
||||
}
|
||||
}
|
||||
} else if (!statep->ls_sequote.got_NUL)
|
||||
*wp++ = QCHAR, *wp++ = c;
|
||||
break;
|
||||
|
||||
case SSQUOTE:
|
||||
if (c == '\'') {
|
||||
POP_STATE();
|
||||
@ -690,8 +731,17 @@ yylex(int cf)
|
||||
}
|
||||
/* invoke quoting mode */
|
||||
Xstring(ws, wp)[0] = QCHAR;
|
||||
} else if (c == '$') {
|
||||
if ((c2 = getsc()) == '\'') {
|
||||
PUSH_STATE(SEQUOTE);
|
||||
statep->ls_sequote.got_NUL = false;
|
||||
goto sherestring_quoted;
|
||||
}
|
||||
ungetsc(c2);
|
||||
goto sherestring_regular;
|
||||
} else if (c == '\'') {
|
||||
PUSH_STATE(SSQUOTE);
|
||||
sherestring_quoted:
|
||||
*wp++ = OQUOTE;
|
||||
ignore_backslash_newline++;
|
||||
/* invoke quoting mode */
|
||||
@ -701,6 +751,7 @@ yylex(int cf)
|
||||
*wp++ = OQUOTE;
|
||||
/* just don't IFS split; no quoting mode */
|
||||
} else {
|
||||
sherestring_regular:
|
||||
*wp++ = CHAR;
|
||||
*wp++ = c;
|
||||
}
|
||||
@ -721,14 +772,24 @@ yylex(int cf)
|
||||
*wp++ = QCHAR;
|
||||
*wp++ = c;
|
||||
}
|
||||
} else if (c == '$') {
|
||||
if ((c2 = getsc()) == '\'') {
|
||||
PUSH_STATE(SEQUOTE);
|
||||
statep->ls_sequote.got_NUL = false;
|
||||
goto sheredelim_quoted;
|
||||
}
|
||||
ungetsc(c2);
|
||||
goto sheredelim_regular;
|
||||
} else if (c == '\'') {
|
||||
PUSH_STATE(SSQUOTE);
|
||||
sheredelim_quoted:
|
||||
*wp++ = OQUOTE;
|
||||
ignore_backslash_newline++;
|
||||
} else if (c == '"') {
|
||||
state = statep->ls_state = SHEREDQUOTE;
|
||||
*wp++ = OQUOTE;
|
||||
} else {
|
||||
sheredelim_regular:
|
||||
*wp++ = CHAR;
|
||||
*wp++ = c;
|
||||
}
|
||||
@ -1604,3 +1665,15 @@ pop_state_(State_info *si, Lex_state *old_end)
|
||||
|
||||
return (si->base + STATE_BSIZE - 1);
|
||||
}
|
||||
|
||||
static int
|
||||
s_get(void)
|
||||
{
|
||||
return (getsc());
|
||||
}
|
||||
|
||||
static void
|
||||
s_put(int c)
|
||||
{
|
||||
ungetsc(c);
|
||||
}
|
||||
|
69
misc.c
69
misc.c
@ -29,7 +29,7 @@
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.120 2009/09/19 19:08:47 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.121 2009/09/19 21:54:45 tg Exp $");
|
||||
|
||||
#undef USE_CHVT
|
||||
/* XXX conditions correct? */
|
||||
@ -1449,19 +1449,20 @@ getrusage(int what, struct rusage *ru)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* process the string at *sp for backslash escapes,
|
||||
* assuming (*sp)[-1] was the backslash; return the
|
||||
* character ([0;0xFF]), Unicode (wc+0x100), or -1
|
||||
* if none found; *sp afterwards points to the first
|
||||
* unprocessed character (unchanged if rv=-1)
|
||||
* process the string available via fg (get a char)
|
||||
* and fp (put back a char) for backslash escapes,
|
||||
* assuming the first call to *fg gets the char di-
|
||||
* rectly after the backslash; return the character
|
||||
* (0..0xFF), Unicode (wc + 0x100), or -1 if no known
|
||||
* escape sequence was found
|
||||
*/
|
||||
int
|
||||
unbksl(const char **sp, bool cstyle)
|
||||
unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
|
||||
{
|
||||
int wc, i;
|
||||
const char *cp = (*sp);
|
||||
int wc, i, c, fc;
|
||||
|
||||
switch (*cp++) {
|
||||
fc = (*fg)();
|
||||
switch (fc) {
|
||||
case 'a':
|
||||
/*
|
||||
* according to the comments in pdksh, \007 seems
|
||||
@ -1474,6 +1475,16 @@ unbksl(const char **sp, bool cstyle)
|
||||
case 'b':
|
||||
wc = '\b';
|
||||
break;
|
||||
case 'c':
|
||||
if (!cstyle)
|
||||
goto unknown_escape;
|
||||
c = (*fg)();
|
||||
wc = CTRL(c);
|
||||
break;
|
||||
case 'E':
|
||||
case 'e':
|
||||
wc = 033;
|
||||
break;
|
||||
case 'f':
|
||||
wc = '\f';
|
||||
break;
|
||||
@ -1497,14 +1508,12 @@ unbksl(const char **sp, bool cstyle)
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (!cstyle)
|
||||
return (-1);
|
||||
goto unknown_escape;
|
||||
/* FALLTHROUGH */
|
||||
case '0':
|
||||
if (cstyle)
|
||||
--cp;
|
||||
(*fp)(fc);
|
||||
/*
|
||||
* look for an octal number with up to three
|
||||
* digits, not counting the leading zero;
|
||||
@ -1512,8 +1521,13 @@ unbksl(const char **sp, bool cstyle)
|
||||
*/
|
||||
wc = 0;
|
||||
i = 3;
|
||||
while (i-- && *cp >= '0' && *cp <= '7')
|
||||
wc = (wc << 3) + (*cp++ - '0');
|
||||
while (i--)
|
||||
if ((c = (*fg)()) >= '0' && c <= '7')
|
||||
wc = (wc << 3) + (c - '0');
|
||||
else {
|
||||
(*fp)(c);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'U':
|
||||
i = 8;
|
||||
@ -1535,28 +1549,35 @@ unbksl(const char **sp, bool cstyle)
|
||||
wc = 0;
|
||||
while (i--) {
|
||||
wc <<= 4;
|
||||
if (*cp >= '0' && *cp <= '9')
|
||||
wc += *cp++ - '0';
|
||||
else if (*cp >= 'A' && *cp <= 'F')
|
||||
wc += *cp++ - 'A' + 10;
|
||||
else if (*cp >= 'a' && *cp <= 'f')
|
||||
wc += *cp++ - 'a' + 10;
|
||||
if ((c = (*fg)()) >= '0' && c <= '9')
|
||||
wc += c - '0';
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
wc += c - 'A' + 10;
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
wc += c - 'a' + 10;
|
||||
else {
|
||||
wc >>= 4;
|
||||
(*fp)(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cstyle || **sp != 'x')
|
||||
if (cstyle || fc != 'x')
|
||||
/* Unicode marker */
|
||||
wc += 0x100;
|
||||
break;
|
||||
case '\'':
|
||||
if (!cstyle)
|
||||
goto unknown_escape;
|
||||
wc = '\'';
|
||||
break;
|
||||
case '\\':
|
||||
wc = '\\';
|
||||
break;
|
||||
default:
|
||||
unknown_escape:
|
||||
(*fp)(fc);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
(*sp) = cp;
|
||||
return (wc);
|
||||
}
|
||||
|
101
mksh.1
101
mksh.1
@ -1,4 +1,4 @@
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.187 2009/09/19 19:08:47 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.188 2009/09/19 21:54:45 tg Exp $
|
||||
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
|
||||
.\"-
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
@ -877,6 +877,12 @@ the
|
||||
and the newline are stripped; otherwise, both the
|
||||
.Ql \e
|
||||
and the character following are unchanged.
|
||||
.Pp
|
||||
If a single-quoted string is preceded by an unquoted
|
||||
.Ql $ ,
|
||||
C style backslash expansion (see below) is applied (even single quote
|
||||
characters inside can be escaped and do not terminate the string then);
|
||||
the expanded result is treated as any other single-quoted string.
|
||||
.Ss Backslash expansion
|
||||
In places where backslashes are expanded, certain C and
|
||||
.At
|
||||
@ -884,11 +890,6 @@ In places where backslashes are expanded, certain C and
|
||||
or GNU
|
||||
.Nm bash
|
||||
style escapes are translated.
|
||||
Explicitly excluded are
|
||||
.Ql \e" ,
|
||||
.Ql \e' ,
|
||||
and
|
||||
.Ql \e? .
|
||||
These include
|
||||
.Ql \ea ,
|
||||
.Ql \eb ,
|
||||
@ -898,16 +899,62 @@ These include
|
||||
.Ql \et ,
|
||||
.Ql \eU######## ,
|
||||
.Ql \eu#### ,
|
||||
.Ql \ev ,
|
||||
.Ql \ex## ,
|
||||
and
|
||||
.Ql \e0### ;
|
||||
.Ql #
|
||||
is, in the case of \e0###, an octal, or, in the case of \ex##,
|
||||
\eu#### or \eU########, a hexadecimal digit, of which there may
|
||||
be none up to two (x), three (0), four (u), or eight (U).
|
||||
The \ex## and \e0### escapes translate to raw 8-bit octets;
|
||||
the \eu#### and \eU######## escapes translate a Unicode codepoint to UTF-8.
|
||||
.Ql \ev .
|
||||
For
|
||||
.Ql \eU########
|
||||
and
|
||||
.Ql \eu#### ,
|
||||
.Dq #
|
||||
means a hexadecimal digit, of thich there may be none up to four or eight;
|
||||
these escapes translate a Unicode codepoint to UTF-8.
|
||||
Furthermore,
|
||||
.Ql \eE
|
||||
and
|
||||
.Ql \ee
|
||||
expand to the escape character.
|
||||
.Pp
|
||||
In the
|
||||
.Ic print
|
||||
builtin mode,
|
||||
.Ql \e" ,
|
||||
.Ql \e\*(aq ,
|
||||
and
|
||||
.Ql \e?
|
||||
are explicitly excluded;
|
||||
octal sequences must have the none up to three octal digits
|
||||
.Dq #
|
||||
prefixed with the digit zero
|
||||
.Pq Ql \e0### ;
|
||||
hexadecimal sequences
|
||||
.Ql \ex##
|
||||
are limited to none up to two hexadecimal digits
|
||||
.Dq # ;
|
||||
both octal and hexadecimal sequences convert to raw octets;
|
||||
.Ql \e# ,
|
||||
where # is none of the above, translates to \e# (backslashes are retained).
|
||||
.Pp
|
||||
Backslash expansion in the C style mode slightly differs: octal sequences
|
||||
.Ql \e###
|
||||
must have no digit zero prefixing the one up to three octal digits
|
||||
.Dq #
|
||||
and yield raw octets; hexadecimal sequences
|
||||
.Ql \ex#*
|
||||
greedily eat up as many hexadecimal digits
|
||||
.Dq #
|
||||
as they can and terminate with the first non-hexadecimal digit;
|
||||
these translate a Unicode codepoint to UTF-8.
|
||||
The sequence
|
||||
.Ql \ec# ,
|
||||
where
|
||||
.Dq #
|
||||
is any octet, translates to Ctrl-# (which basically means,
|
||||
.Ql \ec\*(TI
|
||||
becomes DEL, everything else is bitwise ANDed with 0x1F).
|
||||
Finally,
|
||||
.Ql \e# ,
|
||||
where # is none of the above, translates to # (has the backslash trimmed),
|
||||
even if it is a newline.
|
||||
.Ss Aliases
|
||||
There are two types of aliases: normal command aliases and tracked aliases.
|
||||
Command aliases are normally used as a short hand for a long or often used
|
||||
@ -1431,7 +1478,7 @@ Note that
|
||||
may need to be escaped as an extended globbing pattern
|
||||
.Pq @(...) ,
|
||||
with single quotes
|
||||
.Pq \&'...\&'
|
||||
.Pq \&\*(aq...\&\*(aq
|
||||
or double quotes
|
||||
.Pq \&"...\&" .
|
||||
.Pp
|
||||
@ -1706,7 +1753,7 @@ is (so they know how far it is to the edge of the screen), escape codes in
|
||||
the prompt tend to mess things up.
|
||||
You can tell the shell not to count certain
|
||||
sequences (such as escape codes) by prefixing your prompt with a
|
||||
character (such as control-A) followed by a carriage return and then delimiting
|
||||
character (such as Ctrl-A) followed by a carriage return and then delimiting
|
||||
the escape codes with this character.
|
||||
Any occurences of that character in the prompt are not printed.
|
||||
By the way, don't blame me for
|
||||
@ -2773,12 +2820,12 @@ two prefices and the control character is ignored, any
|
||||
other trailing character will be processed afterwards.
|
||||
.Pp
|
||||
Control characters may be written using caret notation
|
||||
i.e. \*(haX represents Control-X.
|
||||
i.e. \*(haX represents Ctrl-X.
|
||||
Note that although only two prefix characters (usually ESC and \*(haX)
|
||||
are supported, some multi-character sequences can be supported.
|
||||
.Pp
|
||||
The following default bindings show how the arrow keys, the home, end and
|
||||
delete key on a BSD wsvt25, xterm-xfree86 or GNU screen terminal are bound
|
||||
delete key on a BSD wsvt25, xterm\-xfree86 or GNU screen terminal are bound
|
||||
(of course some escape sequences won't work out quite this nicely):
|
||||
.Bd -literal -offset indent
|
||||
bind \*(aq\*(haX\*(aq=prefix\-2
|
||||
@ -3306,18 +3353,14 @@ The
|
||||
.Fl n
|
||||
option suppresses the newline.
|
||||
By default, certain C escapes are translated.
|
||||
These include at least these mentioned in
|
||||
These include these mentioned in
|
||||
.Sx Backslash expansion
|
||||
above, as well as
|
||||
.Ql \ec ,
|
||||
which is equivalent to using the
|
||||
.Fl n
|
||||
option.
|
||||
Contrary to C escapes, the backslash is retained if followed by an
|
||||
unsupported escape character; octal sequences must be preceded by a
|
||||
.Sq 0 .
|
||||
.Ql \e
|
||||
expansion may be inhibited with the
|
||||
Backslash expansion may be inhibited with the
|
||||
.Fl r
|
||||
option.
|
||||
The
|
||||
@ -5774,6 +5817,14 @@ The developer of mksh recognises the efforts of the pdksh authors,
|
||||
who had dedicated their work into Public Domain, our users, and
|
||||
all contributors, such as the Debian and OpenBSD projects.
|
||||
See the documentation, CVS, and web site for details.
|
||||
.Sh CAVEATS
|
||||
.Nm
|
||||
only supports the Unicode BMP (Basic Multilingual Plane).
|
||||
Pipelines are executed in subshells.
|
||||
It has a different scope model from
|
||||
.At
|
||||
.Nm ksh ,
|
||||
which leads to subtile differences in semantics for identical builtins.
|
||||
.Sh BUGS
|
||||
This document attempts to describe
|
||||
.Nm mksh\ R39+devel
|
||||
|
10
sh.h
10
sh.h
@ -134,9 +134,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.342 2009/09/19 19:08:48 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.343 2009/09/19 21:54:46 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R39 2009/09/07"
|
||||
#define MKSH_VERSION "R39 2009/09/19"
|
||||
|
||||
#ifndef MKSH_INCLUDES_ONLY
|
||||
|
||||
@ -1339,6 +1339,10 @@ typedef union {
|
||||
|
||||
#define HERES 10 /* max << in line */
|
||||
|
||||
#undef CTRL
|
||||
#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
|
||||
#define UNCTRL(x) ((x) ^ 0x40) /* ASCII */
|
||||
|
||||
EXTERN Source *source; /* yyparse/yylex source */
|
||||
EXTERN YYSTYPE yylval; /* result from yylex */
|
||||
EXTERN struct ioword *heres [HERES], **herep;
|
||||
@ -1587,7 +1591,7 @@ void set_current_wd(char *);
|
||||
char *strdup_(const char *, Area *);
|
||||
char *strndup_(const char *, size_t, Area *);
|
||||
#endif
|
||||
int unbksl(const char **, bool);
|
||||
int unbksl(bool, int (*)(void), void (*)(int));
|
||||
/* shf.c */
|
||||
struct shf *shf_open(const char *, int, int, int);
|
||||
struct shf *shf_fdopen(int, int, struct shf *);
|
||||
|
Loading…
Reference in New Issue
Block a user