implement VALSUBs
This commit is contained in:
parent
54a698d564
commit
1d0409d932
6
Build.sh
6
Build.sh
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.629 2013/05/02 20:21:36 tg Exp $'
|
||||
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.630 2013/05/02 21:59:44 tg Exp $'
|
||||
#-
|
||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011, 2012, 2013
|
||||
@ -1531,7 +1531,7 @@ else
|
||||
#define EXTERN
|
||||
#define MKSH_INCLUDES_ONLY
|
||||
#include "sh.h"
|
||||
__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.629 2013/05/02 20:21:36 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.630 2013/05/02 21:59:44 tg Exp $");
|
||||
int main(void) { printf("Hello, World!\n"); return (0); }
|
||||
EOF
|
||||
case $cm in
|
||||
@ -2046,7 +2046,7 @@ addsrcs USE_PRINTF_BUILTIN printf.c
|
||||
test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
|
||||
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
|
||||
test -n "$LDSTATIC" && add_cppflags -DMKSH_OPTSTATIC
|
||||
add_cppflags -DMKSH_BUILD_R=459
|
||||
add_cppflags -DMKSH_BUILD_R=461
|
||||
|
||||
$e $bi$me: Finished configuration testing, now producing output.$ao
|
||||
|
||||
|
4
Makefile
4
Makefile
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/Makefile,v 1.120 2013/04/27 18:50:21 tg Exp $
|
||||
# $MirOS: src/bin/mksh/Makefile,v 1.121 2013/05/02 21:59:45 tg Exp $
|
||||
#-
|
||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011, 2012, 2013
|
||||
@ -54,7 +54,7 @@ CPPFLAGS+= -DMKSH_ASSUME_UTF8 -DMKSH_DISABLE_DEPRECATED \
|
||||
-DHAVE_SETGROUPS=1 -DHAVE_STRERROR=0 -DHAVE_STRSIGNAL=0 \
|
||||
-DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \
|
||||
-DHAVE_SYS_ERRLIST_DECL=1 -DHAVE_SYS_SIGLIST_DECL=1 \
|
||||
-DHAVE_PERSISTENT_HISTORY=1 -DMKSH_BUILD_R=459
|
||||
-DHAVE_PERSISTENT_HISTORY=1 -DMKSH_BUILD_R=461
|
||||
CPPFLAGS+= -D${${PROG:L}_tf:C/(Mir${MAN:E}{0,1}){2}/4/:S/x/mksh_BUILD/:U}
|
||||
COPTS+= -std=c99 -Wall
|
||||
.endif
|
||||
|
63
check.t
63
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.611 2013/05/02 20:28:10 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.612 2013/05/02 21:59:45 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 $
|
||||
@ -29,7 +29,7 @@
|
||||
# http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R45 2013/04/27
|
||||
@(#)MIRBSD KSH R46 2013/05/02
|
||||
description:
|
||||
Check version of shell.
|
||||
stdin:
|
||||
@ -38,7 +38,7 @@ name: KSH_VERSION
|
||||
category: shell:legacy-no
|
||||
---
|
||||
expected-stdout:
|
||||
@(#)LEGACY KSH R45 2013/04/27
|
||||
@(#)LEGACY KSH R46 2013/05/02
|
||||
description:
|
||||
Check version of legacy shell.
|
||||
stdin:
|
||||
@ -8922,8 +8922,8 @@ stdin:
|
||||
EOFI
|
||||
#IORDWR_IODUP
|
||||
sh 1<>/dev/console 0<&1 2>&1
|
||||
#COMSUB_EXPRSUB
|
||||
echo $(true) $((1+ 2))
|
||||
#COMSUB_EXPRSUB_FUNSUB_VALSUB
|
||||
echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;}
|
||||
#QCHAR_OQUOTE_CQUOTE
|
||||
echo fo\ob\"a\`r\'b\$az
|
||||
echo "fo\ob\"a\`r\'b\$az"
|
||||
@ -9305,23 +9305,23 @@ expected-stdout:
|
||||
function reread_IORDWR_IODUP {
|
||||
x=$(( sh 1<>/dev/console <&1 2>&1 ) | tr u x )
|
||||
}
|
||||
inline_COMSUB_EXPRSUB() {
|
||||
echo $(true) $((1+ 2))
|
||||
inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() {
|
||||
echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;}
|
||||
}
|
||||
inline_COMSUB_EXPRSUB() {
|
||||
echo $(true ) $((1+ 2))
|
||||
inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() {
|
||||
echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;}
|
||||
}
|
||||
function comsub_COMSUB_EXPRSUB { x=$(
|
||||
echo $(true) $((1+ 2))
|
||||
function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$(
|
||||
echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;}
|
||||
); }
|
||||
function comsub_COMSUB_EXPRSUB {
|
||||
x=$(echo $(true ) $((1+ 2)) )
|
||||
function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB {
|
||||
x=$(echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} )
|
||||
}
|
||||
function reread_COMSUB_EXPRSUB { x=$((
|
||||
echo $(true) $((1+ 2))
|
||||
function reread_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$((
|
||||
echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;}
|
||||
)|tr u x); }
|
||||
function reread_COMSUB_EXPRSUB {
|
||||
x=$(( echo $(true ) $((1+ 2)) ) | tr u x )
|
||||
function reread_COMSUB_EXPRSUB_FUNSUB_VALSUB {
|
||||
x=$(( echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} ) | tr u x )
|
||||
}
|
||||
inline_QCHAR_OQUOTE_CQUOTE() {
|
||||
echo fo\ob\"a\`r\'b\$az
|
||||
@ -9907,6 +9907,35 @@ expected-stdout:
|
||||
2:ya x2,1,0.
|
||||
3:ya,1,3.
|
||||
---
|
||||
name: valsub-1
|
||||
description:
|
||||
Check that "value substitutions" work as advertised
|
||||
stdin:
|
||||
x=1
|
||||
y=2
|
||||
z=3
|
||||
REPLY=4
|
||||
echo "before: x<$x> y<$y> z<$z> R<$REPLY>"
|
||||
x=${|
|
||||
local y
|
||||
echo "begin: x<$x> y<$y> z<$z> R<$REPLY>"
|
||||
x=5
|
||||
y=6
|
||||
z=7
|
||||
REPLY=8
|
||||
echo "end: x<$x> y<$y> z<$z> R<$REPLY>"
|
||||
}
|
||||
echo "after: x<$x> y<$y> z<$z> R<$REPLY>"
|
||||
# ensure trailing newlines are kept
|
||||
t=${|REPLY=$'foo\n\n';}
|
||||
typeset -p t
|
||||
expected-stdout:
|
||||
before: x<1> y<2> z<3> R<4>
|
||||
begin: x<1> y<> z<3> R<>
|
||||
end: x<5> y<6> z<7> R<8>
|
||||
after: x<8> y<2> z<7> R<4>
|
||||
typeset t=$'foo\n\n'
|
||||
---
|
||||
name: test-stnze-1
|
||||
description:
|
||||
Check that the short form [ $x ] works
|
||||
|
23
dot.mkshrc
23
dot.mkshrc
@ -1,5 +1,5 @@
|
||||
# $Id$
|
||||
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.81 2013/05/02 21:46:29 tg Exp $
|
||||
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.82 2013/05/02 21:59:48 tg Exp $
|
||||
#-
|
||||
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011, 2012, 2013
|
||||
@ -31,19 +31,20 @@ esac
|
||||
PS1='#'; (( USER_ID )) && PS1='$'; [[ ${HOSTNAME:=$(ulimit -c 0; hostname -s \
|
||||
2>/dev/null)} = *([ ]|localhost) ]] && HOSTNAME=$(ulimit -c 0; hostname \
|
||||
2>/dev/null); : ${EDITOR:=/bin/ed} ${HOSTNAME:=nil} ${TERM:=vt100}
|
||||
function precmd {
|
||||
: ${MKSH:=$(whence -p mksh)}; PS4='[$EPOCHREALTIME] '; PS1=$'\001\r''${|
|
||||
local e=$?
|
||||
|
||||
(( e )) && print -n "$e|"
|
||||
# precmd is required to retain the errorlevel when ${ …;} is used
|
||||
(( e )) && REPLY+="$e|"
|
||||
REPLY+=${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \?)}
|
||||
REPLY+=@${HOSTNAME%%.*}:
|
||||
|
||||
local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~}
|
||||
local m=${%d} n p=...; (( m > 0 )) || m=${#d}
|
||||
(( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || p=
|
||||
REPLY+=$p$d
|
||||
|
||||
return $e
|
||||
}
|
||||
PS1=$'\001\r''${ precmd;}${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \?
|
||||
)}@${HOSTNAME%%.*}:${ local e=$? d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || \
|
||||
d=${d/#$p/~}; local m=${%d} n p=...; (( m > 0 )) || m=${#d}
|
||||
(( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || \
|
||||
p=; print -nr -- "$p$d"; return $e;} '"$PS1 "; PS4='[$EPOCHREALTIME] '
|
||||
: ${MKSH:=$(whence -p mksh)}; export EDITOR HOSTNAME MKSH TERM USER
|
||||
} '"$PS1 "; export EDITOR HOSTNAME MKSH TERM USER
|
||||
alias ls=ls
|
||||
unalias ls
|
||||
alias l='ls -F'
|
||||
|
36
eval.c
36
eval.c
@ -23,7 +23,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.138 2013/03/29 17:33:06 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.139 2013/05/02 21:59:49 tg Exp $");
|
||||
|
||||
/*
|
||||
* string expansion
|
||||
@ -66,6 +66,7 @@ typedef struct {
|
||||
static int varsub(Expand *, const char *, const char *, int *, int *);
|
||||
static int comsub(Expand *, const char *, int);
|
||||
static void funsub(struct op *);
|
||||
static char *valsub(struct op *, Area *);
|
||||
static char *trimsub(char *, char *, int);
|
||||
static void glob(char *, XPtrV *, bool);
|
||||
static void globit(XString *, char **, char *, XPtrV *, int);
|
||||
@ -298,27 +299,26 @@ expand(
|
||||
continue;
|
||||
case COMSUB:
|
||||
case FUNSUB:
|
||||
case VALSUB:
|
||||
tilde_ok = 0;
|
||||
if (f & DONTRUNCOMMAND) {
|
||||
word = IFS_WORD;
|
||||
*dp++ = '$';
|
||||
if (c == FUNSUB) {
|
||||
*dp++ = '{';
|
||||
*dp++ = ' ';
|
||||
} else
|
||||
*dp++ = '(';
|
||||
*dp++ = c == COMSUB ? '(' : '{';
|
||||
if (c != COMSUB)
|
||||
*dp++ = c == FUNSUB ? ' ' : '|';
|
||||
while (*sp != '\0') {
|
||||
Xcheck(ds, dp);
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
if (c == FUNSUB) {
|
||||
if (c != COMSUB) {
|
||||
*dp++ = ';';
|
||||
*dp++ = '}';
|
||||
} else
|
||||
*dp++ = ')';
|
||||
} else {
|
||||
type = comsub(&x, sp, c);
|
||||
if (type == XCOM && (f&DOBLANK))
|
||||
if (type != XBASE && (f & DOBLANK))
|
||||
doblank++;
|
||||
sp = strnul(sp) + 1;
|
||||
newlines = 0;
|
||||
@ -1366,6 +1366,10 @@ comsub(Expand *xp, const char *cp, int fn MKSH_A_UNUSED)
|
||||
/* rewind the tempfile and restore regular stdout */
|
||||
lseek(shf_fileno(shf), (off_t)0, SEEK_SET);
|
||||
restfd(1, ofd1);
|
||||
} else if (fn == VALSUB) {
|
||||
xp->str = valsub(t, ATEMP);
|
||||
subst_exstat = exstat & 0xFF;
|
||||
return (XSUB);
|
||||
} else {
|
||||
int ofd1, pv[2];
|
||||
|
||||
@ -1832,3 +1836,19 @@ funsub(struct op *t)
|
||||
execute(t, XXCOM | XERROK, NULL);
|
||||
popblock();
|
||||
}
|
||||
|
||||
static char *
|
||||
valsub(struct op *t, Area *ap)
|
||||
{
|
||||
char *cp;
|
||||
struct tbl *vp;
|
||||
|
||||
newblock();
|
||||
vp = local("REPLY", false);
|
||||
e->type = E_FUNC;
|
||||
if (!kshsetjmp(e->jbuf))
|
||||
execute(t, XXCOM | XERROK, NULL);
|
||||
strdupx(cp, str_val(vp), ap);
|
||||
popblock();
|
||||
return (cp);
|
||||
}
|
||||
|
12
lex.c
12
lex.c
@ -23,7 +23,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.184 2013/03/29 17:33:55 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.185 2013/05/02 21:59:49 tg Exp $");
|
||||
|
||||
/*
|
||||
* states while lexing word
|
||||
@ -421,8 +421,14 @@ yylex(int cf)
|
||||
wp += cz;
|
||||
}
|
||||
} else if (c == '{') /*}*/ {
|
||||
c = getsc();
|
||||
if (ctype(c, C_IFSWS)) {
|
||||
if ((c = getsc()) == '|') {
|
||||
/*
|
||||
* non-subenvironment
|
||||
* value substitution
|
||||
*/
|
||||
c = VALSUB;
|
||||
goto subst_command2;
|
||||
} else if (ctype(c, C_IFSWS)) {
|
||||
/*
|
||||
* non-subenvironment
|
||||
* "command" substitution
|
||||
|
11
mksh.1
11
mksh.1
@ -1,4 +1,4 @@
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.314 2013/05/02 20:28:13 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.315 2013/05/02 21:59:50 tg Exp $
|
||||
.\" $OpenBSD: ksh.1,v 1.146 2013/03/18 11:10:52 mpi Exp $
|
||||
.\"-
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
@ -1182,6 +1182,15 @@ work, and in that
|
||||
.Ic exit
|
||||
terminates the parent shell.
|
||||
.Pp
|
||||
Another variant of substitution are the valsubs (value substitutions)
|
||||
.Pf ${\*(Ba\& Ns Ar command Ns \&;}
|
||||
which are also executed in the current environment, like funsubs, but
|
||||
share their I/O with the parent; instead, they evaluate to whatever
|
||||
the, initially empty, expression-local variable
|
||||
.Ev REPLY
|
||||
is set to within the
|
||||
.Ar command Ns No s .
|
||||
.Pp
|
||||
If a substitution appears outside of double quotes, the results of the
|
||||
substitution are generally subject to word or field splitting according to
|
||||
the current value of the
|
||||
|
7
sh.h
7
sh.h
@ -164,9 +164,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.653 2013/04/27 19:16:27 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.654 2013/05/02 21:59:52 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R45 2013/04/27"
|
||||
#define MKSH_VERSION "R46 2013/05/02"
|
||||
|
||||
/* arithmetic types: C implementation */
|
||||
#if !HAVE_CAN_INTTYPES
|
||||
@ -520,7 +520,7 @@ char *ucstrstr(char *, const char *);
|
||||
#define mkssert(e) do { } while (/* CONSTCOND */ 0)
|
||||
#endif
|
||||
|
||||
#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 459)
|
||||
#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 461)
|
||||
#error Must run Build.sh to compile this.
|
||||
int
|
||||
im_sorry_dave(void)
|
||||
@ -1327,6 +1327,7 @@ struct op {
|
||||
#define CPAT 11 /* close pattern: ) */
|
||||
#define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */
|
||||
#define FUNSUB 14 /* ${ foo;} substitution (NUL terminated) */
|
||||
#define VALSUB 15 /* ${|foo;} substitution (NUL terminated) */
|
||||
|
||||
/*
|
||||
* IO redirection
|
||||
|
4
syn.c
4
syn.c
@ -23,7 +23,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.90 2013/04/26 21:22:50 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.91 2013/05/02 21:59:53 tg Exp $");
|
||||
|
||||
struct nesting_state {
|
||||
int start_token; /* token than began nesting (eg, FOR) */
|
||||
@ -1129,7 +1129,7 @@ yyrecursive(int subtype MKSH_A_UNUSED)
|
||||
struct yyrecursive_state *ys;
|
||||
int stok, etok;
|
||||
|
||||
if (subtype == FUNSUB) {
|
||||
if (subtype != COMSUB) {
|
||||
stok = '{';
|
||||
etok = '}';
|
||||
} else {
|
||||
|
17
tree.c
17
tree.c
@ -2,7 +2,7 @@
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
* 2011, 2012
|
||||
* 2011, 2012, 2013
|
||||
* Thorsten Glaser <tg@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.68 2013/03/24 00:56:27 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.69 2013/05/02 21:59:54 tg Exp $");
|
||||
|
||||
#define INDENT 8
|
||||
|
||||
@ -349,7 +349,14 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
|
||||
shf_puts(cs, shf);
|
||||
break;
|
||||
case FUNSUB:
|
||||
shf_puts("${ ", shf);
|
||||
c = ' ';
|
||||
if (0)
|
||||
/* FALLTHROUGH */
|
||||
case VALSUB:
|
||||
c = '|';
|
||||
shf_putc('$', shf);
|
||||
shf_putc('{', shf);
|
||||
shf_putc(c, shf);
|
||||
cs = ";}";
|
||||
goto pSUB;
|
||||
case EXPRSUB:
|
||||
@ -592,6 +599,7 @@ wdscan(const char *wp, int c)
|
||||
break;
|
||||
case COMSUB:
|
||||
case FUNSUB:
|
||||
case VALSUB:
|
||||
case EXPRSUB:
|
||||
while (*wp++ != 0)
|
||||
;
|
||||
@ -834,6 +842,9 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
|
||||
case FUNSUB:
|
||||
shf_puts("FUNSUB<", shf);
|
||||
goto dumpsub;
|
||||
case VALSUB:
|
||||
shf_puts("VALSUB<", shf);
|
||||
goto dumpsub;
|
||||
case EXPRSUB:
|
||||
shf_puts("EXPRSUB<", shf);
|
||||
goto dumpsub;
|
||||
|
Loading…
x
Reference in New Issue
Block a user