Merge tag 'mksh-R52c'

This commit is contained in:
KO Myung-Hun 2016-03-05 14:59:34 +09:00
commit 68f6e899ef
20 changed files with 387 additions and 489 deletions

View File

@ -1,5 +1,5 @@
#!/bin/sh
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.696 2016/01/21 18:24:33 tg Exp $'
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.697 2016/03/04 18:28:39 tg Exp $'
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015, 2016
@ -2347,7 +2347,7 @@ addsrcs '!' HAVE_STRLCPY strlcpy.c
addsrcs USE_PRINTF_BUILTIN printf.c
test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
add_cppflags -DMKSH_BUILD_R=522
add_cppflags -DMKSH_BUILD_R=523
$e $bi$me: Finished configuration testing, now producing output.$ao

188
Makefile
View File

@ -1,188 +0,0 @@
# $MirOS: src/bin/mksh/Makefile,v 1.146 2016/01/21 18:24:34 tg Exp $
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015, 2016
# mirabilos <m@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
# are retained or reproduced in an accompanying document, permission
# is granted to deal in this work without restriction, including un-
# limited rights to use, publicly perform, distribute, sell, modify,
# merge, give away, or sublicence.
#
# This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
# the utmost extent permitted by applicable law, neither express nor
# implied; without malicious intent or gross negligence. In no event
# may a licensor, author or contributor be held liable for indirect,
# direct, other damage, loss, or other issues arising in any way out
# of dealing in the work, even if advised of the possibility of such
# damage or existence of a defect, except proven that it results out
# of said person's immediate fault when using the work as intended.
.ifmake d
__CRAZY= Yes
MKC_DEBG= cpp
DEBUGFILE= Yes
NOMAN= Yes
.endif
.include <bsd.own.mk>
SRCDIR= ${.CURDIR}
PROG= mksh
SRCS= edit.c eval.c exec.c expr.c funcs.c histrap.c jobs.c \
lalloc.c lex.c main.c misc.c shf.c syn.c tree.c var.c
.if !make(test-build)
CPPFLAGS+= -DMKSH_ASSUME_UTF8 -DMKSH_DISABLE_DEPRECATED \
-DHAVE_ATTRIBUTE_BOUNDED=1 -DHAVE_ATTRIBUTE_FORMAT=1 \
-DHAVE_ATTRIBUTE_NORETURN=1 -DHAVE_ATTRIBUTE_PURE=1 \
-DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 \
-DHAVE_SYS_TIME_H=1 -DHAVE_TIME_H=1 -DHAVE_BOTH_TIME_H=1 \
-DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 \
-DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_PARAM_H=1 \
-DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1 \
-DHAVE_SYS_SYSMACROS_H=0 -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 \
-DHAVE_IO_H=0 -DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 \
-DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 \
-DHAVE_TERMIOS_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 \
-DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 \
-DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 -DHAVE_RLIM_T=1 \
-DHAVE_SIG_T=1 -DHAVE_SYS_ERRLIST=1 -DHAVE_SYS_SIGNAME=1 \
-DHAVE_SYS_SIGLIST=1 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 \
-DHAVE_GETRUSAGE=1 -DHAVE_GETSID=1 -DHAVE_GETTIMEOFDAY=1 \
-DHAVE_KILLPG=1 -DHAVE_MEMMOVE=1 -DHAVE_MKNOD=0 -DHAVE_MMAP=1 \
-DHAVE_NICE=1 -DHAVE_REVOKE=1 -DHAVE_SETLOCALE_CTYPE=0 \
-DHAVE_LANGINFO_CODESET=0 -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 \
-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=522
CPPFLAGS+= -D${${PROG:L}_tf:C/(Mir${MAN:E}{0,1}){2}/4/:S/x/mksh_BUILD/:U}
CPPFLAGS+= -I.
COPTS+= -std=c89 -Wall
.endif
USE_PRINTF_BUILTIN?= 0
.if ${USE_PRINTF_BUILTIN} == 1
.PATH: ${BSDSRCDIR}/usr.bin/printf
SRCS+= printf.c
CPPFLAGS+= -DMKSH_PRINTF_BUILTIN
.endif
DEBUGFILE?= No
.if ${DEBUGFILE:L} == "yes"
CPPFLAGS+= -DDF=mksh_debugtofile
.endif
MANLINKS= [ false pwd sh sleep test true
BINLINKS= ${MANLINKS} echo domainname kill
.for _i in ${BINLINKS}
LINKS+= ${BINDIR}/${PROG} ${BINDIR}/${_i}
.endfor
.for _i in ${MANLINKS}
MLINKS+= ${PROG}.1 ${_i}.1
.endfor
OPTGENS!= cd ${SRCDIR:Q} && echo *.opt
.for _i in ${OPTGENS}
GENERATED+= ${_i:R}.gen
${_i:R}.gen: ${_i} ${SRCDIR}/Build.sh
/bin/sh ${SRCDIR:Q}/Build.sh -G ${SRCDIR:Q}/${_i:Q}
.endfor
CLEANFILES+= ${GENERATED}
${PROG} beforedepend: ${GENERATED}
regress: ${PROG} check.pl check.t
-rm -rf regress-dir
mkdir -p regress-dir
echo export FNORD=666 >regress-dir/.mkshrc
HOME=$$(realpath regress-dir) perl ${SRCDIR}/check.pl \
-s ${SRCDIR}/check.t -v -p ./${PROG} \
-C shell:legacy-no,int:32,fastbox
test-build: .PHONY
-rm -rf build-dir
mkdir -p build-dir
.if ${USE_PRINTF_BUILTIN} == 1
cp ${BSDSRCDIR}/usr.bin/printf/printf.c build-dir/
.endif
cd build-dir; env CC=${CC:Q} CFLAGS=${CFLAGS:M*:Q} \
CPPFLAGS=${CPPFLAGS:M*:Q} LDFLAGS=${LDFLAGS:M*:Q} \
LIBS= NOWARN=-Wno-error TARGET_OS= CPP= /bin/sh \
${SRCDIR}/Build.sh -Q -r ${_TBF} && ./test.sh -v -f
CLEANFILES+= lksh.cat1
test-build-lksh: .PHONY
cd ${SRCDIR} && exec ${MAKE} lksh.cat1 test-build _TBF=-L
bothmans: .PHONY
cd ${SRCDIR} && exec ${MAKE} MAN='lksh.1 mksh.1' __MANALL
cleandir: clean-extra
clean-extra: .PHONY
-rm -rf build-dir regress-dir printf.o printf.ln
mksh_tf=xMakefile${OStype:S/${MACHINE_OS}/1/1g}${OSNAME}
distribution:
sed 's!\$$I''d\([:$$]\)!$$M''irSecuCron\1!g' \
${SRCDIR}/dot.mkshrc >${DESTDIR}/etc/skel/.mkshrc
chown ${BINOWN}:${CONFGRP} ${DESTDIR}/etc/skel/.mkshrc
chmod 0644 ${DESTDIR}/etc/skel/.mkshrc
.include <bsd.prog.mk>
.ifmake cats
V_GROFF!= pkg_info -e 'groff-*'
V_GHOSTSCRIPT!= pkg_info -e 'ghostscript-*'
. if empty(V_GROFF) || empty(V_GHOSTSCRIPT)
. error empty V_GROFF=${V_GROFF} or V_GHOSTSCRIPT=${V_GHOSTSCRIPT}
. endif
.endif
CLEANFILES+= ${MANALL:S/.cat/.ps/} ${MAN:S/$/.pdf/} ${MANALL:S/$/.gz/}
CLEANFILES+= ${MAN:S/$/.htm/} ${MAN:S/$/.htm.gz/}
CLEANFILES+= ${MAN:S/$/.txt/} ${MAN:S/$/.txt.gz/}
CATS_KW= mksh, ksh, sh
CATS_TITLE_mksh_1=mksh - The MirBSD Korn Shell
cats: ${MANALL} ${MANALL:S/.cat/.ps/}
.if "${MANALL:Nlksh.cat1:Nmksh.cat1}" != ""
. error Adjust here.
.endif
.for _m _n in mksh 1
x=$$(ident ${SRCDIR:Q}/${_m}.${_n} | \
awk '/Mir''OS:/ { print $$4$$5; }' | \
tr -dc 0-9); (( $${#x} == 14 )) || exit 1; exec \
${MKSH} ${BSDSRCDIR:Q}/contrib/hosted/tg/ps2pdfmir -c \
-o ${_m}.${_n}.pdf '[' /Author '(The MirOS Project)' \
/Title '('${CATS_TITLE_${_m}_${_n}:Q}')' \
/Subject '(BSD Reference Manual)' /ModDate "(D:$$x)" \
/Creator '(GNU groff version ${V_GROFF:S/groff-//} \(MirPorts\))' \
/Producer '(Artifex Ghostscript ${V_GHOSTSCRIPT:S/ghostscript-//:S/-artifex//} \(MirPorts\))' \
/Keywords '('${CATS_KW:Q}')' /DOCINFO pdfmark \
-f ${_m}.ps${_n}
.endfor
set -e; . ${BSDSRCDIR:Q}/scripts/roff2htm; set_target_absolute; \
for m in ${MANALL}; do \
bn=$${m%.*}; ext=$${m##*.cat}; \
[[ $$bn != $$m ]]; [[ $$ext != $$m ]]; \
gzip -n9 <"$$m" >"$$m.gz"; \
col -bx <"$$m" >"$$bn.$$ext.txt"; \
rm -f "$$bn.$$ext.txt.gz"; gzip -n9 "$$bn.$$ext.txt"; \
do_conversion_verbose "$$bn" "$$ext" "$$m" "$$bn.$$ext.htm"; \
rm -f "$$bn.$$ext.htm.gz"; gzip -n9 "$$bn.$$ext.htm"; \
done
.ifmake d
. ifmake obj || depend || all || install || regress || test-build
d:
. else
d: all
. endif
.endif
dr:
p=$$(realpath ${PROG:Q}) && cd ${SRCDIR:Q} && exec ${MKSH} \
${BSDSRCDIR:Q}/contrib/hosted/tg/sdmksh "$$p"

103
check.t
View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.724 2016/02/24 01:47:30 tg Exp $
# $MirOS: src/bin/mksh/check.t,v 1.727 2016/03/04 14:26:09 tg Exp $
# -*- mode: sh -*-
#-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -30,7 +30,7 @@
# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout:
@(#)MIRBSD KSH R52 2016/02/23
@(#)MIRBSD KSH R52 2016/03/04
description:
Check version of shell.
stdin:
@ -39,7 +39,7 @@ name: KSH_VERSION
category: shell:legacy-no
---
expected-stdout:
@(#)LEGACY KSH R52 2016/02/23
@(#)LEGACY KSH R52 2016/03/04
description:
Check version of legacy shell.
stdin:
@ -2249,7 +2249,7 @@ expected-stdout:
hi
there
---
name: heredoc-4
name: heredoc-4a
description:
Check that an error occurs if the heredoc-delimiter is missing.
stdin: !
@ -2259,6 +2259,34 @@ stdin: !
expected-exit: e > 0
expected-stderr-pattern: /.*/
---
name: heredoc-4an
description:
Check that an error occurs if the heredoc-delimiter is missing.
arguments: !-n!
stdin: !
cat << EOF
hi
there
expected-exit: e > 0
expected-stderr-pattern: /.*/
---
name: heredoc-4b
description:
Check that an error occurs if the heredoc is missing.
stdin: !
cat << EOF
expected-exit: e > 0
expected-stderr-pattern: /.*/
---
name: heredoc-4bn
description:
Check that an error occurs if the heredoc is missing.
arguments: !-n!
stdin: !
cat << EOF
expected-exit: e > 0
expected-stderr-pattern: /.*/
---
name: heredoc-5
description:
Check that backslash quotes a $, ` and \ and kills a \newline
@ -2657,6 +2685,32 @@ stdin:
expected-stdout:
= these parens \( ) are a problem =
---
name: heredoc-comsub-5
description:
Check heredoc and COMSUB mixture in input
stdin:
prefix() { sed -e "s/^/$1:/"; }
XXX() { echo x-en; }
YYY() { echo y-es; }
prefix A <<XXX && echo "$(prefix B <<XXX
echo line 1
XXX
echo line 2)" && prefix C <<YYY
echo line 3
XXX
echo line 4)"
echo line 5
YYY
XXX
expected-stdout:
A:echo line 3
B:echo line 1
line 2
C:echo line 4)"
C:echo line 5
x-en
---
name: heredoc-subshell-1
description:
Tests for here documents in subshells, taken from Austin ML
@ -6578,6 +6632,37 @@ stdin:
expected-exit: 1
expected-stderr-pattern: !/not set/
---
name: xxx-param-subst-qmark-namespec
description:
Check special names are output correctly
stdin:
doit() {
"$__progname" -c "$@" >o1 2>o2
rv=$?
echo RETVAL: $rv
sed -e "s^${__progname%.exe}\.*e*x*e*: PROG: " -e 's/^/STDOUT: /g' <o1
sed -e "s^${__progname%.exe}\.*e*x*e*: PROG: " -e 's/^/STDERR: /g' <o2
}
doit 'echo ${1x}'
doit 'echo "${1x}"'
doit 'echo ${1?}'
doit 'echo ${19?}'
doit 'echo ${!:?}'
doit -u 'echo ${*:?}' foo ""
expected-stdout:
RETVAL: 1
STDERR: PROG: ${1x}: bad substitution
RETVAL: 1
STDERR: PROG: ${1x}: bad substitution
RETVAL: 1
STDERR: PROG: 1: parameter null or not set
RETVAL: 1
STDERR: PROG: 19: parameter null or not set
RETVAL: 1
STDERR: PROG: !: parameter null or not set
RETVAL: 1
STDERR: foo: ${*:?}: bad substitution
---
name: xxx-param-_-1
# fails due to weirdness of execv stuff
category: !os:uwin-nt
@ -12111,6 +12196,14 @@ expected-stdout:
after 0='swc' 1='二' 2=''
= done
---
name: command-path
description:
Check 'command -p' is not 'whence -p'
stdin:
command -pv if
expected-stdout:
if
---
name: duffs-device
description:
Check that the compiler did not optimise-break them
@ -12183,7 +12276,7 @@ stdin:
Copyright (C) 2002 Free Software Foundation, Inc.'
EOF
chmod +x bash
"$__progname" -xc 'foo=$(./bash --version 2>&1 | sed 1q); echo "=$foo="'
"$__progname" -xc 'foo=$(./bash --version 2>&1 | sed q); echo "=$foo="'
expected-stdout:
=GNU bash, version 2.05b.0(1)-release (i386-ecce-mirbsd10)=
expected-stderr-pattern:

6
edit.c
View File

@ -28,7 +28,7 @@
#ifndef MKSH_NO_CMDLINE_EDITING
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.293 2016/01/21 18:24:37 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.294 2016/03/04 14:26:12 tg Exp $");
/*
* in later versions we might use libtermcap for this, but since external
@ -4601,8 +4601,8 @@ vi_cmd(int argcnt, const char *cmd)
static int
domove(int argcnt, const char *cmd, int sub)
{
int bcount, i = 0, t;
int ncursor = 0;
int ncursor = 0, i = 0, t;
unsigned int bcount;
switch (*cmd) {
case 'b':

12
eval.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.182 2016/02/24 01:47:32 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.185 2016/02/26 19:05:21 tg Exp $");
/*
* string expansion
@ -375,8 +375,9 @@ expand(
unwind_substsyn:
/* restore sp */
sp = varname - 2;
end = (beg = wdcopy(sp, ATEMP)) +
(wdscan(sp, CSUBST) - sp);
beg = wdcopy(sp, ATEMP);
end = (wdscan(cstrchr(sp, '\0') + 1,
CSUBST) - sp) + beg;
/* ({) the } or x is already skipped */
if (end < wdscan(beg, EOS))
*end = EOS;
@ -403,8 +404,8 @@ expand(
st->stype = stype;
st->base = Xsavepos(ds, dp);
st->f = f;
if (x.var == &vtemp) {
st->var = tempvar();
if (x.var == vtemp) {
st->var = tempvar(vtemp->name);
st->var->flag &= ~INTEGER;
/* can't fail here */
setstr(st->var,
@ -1192,6 +1193,7 @@ varsub(Expand *xp, const char *sp, const char *word,
/* can't trim a vector (yet) */
case '%':
case '#':
case '?':
case '0':
case '/':
case 0x100 | '#':

9
exec.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.171 2016/01/21 18:24:39 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.172 2016/03/01 18:30:04 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
@ -1623,13 +1623,6 @@ herein(struct ioword *iop, char **resbuf)
struct temp *h;
int i;
/* ksh -c 'cat <<EOF' can cause this... */
if (iop->heredoc == NULL && !(iop->ioflag & IOHERESTR)) {
warningf(true, Tmissinghere);
/* special to iosetup(): don't print error */
return (-2);
}
/* lexer substitution flags */
i = (iop->ioflag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;

23
expr.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.81 2016/01/14 21:17:50 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.83 2016/03/01 18:29:38 tg Exp $");
/* the order of these enums is constrained by the order of opinfo[] */
enum token {
@ -227,7 +227,7 @@ v_evaluate(struct tbl *vp, const char *expr, volatile int error_ok,
exprtoken(es);
if (es->tok == END) {
es->tok = LIT;
es->val = tempvar();
es->val = tempvar("");
}
v = intvar(es, evalexpr(es, MAX_PREC));
@ -649,7 +649,7 @@ exprtoken(Expr_state *es)
cp += len;
}
if (es->noassign) {
es->val = tempvar();
es->val = tempvar("");
es->val->flag |= EXPRLVALUE;
} else {
strndupx(tvar, es->tokp, cp - es->tokp, ATEMP);
@ -665,7 +665,10 @@ exprtoken(Expr_state *es)
goto process_tvar;
#ifndef MKSH_SMALL
} else if (c == '\'') {
++cp;
if (*++cp == '\0') {
es->tok = END;
evalerr(es, ET_UNEXPECTED, NULL);
}
cp += utf_ptradj(cp);
if (*cp++ != '\'')
evalerr(es, ET_STR,
@ -684,7 +687,7 @@ exprtoken(Expr_state *es)
c = *cp++;
strndupx(tvar, es->tokp, --cp - es->tokp, ATEMP);
process_tvar:
es->val = tempvar();
es->val = tempvar("");
es->val->flag &= ~INTEGER;
es->val->type = 0;
es->val->val.s = tvar;
@ -719,17 +722,19 @@ assign_check(Expr_state *es, enum token op, struct tbl *vasn)
}
struct tbl *
tempvar(void)
tempvar(const char *vname)
{
struct tbl *vp;
size_t vsize;
vp = alloc(sizeof(struct tbl), ATEMP);
vsize = strlen(vname) + 1;
vp = alloc(offsetof(struct tbl, name[0]) + vsize, ATEMP);
memcpy(vp->name, vname, vsize);
vp->flag = ISSET|INTEGER;
vp->type = 0;
vp->areap = ATEMP;
vp->ua.hval = 0;
vp->val.i = 0;
vp->name[0] = '\0';
return (vp);
}
@ -744,7 +749,7 @@ intvar(Expr_state *es, struct tbl *vp)
(vp->flag & (ISSET|INTEGER|EXPRLVALUE)) == (ISSET|INTEGER))
return (vp);
vq = tempvar();
vq = tempvar("");
if (setint_v(vq, vp, es->arith) == NULL) {
if (vp->flag & EXPRINEVAL)
evalerr(es, ET_RECURSIVE, vp->name);

162
funcs.c
View File

@ -38,7 +38,7 @@
#endif
#endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.294 2016/01/21 18:24:39 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.295 2016/02/26 20:56:43 tg Exp $");
#if HAVE_KILLPG
/*
@ -64,6 +64,8 @@ __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.294 2016/01/21 18:24:39 tg Exp $");
static int c_suspend(const char **);
#endif
static int do_whence(const char **, int, bool, bool);
/* getn() that prints error */
static int
bi_getn(const char *as, int *ai)
@ -514,14 +516,10 @@ s_put(int c MKSH_A_UNUSED)
int
c_whence(const char **wp)
{
struct tbl *tp;
const char *id;
bool pflag = false, vflag = false, Vflag = false;
int rv = 0, optc, fcflags;
bool iam_whence = wp[0][0] == 'w';
const char *opts = iam_whence ? "pv" : "pvV";
int optc;
bool pflag = false, vflag = false;
while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
while ((optc = ksh_getopt(wp, &builtin_opt, "pv")) != -1)
switch (optc) {
case 'p':
pflag = true;
@ -529,79 +527,82 @@ c_whence(const char **wp)
case 'v':
vflag = true;
break;
case '?':
return (1);
}
wp += builtin_opt.optind;
return (do_whence(wp, pflag ? FC_PATH :
FC_BI | FC_FUNC | FC_PATH | FC_WHENCE, vflag, false));
}
/* note: command without -vV is dealt with in comexec() */
int
c_command(const char **wp)
{
int optc, fcflags = FC_BI | FC_FUNC | FC_PATH | FC_WHENCE;
bool vflag = false;
/* options not sorted to facilitate string pooling */
while ((optc = ksh_getopt(wp, &builtin_opt, "Vpv")) != -1)
switch (optc) {
case 'p':
fcflags |= FC_DEFPATH;
break;
case 'V':
Vflag = true;
vflag = true;
break;
case 'v':
vflag = false;
break;
case '?':
return (1);
}
wp += builtin_opt.optind;
fcflags = FC_BI | FC_PATH | FC_FUNC;
if (!iam_whence) {
/* Note that -p on its own is deal with in comexec() */
if (pflag)
fcflags |= FC_DEFPATH;
/*
* Convert command options to whence options - note that
* command -pV uses a different path search than whence -v
* or whence -pv. This should be considered a feature.
*/
vflag = Vflag;
}
if (pflag)
fcflags &= ~(FC_BI | FC_FUNC);
return (do_whence(wp, fcflags, vflag, true));
}
static int
do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
{
uint32_t h;
int rv = 0;
struct tbl *tp;
const char *id;
while ((vflag || rv == 0) && (id = *wp++) != NULL) {
uint32_t h = 0;
h = hash(id);
tp = NULL;
if (!pflag)
tp = ktsearch(&keywords, id, h = hash(id));
if (!tp && !pflag) {
tp = ktsearch(&aliases, id, h ? h : hash(id));
if (fcflags & FC_WHENCE)
tp = ktsearch(&keywords, id, h);
if (!tp && (fcflags & FC_WHENCE)) {
tp = ktsearch(&aliases, id, h);
if (tp && !(tp->flag & ISSET))
tp = NULL;
}
if (!tp)
tp = findcom(id, fcflags);
if (vflag || (tp->type != CALIAS && tp->type != CEXEC &&
tp->type != CTALIAS))
switch (tp->type) {
case CSHELL:
case CFUNC:
case CKEYWD:
shf_puts(id, shl_stdout);
if (vflag) {
switch (tp->type) {
case CKEYWD:
case CALIAS:
case CFUNC:
case CSHELL:
shf_puts(" is a", shl_stdout);
break;
}
switch (tp->type) {
case CKEYWD:
case CSHELL:
case CTALIAS:
case CEXEC:
shf_putc(' ', shl_stdout);
break;
}
break;
}
switch (tp->type) {
case CKEYWD:
case CSHELL:
if (vflag)
shf_puts("reserved word", shl_stdout);
break;
case CALIAS:
if (vflag)
shprintf("n %salias for ",
(tp->flag & EXPORT) ? "exported " : null);
if (!iam_whence && !vflag)
shprintf("%s %s=", Talias, id);
print_value_quoted(shl_stdout, tp->val.s);
shprintf(" is a %sshell %s",
(tp->flag & SPEC_BI) ? "special " : "",
Tbuiltin);
break;
case CFUNC:
if (vflag) {
shf_puts(" is a", shl_stdout);
if (tp->flag & EXPORT)
shf_puts("n exported", shl_stdout);
if (tp->flag & TRACE)
@ -615,34 +616,42 @@ c_whence(const char **wp)
shf_puts(T_function, shl_stdout);
}
break;
case CSHELL:
if (vflag) {
if (tp->flag & SPEC_BI)
shf_puts("special ", shl_stdout);
shprintf("%s %s", "shell", Tbuiltin);
}
break;
case CTALIAS:
case CEXEC:
case CTALIAS:
if (tp->flag & ISSET) {
if (vflag) {
shf_puts("is ", shl_stdout);
shprintf("%s is ", id);
if (tp->type == CTALIAS)
shprintf("a tracked %s%s for ",
(tp->flag & EXPORT) ?
"exported " : null,
"exported " : "",
Talias);
}
shf_puts(tp->val.s, shl_stdout);
} else {
if (vflag)
shf_puts("not found", shl_stdout);
shprintf("%s not found", id);
rv = 1;
}
break;
default:
shf_puts(" is *GOK*", shl_stdout);
case CALIAS:
if (vflag) {
shprintf("%s is an %s%s for ", id,
(tp->flag & EXPORT) ? "exported " : "",
Talias);
} else if (iscommand)
shprintf("%s %s=", Talias, id);
print_value_quoted(shl_stdout, tp->val.s);
break;
case CKEYWD:
if (vflag)
shf_puts(" is a reserved word", shl_stdout);
break;
#ifndef MKSH_SMALL
default:
bi_errorf("%s is of unknown type %d", id, tp->type);
return (1);
#endif
}
if (vflag || !rv)
shf_putc('\n', shl_stdout);
@ -650,17 +659,6 @@ c_whence(const char **wp)
return (rv);
}
/* Deal with command -vV - command -p dealt with in comexec() */
int
c_command(const char **wp)
{
/*
* Let c_whence do the work. Note that c_command() must be
* a distinct function from c_whence() (tested in comexec()).
*/
return (c_whence(wp));
}
/* typeset, global, export, and readonly */
static void c_typeset_vardump(struct tbl *, uint32_t, int, bool, bool);
static void c_typeset_vardump_recursive(struct block *, uint32_t, int, bool,

View File

@ -27,7 +27,7 @@
#include <sys/file.h>
#endif
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.154 2016/02/24 01:45:59 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.156 2016/03/04 14:26:13 tg Exp $");
Trap sigtraps[ksh_NSIG + 1];
static struct sigaction Sigact_ign;
@ -1017,23 +1017,26 @@ inittraps(void)
{
int i;
const char *cs;
#if !HAVE_SYS_SIGNAME
const struct mksh_sigpair *pair;
#endif
trap_exstat = -1;
/* Populate sigtraps based on sys_signame and sys_siglist. */
/* populate sigtraps based on sys_signame and sys_siglist */
for (i = 1; i < ksh_NSIG; i++) {
sigtraps[i].signal = i;
#if HAVE_SYS_SIGNAME
cs = sys_signame[i];
#else
const struct mksh_sigpair *pair = mksh_sigpairs;
pair = mksh_sigpairs;
while ((pair->nr != i) && (pair->name != NULL))
++pair;
cs = pair->name;
#endif
if ((cs == NULL) ||
(cs[0] == '\0'))
sigtraps[i].name = shf_smprintf("%d", i);
sigtraps[i].name = null;
else {
char *s;
@ -1049,7 +1052,18 @@ inittraps(void)
sigtraps[i].name = s;
while ((*s = ksh_toupper(*s)))
++s;
/* check for reserved names */
if (!strcmp(sigtraps[i].name, "EXIT") ||
!strcmp(sigtraps[i].name, "ERR")) {
#ifndef MKSH_SMALL
internal_warningf("ignoring invalid signal name %s",
sigtraps[i].name);
#endif
sigtraps[i].name = null;
}
}
if (sigtraps[i].name == null)
sigtraps[i].name = shf_smprintf("%d", i);
#if HAVE_SYS_SIGLIST
sigtraps[i].mess = sys_siglist[i];
#elif HAVE_STRSIGNAL

6
jobs.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.119 2016/02/24 01:44:45 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.120 2016/03/04 14:26:13 tg Exp $");
#if HAVE_KILLPG
#define mksh_killpg killpg
@ -1425,8 +1425,8 @@ check_job(Job *j)
/* XXX debugging (nasty - interrupt routine using shl_out) */
if (!(j->flags & JF_STARTED)) {
internal_warningf("check_job: job started (flags 0x%x)",
j->flags);
internal_warningf("check_job: job started (flags 0x%X)",
(unsigned int)j->flags);
return;
}

View File

@ -23,7 +23,7 @@
#include <err.h>
#endif
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.25 2016/02/24 02:08:39 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.26 2016/02/26 21:53:36 tg Exp $");
/* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */
#if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0)
@ -36,7 +36,7 @@ __RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.25 2016/02/24 02:08:39 tg Exp $");
static struct lalloc_common *findptr(struct lalloc_common **, char *, Area *);
#ifndef MKSH_ALLOC_CATCH_UNDERRUNS
#define ALLOC_ISUNALIGNED(p) (((size_t)(p)) % ALLOC_SIZE)
#define ALLOC_ISUNALIGNED(p) (((size_t)(p)) % sizeof(struct lalloc_common))
#else
#define ALLOC_ISUNALIGNED(p) (((size_t)(p)) & 4095)
#undef remalloc
@ -107,10 +107,10 @@ findptr(struct lalloc_common **lpp, char *ptr, Area *ap)
#endif
/* get address of ALLOC_ITEM from user item */
/*
* note: the alignment of "ptr" to ALLOC_SIZE is checked
* note: the alignment of "ptr" to ALLOC_ITEM is checked
* above; the "void *" gets us rid of a gcc 2.95 warning
*/
*lpp = (lp = ptr - ALLOC_SIZE);
*lpp = (lp = ptr - sizeof(ALLOC_ITEM));
/* search for allocation item in group list */
while (ap->next != lp)
if ((ap = ap->next) == NULL) {
@ -126,7 +126,7 @@ findptr(struct lalloc_common **lpp, char *ptr, Area *ap)
internal_errorf("rogue pointer %zX", (size_t)ptr);
#endif
}
return ((void *)ap);
return (ap);
}
void *
@ -150,18 +150,18 @@ aresize(void *ptr, size_t numb, Area *ap)
pp->next = lp->next;
}
if (notoktoadd(numb, ALLOC_SIZE) ||
(lp = remalloc(lp, numb + ALLOC_SIZE)) == NULL
if (notoktoadd(numb, sizeof(ALLOC_ITEM)) ||
(lp = remalloc(lp, numb + sizeof(ALLOC_ITEM))) == NULL
#ifndef MKSH_SMALL
|| ALLOC_ISUNALIGNED(lp)
#endif
)
internal_errorf(Toomem, numb);
/* this only works because Area and ALLOC_ITEM share lalloc_common */
/* area pointer and items share struct lalloc_common */
lp->next = ap->next;
ap->next = lp;
/* return user item address */
return ((char *)lp + ALLOC_SIZE);
return ((char *)lp + sizeof(ALLOC_ITEM));
}
void

48
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.219 2016/01/21 18:24:41 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.222 2016/03/01 19:22:31 tg Exp $");
/*
* states while lexing word
@ -526,33 +526,13 @@ yylex(int cf)
*wp++ = COMSUB;
/*
* We need to know whether we are within double
* quotes, since most shells translate \" to "
* within "…`…\"…`…". This is not done in POSIX
* mode (§2.2.3 Double-Quotes: The backquote
* shall retain its special meaning introducing
* the other form of command substitution (see
* Command Substitution). The portion of the
* quoted string from the initial backquote and
* the characters up to the next backquote that
* is not preceded by a <backslash>, having
* escape characters removed, defines that
* command whose output replaces "`...`" when
* the word is expanded.; §2.6.3 Command
* Substitution: Within the backquoted style
* of command substitution, <backslash> shall
* retain its literal meaning, except when
* followed by: '$', '`', or <backslash>. The
* search for the matching backquote shall be
* satisfied by the first unquoted non-escaped
* backquote; during this search, if a
* non-escaped backquote is encountered[],
* undefined results occur.).
* quotes in order to translate \" to " within
* "…`…\"…`…" because, unlike for COMSUBs, the
* outer double quoteing changes the backslash
* meaning for the inside. For more details:
* http://austingroupbugs.net/view.php?id=1015
*/
statep->ls_bool = false;
#ifdef austingroupbugs1015_is_still_not_resolved
if (Flag(FPOSIX))
break;
#endif
s2 = statep;
base = state_info.base;
while (/* CONSTCOND */ 1) {
@ -1000,6 +980,16 @@ yylex(int cf)
if (cf & CONTIN)
goto Again;
}
} else if (c == '\0' && !(cf & HEREDELIM)) {
struct ioword **p = heres;
while (p < herep)
if ((*p)->ioflag & IOHERESTR)
++p;
else
/* ksh -c 'cat <<EOF' can cause this */
yyerror("here document '%s' unclosed\n",
evalstr((*p)->delim, 0));
}
return (c);
}
@ -1173,7 +1163,7 @@ readhere(struct ioword *iop)
while (c != '\n') {
if (!c)
/* oops, reached EOF */
yyerror("%s '%s' unclosed\n", Theredoc, eof);
yyerror("here document '%s' unclosed\n", eof);
/* store character */
Xcheck(xs, xp);
Xput(xs, xp, c);
@ -1359,8 +1349,10 @@ getsc_line(Source *s)
ksh_tmout_state = TMOUT_READING;
alarm(ksh_tmout);
}
if (interactive)
if (interactive) {
histsave(&s->line, NULL, HIST_FLUSH, true);
change_winsz();
}
#ifndef MKSH_NO_CMDLINE_EDITING
if (have_tty && (
#if !MKSH_S_NOVI

16
main.c
View File

@ -34,7 +34,7 @@
#include <locale.h>
#endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.308 2016/02/24 01:44:46 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.310 2016/02/26 21:53:36 tg Exp $");
extern char **environ;
@ -110,13 +110,13 @@ rndsetup(void)
} *bufptr;
char *cp;
cp = alloc(sizeof(*bufptr) - ALLOC_SIZE, APERM);
cp = alloc(sizeof(*bufptr) - sizeof(ALLOC_ITEM), APERM);
#ifdef DEBUG
/* clear the allocated space, for valgrind */
memset(cp, 0, sizeof(*bufptr) - ALLOC_SIZE);
memset(cp, 0, sizeof(*bufptr) - sizeof(ALLOC_ITEM));
#endif
/* undo what alloc() did to the malloc result address */
bufptr = (void *)(cp - ALLOC_SIZE);
bufptr = (void *)(cp - sizeof(ALLOC_ITEM));
/* PIE or something similar provides us with deltas here */
bufptr->dataptr = &rndsetupstate;
/* ASLR in at least Windows, Linux, some BSDs */
@ -208,6 +208,8 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
/* initialise permanent Area */
ainit(&aperm);
/* max. name length: -2147483648 = 11 (+ NUL) */
vtemp = alloc(offsetof(struct tbl, name[0]) + 12, APERM);
/* set up base environment */
env.type = E_NONE;
@ -933,9 +935,9 @@ newenv(int type)
* struct env includes ALLOC_ITEM for alignment constraints
* so first get the actually used memory, then assign it
*/
cp = alloc(sizeof(struct env) - ALLOC_SIZE, ATEMP);
cp = alloc(sizeof(struct env) - sizeof(ALLOC_ITEM), ATEMP);
/* undo what alloc() did to the malloc result address */
ep = (void *)(cp - ALLOC_SIZE);
ep = (void *)(cp - sizeof(ALLOC_ITEM));
/* initialise public members of struct env (not the ALLOC_ITEM) */
ainit(&ep->area);
ep->oenv = e;
@ -1031,7 +1033,7 @@ quitenv(struct shf *shf)
/* free the struct env - tricky due to the ALLOC_ITEM inside */
cp = (void *)ep;
afree(cp + ALLOC_SIZE, ATEMP);
afree(cp + sizeof(ALLOC_ITEM), ATEMP);
}
/* Called after a fork to cleanup stuff left over from parents environment */

4
misc.c
View File

@ -30,7 +30,7 @@
#include <grp.h>
#endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.241 2016/01/21 18:24:43 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.242 2016/03/04 14:26:13 tg Exp $");
#define KSH_CHVT_FLAG
#ifdef MKSH_SMALL
@ -1291,7 +1291,7 @@ print_columns(struct shf *shf, unsigned int n,
shf_puts(str, shf);
else
shf_fprintf(shf, "%*s%*s",
max_col, str, nspace, null);
(int)max_col, str, (int)nspace, null);
}
shf_putchar('\n', shf);
}

70
mksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.389 2016/02/11 19:00:50 tg Exp $
.\" $MirOS: src/bin/mksh/mksh.1,v 1.392 2016/03/04 18:28:41 tg Exp $
.\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
@ -76,7 +76,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always.
.\"
.Dd $Mdocdate: February 11 2016 $
.Dd $Mdocdate: March 4 2016 $
.\"
.\" Check which macro package we use, and do other -mdoc setup.
.\"
@ -1004,13 +1004,14 @@ quotes all characters, except
.Ql \`
and
.Ql \e ,
up to the next unquoted double quote.
up to the next unescaped double quote.
.Ql $
and
.Ql \`
inside double quotes have their usual meaning (i.e. parameter, arithmetic,
or command substitution) except no field splitting is carried out on the
results of double-quoted substitutions.
results of double-quoted substitutions, and the old-style form of command
substitution has backslash-quoting for double quotes enabled.
If a
.Ql \e
inside a double-quoted string is followed by
@ -1307,13 +1308,13 @@ form, a
followed by any of
.Ql $ ,
.Ql \` ,
.Ql \&"
.Pq currently, and violating Tn POSIX ,
or
.Ql \e
is stripped (a
is stripped (as is
.Ql \&"
when the substitution is part of a double-quoted string); a backslash
.Ql \e
followed by any other character is unchanged).
followed by any other character is unchanged.
As a special case in command substitutions, a command of the form
.Pf \*(Lt Ar file
is interpreted to mean substitute the contents of
@ -4312,6 +4313,11 @@ options (with single letter names) can be found in the parameter
with no option name will list all the options and whether each is on or off;
.Ic set +o
will print the long names of all options that are currently on.
In a future version,
.Ic set +o
will behave
.Tn POSIX
compliant and print commands to restore the current options instead.
.Pp
Remaining arguments, if any, are positional parameters and are assigned, in
order, to the positional parameters (i.e. $1, $2, etc.).
@ -5141,38 +5147,20 @@ If job monitoring is enabled, the completion status of jobs is printed
.Op Fl pv
.Op Ar name ...
.Xc
For each
.Ar name ,
the type of command is listed (reserved word, built-in, alias,
function, tracked alias, or executable).
If the
.Fl p
option is used, a path search is performed even if
.Ar name
is a reserved word, alias, etc.
Without the
.Fl v
option,
.Ic whence
is similar to
.Ic command Fl v
except that
.Ic whence
will find reserved words and won't print aliases as alias commands.
option, it is the same as
.Ic command Fl v ,
except aliases are not printed as alias command.
With the
.Fl v
option,
.Ic whence
is the same as
option, it is exactly the same as
.Ic command Fl V .
Note that for
.Ic whence ,
the
In either case, the
.Fl p
option does not affect the search path used, as it does for
.Ic command .
If the type of one or more of the names could not be determined, the exit
status is non-zero.
option differs: the search path is not affected in
.Ic whence ,
but the search is restricted to the path.
.El
.Ss Job control
Job control refers to the shell's ability to monitor and control jobs which
@ -6596,20 +6584,8 @@ when multiple shells are accessing the file; the rollover process
for the in-memory portion of the history is slow, should use
.Xr memmove 3 .
.Pp
Handling of backslash plus double-quote inside the (deprecated)
.Pf \` Ns Ar command Ns \`
form of command substitution when the substitution itself is
also inside double quotes currently deliberately violates
.Tn POSIX
even in
.Fl o Ic posix
mode until Austin group bug 1015 has been resolved either way,
as the current wording of the standard prohibits the current
and historic practice of several shells which several scripts
(admittedly wrongly) depend on.
.Pp
This document attempts to describe
.Nm mksh\ R52b
.Nm mksh\ R52c
and up,
.\" with vendor patches from insert-your-name-here,
compiled without any options impacting functionality, such as

38
sh.h
View File

@ -175,9 +175,9 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.762 2016/02/24 02:08:39 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.768 2016/03/04 18:28:42 tg Exp $");
#endif
#define MKSH_VERSION "R52 2016/02/23"
#define MKSH_VERSION "R52 2016/03/04"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
@ -578,7 +578,7 @@ char *ucstrstr(char *, const char *);
#define mkssert(e) do { } while (/* CONSTCOND */ 0)
#endif
#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 522)
#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 523)
#error Must run Build.sh to compile this.
extern void thiswillneverbedefinedIhope(void);
int
@ -703,21 +703,21 @@ struct lalloc_common {
struct lalloc_common *next;
};
#ifdef MKSH_ALLOC_CATCH_UNDERRUNS
struct lalloc_item {
struct lalloc_common *next;
#ifdef MKSH_ALLOC_CATCH_UNDERRUNS
size_t len;
char dummy[8192 - sizeof(struct lalloc_common *) - sizeof(size_t)];
#endif
};
#endif
/* 2. sizes */
#ifdef MKSH_ALLOC_CATCH_UNDERRUNS
#define ALLOC_ITEM struct lalloc_item
#define ALLOC_SIZE (sizeof(ALLOC_ITEM))
#ifndef MKSH_ALLOC_CATCH_UNDERRUNS
#define ALLOC_OVERHEAD ALLOC_SIZE
#else
#define ALLOC_OVERHEAD 0
#else
#define ALLOC_ITEM struct lalloc_common
#define ALLOC_OVERHEAD (sizeof(ALLOC_ITEM))
#endif
/* 3. group structure */
@ -850,11 +850,13 @@ EXTERN struct {
/* null value for variable; comparison pointer for unset */
EXTERN char null[] E_INIT("");
/* helpers for string pooling */
EXTERN const char Tintovfl[] E_INIT("integer overflow %zu %c %zu prevented");
EXTERN const char Toomem[] E_INIT("can't allocate %zu data bytes");
#if defined(__GNUC__)
#define Tsynerr "syntax error"
#define Tintovfl "integer overflow %zu %c %zu prevented"
#define Toomem "can't allocate %zu data bytes"
#else
EXTERN const char Tintovfl[] E_INIT("integer overflow %zu %c %zu prevented");
EXTERN const char Toomem[] E_INIT("can't allocate %zu data bytes");
EXTERN const char Tsynerr[] E_INIT("syntax error");
#endif
EXTERN const char Tselect[] E_INIT("select");
@ -887,12 +889,6 @@ EXTERN const char T_funny_command[] E_INIT("funny $() command");
EXTERN const char Tfg_badsubst[] E_INIT("fileglob: bad substitution");
#endif
#define Tbadsubst (Tfg_badsubst + 10) /* "bad substitution" */
#if defined(__GNUC__)
#define Tmissinghere "missing here document"
#else
EXTERN const char Tmissinghere[] E_INIT("missing here document");
#endif
#define Theredoc (Tmissinghere + 8) /* "here document" */
EXTERN const char TC_LEX1[] E_INIT("|&;<>() \t\n");
#define TC_IFSWS (TC_LEX1 + 7) /* space tab newline */
@ -1216,7 +1212,7 @@ struct tbl {
char name[4];
};
EXTERN struct tbl vtemp;
EXTERN struct tbl *vtemp;
/* set by global() and local() */
EXTERN bool last_lookup_was_array;
@ -1285,7 +1281,7 @@ enum namerefflag {
#define FC_BI (FC_SPECBI | FC_NORMBI)
#define FC_PATH BIT(3) /* do path search */
#define FC_DEFPATH BIT(4) /* use default path in path search */
#define FC_WHENCE BIT(5) /* for use by command and whence */
#define AF_ARGV_ALLOC 0x1 /* argv[] array allocated */
#define AF_ARGS_ALLOCED 0x2 /* argument strings allocated */
@ -1768,7 +1764,7 @@ size_t utf_ptradj(const char *) MKSH_A_PURE;
int utf_wcwidth(unsigned int) MKSH_A_PURE;
#endif
int ksh_access(const char *, int);
struct tbl *tempvar(void);
struct tbl *tempvar(const char *);
/* funcs.c */
int c_hash(const char **);
int c_pwd(const char **);
@ -2025,7 +2021,7 @@ char *shf_smprintf(const char *, ...)
ssize_t shf_vfprintf(struct shf *, const char *, va_list)
MKSH_A_FORMAT(__printf__, 2, 0);
/* syn.c */
int assign_command(const char *, bool);
int assign_command(const char *, bool) MKSH_A_PURE;
void initkeywords(void);
struct op *compile(Source *, bool);
bool parse_usec(const char *, struct timeval *);

85
shf.c
View File

@ -2,7 +2,7 @@
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
* 2012, 2013, 2015
* 2012, 2013, 2015, 2016
* mirabilos <m@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@ -25,7 +25,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.69 2015/12/31 20:38:59 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.70 2016/03/04 14:26:16 tg Exp $");
/* flags to shf_emptybuf() */
#define EB_READSW 0x01 /* about to switch to reading */
@ -197,7 +197,8 @@ shf_sopen(char *buf, ssize_t bsize, int sflags, struct shf *shf)
{
/* can't have a read+write string */
if (!(!(sflags & SHF_RD) ^ !(sflags & SHF_WR)))
internal_errorf("%s: flags 0x%X", "shf_sopen", sflags);
internal_errorf("%s: flags 0x%X", "shf_sopen",
(unsigned int)sflags);
if (!shf) {
shf = alloc(sizeof(struct shf), ATEMP);
@ -452,7 +453,8 @@ shf_read(char *buf, ssize_t bsize, struct shf *shf)
ssize_t ncopy, orig_bsize = bsize;
if (!(shf->flags & SHF_RD))
internal_errorf("%s: flags 0x%X", "shf_read", shf->flags);
internal_errorf("%s: flags 0x%X", "shf_read",
(unsigned int)shf->flags);
if (bsize <= 0)
internal_errorf("%s: %s %zd", "shf_write", "bsize", bsize);
@ -489,7 +491,8 @@ shf_getse(char *buf, ssize_t bsize, struct shf *shf)
char *orig_buf = buf;
if (!(shf->flags & SHF_RD))
internal_errorf("%s: flags 0x%X", "shf_getse", shf->flags);
internal_errorf("%s: flags 0x%X", "shf_getse",
(unsigned int)shf->flags);
if (bsize <= 0)
return (NULL);
@ -525,7 +528,8 @@ int
shf_getchar(struct shf *shf)
{
if (!(shf->flags & SHF_RD))
internal_errorf("%s: flags 0x%X", "shf_getchar", shf->flags);
internal_errorf("%s: flags 0x%X", "shf_getchar",
(unsigned int)shf->flags);
if (shf->rnleft == 0 && (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
return (-1);
@ -541,7 +545,8 @@ int
shf_ungetc(int c, struct shf *shf)
{
if (!(shf->flags & SHF_RD))
internal_errorf("%s: flags 0x%X", "shf_ungetc", shf->flags);
internal_errorf("%s: flags 0x%X", "shf_ungetc",
(unsigned int)shf->flags);
if ((shf->flags & SHF_ERROR) || c == -1 ||
(shf->rp == shf->buf && shf->rnleft))
@ -578,7 +583,8 @@ int
shf_putchar(int c, struct shf *shf)
{
if (!(shf->flags & SHF_WR))
internal_errorf("%s: flags 0x%X", "shf_putchar", shf->flags);
internal_errorf("%s: flags 0x%X", "shf_putchar",
(unsigned int)shf->flags);
if (c == -1)
return (-1);
@ -633,7 +639,8 @@ shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
ssize_t n, ncopy, orig_nbytes = nbytes;
if (!(shf->flags & SHF_WR))
internal_errorf("%s: flags 0x%X", "shf_write", shf->flags);
internal_errorf("%s: flags 0x%X", "shf_write",
(unsigned int)shf->flags);
if (nbytes < 0)
internal_errorf("%s: %s %zd", "shf_write", "nbytes", nbytes);
@ -764,7 +771,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
const char *s;
char c, *cp;
int tmp = 0, flags;
ssize_t field, precision, len;
size_t field, precision, len;
unsigned long lnum;
/* %#o produces the longest output */
char numbuf[(8 * sizeof(long) + 2) / 3 + 1];
@ -791,7 +798,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
*/
flags = 0;
field = precision = 0;
for ( ; (c = *fmt++) ; ) {
while ((c = *fmt++)) {
switch (c) {
case '#':
flags |= FL_HASH;
@ -821,12 +828,17 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
case '*':
tmp = VA(int);
if (flags & FL_DOT)
precision = tmp;
else if ((field = tmp) < 0) {
field = -field;
flags |= FL_RIGHT;
}
if (tmp < 0) {
if (flags & FL_DOT)
precision = 0;
else {
field = (unsigned int)-tmp;
flags |= FL_RIGHT;
}
} else if (flags & FL_DOT)
precision = (unsigned int)tmp;
else
field = (unsigned int)tmp;
continue;
case 'l':
@ -848,26 +860,23 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
bool overflowed = false;
tmp = ksh_numdig(c);
while (c = *fmt++, ksh_isdigit(c)) {
while (c = *fmt++, ksh_isdigit(c))
if (notok2mul(2147483647, tmp, 10))
overflowed = true;
tmp = tmp * 10 + ksh_numdig(c);
}
else
tmp = tmp * 10 + ksh_numdig(c);
--fmt;
if (overflowed)
tmp = 0;
if (flags & FL_DOT)
precision = tmp;
precision = (unsigned int)tmp;
else
field = tmp;
field = (unsigned int)tmp;
continue;
}
break;
}
if (precision < 0)
precision = 0;
if (!c)
/* nasty format */
break;
@ -953,7 +962,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
*--cp = (flags & FL_UPPER) ? 'X' : 'x';
*--cp = '0';
}
}
}
}
len = numbuf + sizeof(numbuf) - (s = cp);
if (flags & FL_DOT) {
@ -999,7 +1008,6 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
if (field > precision) {
field -= precision;
if (!(flags & FL_RIGHT)) {
field = -field;
/* skip past sign or 0x when padding with 0 */
if ((flags & FL_ZERO) && (flags & FL_NUMBER)) {
if (*s == '+' || *s == '-' ||
@ -1012,7 +1020,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
shf_putc(*s, shf);
s++;
nwritten++;
if (--precision > 0 &&
if (--precision &&
ksh_eq(*s, 'X', 'x')) {
shf_putc(*s, shf);
s++;
@ -1023,19 +1031,16 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
c = '0';
} else
c = flags & FL_ZERO ? '0' : ' ';
if (field < 0) {
nwritten += -field;
while (field < 0) {
shf_putc(c, shf);
++field;
}
}
nwritten += field;
while (field--)
shf_putc(c, shf);
field = 0;
} else
c = ' ';
} else
field = 0;
if (precision > 0) {
if (precision) {
const char *q;
nwritten += precision;
@ -1044,11 +1049,9 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
shf_putc(*s, shf);
} while (++s < q);
}
if (field > 0) {
nwritten += field;
for ( ; field > 0 ; --field)
shf_putc(c, shf);
}
nwritten += field;
while (field--)
shf_putc(c, shf);
}
return (shf_error(shf) ? -1 : nwritten);

6
syn.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.110 2016/01/21 18:24:44 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.111 2016/02/26 21:24:58 tg Exp $");
struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */
@ -31,6 +31,7 @@ struct nesting_state {
};
struct yyrecursive_state {
struct ioword *old_heres[HERES];
struct yyrecursive_state *next;
struct ioword **old_herep;
int old_symbol;
@ -1175,7 +1176,9 @@ yyrecursive(int subtype MKSH_A_UNUSED)
ys->old_reject = reject;
ys->old_symbol = symbol;
ACCEPT;
memcpy(ys->old_heres, heres, sizeof(heres));
ys->old_herep = herep;
herep = heres;
ys->old_salias = sALIAS;
sALIAS = 0;
ys->next = e->yyrecursive_statep;
@ -1202,6 +1205,7 @@ yyrecursive_pop(bool popall)
e->yyrecursive_statep = ys->next;
sALIAS = ys->old_salias;
memcpy(heres, ys->old_heres, sizeof(heres));
herep = ys->old_herep;
reject = ys->old_reject;
symbol = ys->old_symbol;

12
tree.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.81 2016/01/21 18:24:45 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.83 2016/03/04 14:26:16 tg Exp $");
#define INDENT 8
@ -631,8 +631,8 @@ wdscan(const char *wp, int c)
break;
default:
internal_warningf(
"wdscan: unknown char 0x%x (carrying on)",
wp[-1]);
"wdscan: unknown char 0x%X (carrying on)",
(unsigned char)wp[-1]);
}
}
@ -817,7 +817,7 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
return (--wp);
case ADELIM:
if (*wp == /*{*/'}') {
shf_puts("]ADELIM(})", shf);
shf_puts(/*{*/ "]ADELIM(})", shf);
return (wp + 1);
}
shf_puts("ADELIM=", shf);
@ -852,10 +852,10 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
shf_puts("EXPRSUB<", shf);
goto dumpsub;
case OQUOTE:
shf_fprintf(shf, "OQUOTE{%d", ++quotelevel);
shf_fprintf(shf, "OQUOTE{%d" /*}*/, ++quotelevel);
break;
case CQUOTE:
shf_fprintf(shf, "%d}CQUOTE", quotelevel);
shf_fprintf(shf, /*{*/ "%d}CQUOTE", quotelevel);
if (quotelevel)
quotelevel--;
else

44
var.c
View File

@ -28,7 +28,7 @@
#include <sys/sysctl.h>
#endif
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.198 2016/01/21 18:24:45 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.201 2016/03/01 20:28:33 tg Exp $");
/*-
* Variables
@ -242,18 +242,26 @@ global(const char *n)
if (!ksh_isalphx(c)) {
if (array)
errorf(Tbadsubst);
vp = &vtemp;
vp = vtemp;
vp->flag = DEFINED;
vp->type = 0;
vp->areap = ATEMP;
*vp->name = c;
if (ksh_isdigit(c)) {
if (getn(vn, &c) && (c <= l->argc))
/* setstr can't fail here */
setstr(vp, l->argv[c], KSH_RETURN_ERROR);
if (getn(vn, &c)) {
/* main.c:main_init() says 12 */
shf_snprintf(vp->name, 12, "%d", c);
if (c <= l->argc) {
/* setstr can't fail here */
setstr(vp, l->argv[c],
KSH_RETURN_ERROR);
}
} else
vp->name[0] = '\0';
vp->flag |= RDONLY;
goto out;
}
vp->name[0] = c;
vp->name[1] = '\0';
vp->flag |= RDONLY;
if (vn[1] != '\0')
goto out;
@ -320,7 +328,7 @@ local(const char *n, bool copy)
vn = array_index_calc(n, &array, &val);
h = hash(vn);
if (!ksh_isalphx(*vn)) {
vp = &vtemp;
vp = vtemp;
vp->flag = DEFINED|RDONLY;
vp->type = 0;
vp->areap = ATEMP;
@ -479,13 +487,12 @@ void
setint(struct tbl *vq, mksh_ari_t n)
{
if (!(vq->flag&INTEGER)) {
struct tbl *vp = &vtemp;
vp->flag = (ISSET|INTEGER);
vp->type = 0;
vp->areap = ATEMP;
vp->val.i = n;
vtemp->flag = (ISSET|INTEGER);
vtemp->type = 0;
vtemp->areap = ATEMP;
vtemp->val.i = n;
/* setstr can't fail here */
setstr(vq, str_val(vp), KSH_RETURN_ERROR);
setstr(vq, str_val(vtemp), KSH_RETURN_ERROR);
} else
vq->val.i = n;
vq->flag |= ISSET;
@ -827,12 +834,13 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
/* check target value for being a valid variable name */
ccp = skip_varname(qval, false);
if (ccp == qval) {
if (ksh_isdigit(qval[0])) {
int c;
int c;
if (getn(qval, &c))
goto nameref_rhs_checked;
} else if (qval[1] == '\0') switch (qval[0]) {
if (!(c = (unsigned char)qval[0]))
goto nameref_empty;
else if (ksh_isdigit(c) && getn(qval, &c))
goto nameref_rhs_checked;
else if (qval[1] == '\0') switch (c) {
case '$':
case '!':
case '?':