mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-13 11:42:21 +00:00
Revert "Fix defining types conditionally and/or in subshells (re: 8ced1daa
)"
This reverts commit 2b9cbbbc8e
.
This is not ready for prime time. Crashses when running a $PS2
discipline function. This needs fixing and more testing in
development before making it into the 1.0 branch. In the meantime,
that terrible problem with types is back, sorry about that.
This commit is contained in:
parent
2b9cbbbc8e
commit
f508660ddf
10 changed files with 18 additions and 101 deletions
7
NEWS
7
NEWS
|
@ -3,13 +3,6 @@ For full details, see the git log at: https://github.com/ksh93/ksh
|
|||
|
||||
Any uppercase BUG_* names are modernish shell bug IDs.
|
||||
|
||||
2021-11-29:
|
||||
|
||||
- Ksh no longer behaves badly when parsing a type definition command
|
||||
('typeset -T' or 'enum') without executing it or when executing it in
|
||||
a subshell. Types can now safely be defined in subshells and defined
|
||||
conditionally as in 'if condition; then enum ...; fi'.
|
||||
|
||||
2021-11-24:
|
||||
|
||||
- The --posix mode was amended to stop the '.' command (but not 'source') from
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#pragma prototyped
|
||||
#include "defs.h"
|
||||
|
||||
#define ENUM_ID "enum (ksh 93u+m) 2021-11-29"
|
||||
#define ENUM_ID "enum (ksh 93u+m) 2021-11-23"
|
||||
|
||||
const char sh_optenum[] =
|
||||
"[-?@(#)$Id: " ENUM_ID " $\n]"
|
||||
|
@ -239,10 +239,6 @@ int b_enum(int argc, char** argv, Shbltin_t *context)
|
|||
error(ERROR_USAGE|2, "%s", optusage(NiL));
|
||||
return 1;
|
||||
}
|
||||
#ifndef STANDALONE
|
||||
if(shp->subshell && !shp->subshare)
|
||||
sh_subfork();
|
||||
#endif
|
||||
while(cp = *argv++)
|
||||
{
|
||||
if(!(np = nv_open(cp, (void*)0, NV_VARNAME|NV_NOADD)) || !(ap=nv_arrayptr(np)) || ap->fun || (sz=ap->nelem&(((1L<<ARRAY_BITS)-1))) < 2)
|
||||
|
|
|
@ -1769,7 +1769,7 @@ const char sh_opttrap[] =
|
|||
;
|
||||
|
||||
const char sh_opttypeset[] =
|
||||
"+[-1c?\n@(#)$Id: typeset (ksh 93u+m) 2021-11-29 $\n]"
|
||||
"+[-1c?\n@(#)$Id: typeset (ksh 93u+m) 2021-02-10 $\n]"
|
||||
"[--catalog?" SH_DICT "]"
|
||||
"[+NAME?typeset - declare or display variables with attributes]"
|
||||
"[+DESCRIPTION?Without the \b-f\b option, \btypeset\b sets, unsets, "
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
|
||||
#define SH_RELEASE_SVER "1.0.0-beta.2" /* semantic version number: https://semver.org */
|
||||
#define SH_RELEASE_DATE "2021-11-29" /* must be in this format for $((.sh.version)) */
|
||||
#define SH_RELEASE_DATE "2021-11-24" /* must be in this format for $((.sh.version)) */
|
||||
#define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK
|
||||
|
||||
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */
|
||||
|
|
|
@ -8661,3 +8661,7 @@ won't be executed until the foreground job terminates.
|
|||
It is a good idea to leave a space after the comma operator in
|
||||
arithmetic expressions to prevent the comma from being interpreted
|
||||
as the decimal point character in certain locales.
|
||||
.PP
|
||||
Commands that add type definitions (\f3enum\fP, \f3typeset -T\fP)
|
||||
must be run unconditionally and in the main shell environment.
|
||||
Defining types conditionally or in a subshell will cause undefined behavior.
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "variables.h"
|
||||
|
||||
static const char sh_opttype[] =
|
||||
"[-1c?\n@(#)$Id: type (ksh 93u+m) 2021-11-29 $\n]"
|
||||
"[-1c?\n@(#)$Id: type (AT&T Labs Research) 2008-07-01 $\n]"
|
||||
"[--catalog?" SH_DICT "]"
|
||||
"[+NAME?\f?\f - set the type of variables to \b\f?\f\b]"
|
||||
"[+DESCRIPTION?\b\f?\f\b sets the type on each of the variables specified "
|
||||
|
|
|
@ -65,10 +65,6 @@ static Shnode_t *test_and(Lex_t*);
|
|||
static Shnode_t *test_or(Lex_t*);
|
||||
static Shnode_t *test_primary(Lex_t*);
|
||||
|
||||
static void dcl_hacktivate(void), dcl_dehacktivate(void), (*orig_exit)(int), dcl_exit(int);
|
||||
static Dt_t *dcl_tree;
|
||||
static int dcl_recursion;
|
||||
|
||||
#define sh_getlineno(lp) (lp->lastline)
|
||||
|
||||
#ifndef NIL
|
||||
|
@ -187,10 +183,13 @@ static void typeset_order(const char *str,int line)
|
|||
}
|
||||
|
||||
/*
|
||||
* This function handles linting for 'typeset' options via typeset_order().
|
||||
* Pre-add type declaration built-ins at parse time to avoid
|
||||
* syntax errors when using -c, shcomp, '.'/source or eval.
|
||||
*
|
||||
* Also, upon parsing typeset -T or enum, it pre-adds the type declaration built-ins that these would create to
|
||||
* an internal tree to avoid syntax errors upon pre-execution parsing of assignment-arguments with parentheses.
|
||||
* This hack has a bad side effect: defining a type with 'typeset -T' or 'enum'
|
||||
* in a subshell or an 'if false' block will cause an inconsistent state. But
|
||||
* as these built-ins alter the syntax of the shell, it's necessary for making
|
||||
* them work if we're parsing an entire script before or without executing it.
|
||||
*
|
||||
* intypeset==1 for typeset & friends; intypeset==2 for enum
|
||||
*/
|
||||
|
@ -251,43 +250,6 @@ static void check_typedef(struct comnod *tp, char intypeset)
|
|||
if(cp)
|
||||
nv_onattr(sh_addbuiltin(cp, (Shbltin_f)SYSTRUE->nvalue.bfp, NIL(void*)), NV_BLTIN|BLT_DCL);
|
||||
}
|
||||
/*
|
||||
* (De)activate an internal declaration built-ins tree into which check_typedef() can pre-add dummy type
|
||||
* declaration command nodes, allowing correct parsing of assignment-arguments with parentheses for custom
|
||||
* type declaration commands before actually executing the commands that create those commands.
|
||||
*
|
||||
* A viewpath from the main built-ins tree to this internal tree is added, unifying the two for search
|
||||
* purposes and causing new nodes to be added to the internal tree. When parsing is done, we close that
|
||||
* viewpath. This hides those pre-added nodes at execution time, avoiding an inconsistent state if a type
|
||||
* creation command is parsed but not executed.
|
||||
*/
|
||||
static void dcl_hacktivate(void)
|
||||
{
|
||||
if(!dcl_tree)
|
||||
dcl_tree = dtopen(&_Nvdisc, Dtoset);
|
||||
if(dcl_recursion++)
|
||||
return;
|
||||
dtview(sh.bltin_tree, dcl_tree);
|
||||
orig_exit = error_info.exit;
|
||||
error_info.exit = dcl_exit;
|
||||
}
|
||||
static void dcl_dehacktivate(void)
|
||||
{
|
||||
#if !_AST_ksh_release
|
||||
if(!dcl_recursion || !dcl_tree)
|
||||
abort();
|
||||
#endif
|
||||
if(--dcl_recursion)
|
||||
return;
|
||||
error_info.exit = orig_exit;
|
||||
dtview(sh.bltin_tree, NIL(Dt_t*));
|
||||
}
|
||||
static noreturn void dcl_exit(int e)
|
||||
{
|
||||
dcl_dehacktivate();
|
||||
(*error_info.exit)(e);
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a parent node for fork() or io-redirection
|
||||
|
@ -546,7 +508,6 @@ static Shnode_t *sh_cmd(Lex_t *lexp, register int sym, int flag)
|
|||
{
|
||||
register Shnode_t *left, *right;
|
||||
register int type = FINT|FAMP;
|
||||
dcl_hacktivate();
|
||||
if(sym==NL)
|
||||
lexp->lasttok = 0;
|
||||
left = list(lexp,flag);
|
||||
|
@ -588,7 +549,6 @@ static Shnode_t *sh_cmd(Lex_t *lexp, register int sym, int flag)
|
|||
sh_syntax(lexp);
|
||||
}
|
||||
}
|
||||
dcl_dehacktivate();
|
||||
return(left);
|
||||
}
|
||||
|
||||
|
@ -1090,19 +1050,8 @@ static struct argnod *assign(Lex_t *lexp, register struct argnod *ap, int type)
|
|||
if(array && type==NV_TYPE)
|
||||
{
|
||||
struct argnod *arg = lexp->arg;
|
||||
int save_recursion = dcl_recursion;
|
||||
int p;
|
||||
/*
|
||||
* Forcibly deactivate the dummy declaration built-ins tree as path_search() does an
|
||||
* FPATH search, which may cause arbitrary ksh code to be executed. Yes, at parse time.
|
||||
*/
|
||||
n = lexp->token;
|
||||
dcl_recursion = 1;
|
||||
dcl_dehacktivate();
|
||||
p = path_search(lexp->sh,lexp->arg->argval,NIL(Pathcomp_t**),1);
|
||||
dcl_hacktivate();
|
||||
dcl_recursion = save_recursion;
|
||||
if(p && (np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && nv_isattr(np,BLT_DCL))
|
||||
if(path_search(lexp->sh,lexp->arg->argval,NIL(Pathcomp_t**),1) && (np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && nv_isattr(np,BLT_DCL))
|
||||
{
|
||||
lexp->token = n;
|
||||
lexp->arg = arg;
|
||||
|
|
|
@ -1090,8 +1090,6 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
#if SHOPT_TYPEDEF
|
||||
else if(argn>=3 && checkopt(com,'T'))
|
||||
{
|
||||
if(shp->subshell && !shp->subshare)
|
||||
sh_subfork();
|
||||
# if SHOPT_NAMESPACE
|
||||
if(shp->namespace)
|
||||
{
|
||||
|
|
|
@ -155,11 +155,6 @@ got=$(eval 2>&1 'command command command enum -i -i -iii --igno -ii PARSER_t=(r
|
|||
exp='PARSER_t -r -A hack=([C]=g)'
|
||||
[[ $got == "$exp" ]] || err_exit "incorrect typeset output for enum with command prefix and options" \
|
||||
"(expected $(printf %q "$exp"); got $(printf %q "$got"))"
|
||||
PATH=/dev/null command -v PARSER_t >/dev/null && err_exit "PARSER_t leaked out of subshell"
|
||||
if false
|
||||
then enum PARSER2_t=(a b)
|
||||
fi
|
||||
PATH=/dev/null command -v PARSER2_t >/dev/null && err_exit "PARSER2_t incompletely defined though definition was never executed"
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
|
|
@ -452,24 +452,20 @@ cd "$tmp"
|
|||
FPATH=$PWD
|
||||
PATH=$PWD:$PATH
|
||||
cat > A_t <<- \EOF
|
||||
if false
|
||||
then typeset -T Parser_shenanigans=(typeset -i foo)
|
||||
fi
|
||||
typeset -T A_t=(
|
||||
B_t b
|
||||
)
|
||||
EOF
|
||||
cat > B_t <<- \EOF
|
||||
PATH=/dev/null command -v Parser_shenanigans
|
||||
typeset -T B_t=(
|
||||
integer n=5
|
||||
)
|
||||
EOF
|
||||
|
||||
unset n
|
||||
if n=$(FPATH=$PWD PATH=$PWD:$PATH "$SHELL" -c 'A_t a; print ${a.b.n}' 2>&1)
|
||||
then [[ $n == '5' ]] || err_exit "dynamic loading of types gives wrong result (got $(printf %q "$n"))"
|
||||
else err_exit "unable to load types dynamically (got $(printf %q "$n"))"
|
||||
if n=$(FPATH=$PWD PATH=$PWD:$PATH $SHELL 2> /dev/null -c 'A_t a; print ${a.b.n}')
|
||||
then (( n==5 )) || err_exit 'dynamic loading of types gives wrong result'
|
||||
else err_exit 'unable to load types dynamically'
|
||||
fi
|
||||
|
||||
# check that typeset -T reproduces a type.
|
||||
|
@ -643,19 +639,5 @@ got=$($SHELL -c 'enum Foo_t=(foo bar); typeset -T')
|
|||
[[ -z $got ]] || err_exit "Types created by enum are listed with 'typeset -T'" \
|
||||
"(got $(printf %q "$got"))"
|
||||
|
||||
# ======
|
||||
# Parser shenanigans.
|
||||
if false
|
||||
then typeset -T PARSER_t=(typeset name=foobar)
|
||||
fi
|
||||
PATH=/dev/null command -v PARSER_t >/dev/null && err_exit "PARSER_t incompletely defined though definition was never executed"
|
||||
|
||||
unset v
|
||||
got=$( set +x; redirect 2>&1; typeset -T Subsh_t=(typeset -i x); Subsh_t -a v=( (x=1) (x=2) (x=3) ); typeset -p v )
|
||||
exp='Subsh_t -a v=((typeset -i x=1) (typeset -i x=2) (typeset -i x=3))'
|
||||
[[ $got == "$exp" ]] || err_exit "bad typeset output for Subsh_t" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
PATH=/dev/null command -v Subsh_t >/dev/null && err_exit "Subsh_t leaked out of subshell"
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
|
Loading…
Reference in a new issue