Skip to content

Commit

Permalink
[v1.1] Make '_' refer to type var in discipline func within type
Browse files Browse the repository at this point in the history
Example reproducer script:

  typeset -T Stopwatch_t=(
	float starttime stoptime diff
	function start { ((_.starttime = SECONDS)); }
	function stop { ((_.stoptime = SECONDS)); }
	function diff.getn
	{
		((.sh.value = _.stoptime - _.starttime))
		save_nameref=$(typeset -p _)
	}
  )
  Stopwatch_t sw
  sw.start
  sleep 0.1
  sw.stop
  printf "time=%f\n" sw.diff
  print "$save_nameref"

Actual output:

  time=0.000000
  typeset -n _=sw.diff

Expected output:

  time=0.105274
  typeset -n _=sw

The problem is that the automatic nameref '_' within the diff.getn
discipline function refers to the diff variable, though it was
expected to refer to its parent, the Stopwatch_t sw variable.

This is not actually a bug, though. It is documented behaviour that
'_' within a discipline function refers to the variable that the
discipline function is for. As sh.1 puts it: "The variable _ is a
reference to the variable including the subscript if any".

However, for discipline functions set for type subvariables, this
is not the most useful behaviour, because '_' is generally expected
to refer to the type variable when used in its subfunctions. It
would be more useful for '_' to always refer to the type variable,
inside and outside of a discipline function, so that a script like
the reproducer above can be straightforward.

'_' was changed to behave like this in the unreleased AT&T ksh 93v-
beta (and thus also in the abandoned ksh2020 release). This commit
backports that change for the future ksh 93u+m/1.1 release.

It does mean we lose '_' as a self-reference to the discipline
function variable in that specific case. This is an incompatible
change and not really a bugfix, so it would not be reasonable to
backport it to the stable 93u+m/1.0.x release series at this point.

src/cmd/ksh93/sh/nvtype.c,
src/cmd/ksh93/include/name.h:
- Backport nv_typeparent() function from ksh 93v- (versions
  2013-07-27 and 2013-08-29 in the ast-open-archive repo). This
  checks if the parent of a variable is of a 'typeset -T' type and,
  if so, returns a pointer to the node of that type variable.

src/cmd/ksh93/sh/xec.c: set_instance():
- Backport a check for parent type when setting '_' that uses the
  new function. If the variable node has the NV_MINIMAL attribute
  (what this means exactly remains to be researched), is not itself
  a type, but has a parent type, then we set '_' to the variable's
  parent node instead.

src/cmd/ksh93/tests/types.sh:
- Add regression test that was backported and significantly
  extended from the 93v- version.
  • Loading branch information
McDutchie committed Aug 26, 2024
1 parent ab43fdc commit b75df92
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 3 deletions.
4 changes: 4 additions & 0 deletions ANNOUNCE
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ New shell language features:
after the decimal point if the TIMEFORAMT variable is not set. See also
TIMEFORMAT under 'New features in shell variables' below.

- With in 'typeset -T' type declarations, the '_' automatic self-reference
variable now always refers to the type variable, even within discipline
function (such as .get or .getn) that are set for its subvariables.

New features in built-in commands:

- When printing a function definition, 'typeset -f function_name' now
Expand Down
10 changes: 10 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ This documents significant changes in the dev branch of ksh 93u+m.
For full details, see the git log at: https://github.com/ksh93/ksh
Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library.

2024-08-26:

- [v1.1] Backported a change to '_' in types from the unreleased ksh 93v-
beta. If a 'typeset -T' type declaration sets a discipline function for
one of its subvariables (such as var.get() or var.getn()), then, within
that discipline function, the automatic '_' nameref now refers to the type
variable and no longer to the subvariable that the discipline function was
set for. This means '_' now always refers to the type variable when used
in a type declaration.

2024-08-22:

- Fixed: command lines containing certain specific kinds of syntax error
Expand Down
7 changes: 7 additions & 0 deletions src/cmd/ksh93/COMPATIBILITY
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ For more details, see the NEWS file and for complete details, see the git log.
limited to two hexadecimal digits (yielding one byte). For
multi-byte characters, \u and \U should be used instead.

5. If a 'typeset -T' type declaration sets a discipline function for
one of its subvariables (such as var.get() or var.getn()), then,
within that discipline function, the automatic '_' nameref now
refers to the type variable and no longer to the subvariable that
the discipline function was set for. This means '_' now always
refers to the type variable when used in a type declaration.

____________________________________________________________________________

ksh 93u+m/1.0.9 vs. ksh 93u+
Expand Down
1 change: 1 addition & 0 deletions src/cmd/ksh93/include/name.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ extern void nv_outnode(Namval_t*,Sfio_t*, int, int);
extern int nv_subsaved(Namval_t*, int);
extern void nv_typename(Namval_t*, Sfio_t*);
extern void nv_newtype(Namval_t*);
extern Namval_t *nv_typeparent(Namval_t*);
extern int nv_istable(Namval_t*);
extern size_t nv_datasize(Namval_t*, size_t*);
extern Namfun_t *nv_mapchar(Namval_t*, const char*);
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/include/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
#define SH_RELEASE_SVER "1.1.0-alpha" /* semantic version number: https://semver.org */
#define SH_RELEASE_DATE "2024-08-23" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_DATE "2024-08-26" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_CPYR "(c) 2020-2024 Contributors to ksh " SH_RELEASE_FORK

/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */
Expand Down
9 changes: 7 additions & 2 deletions src/cmd/ksh93/sh.1
Original file line number Diff line number Diff line change
Expand Up @@ -1682,7 +1682,10 @@ file when checking for mail.
While defining a compound variable or a type,
.B _
is initialized as a reference to the compound variable or type.
When a discipline function is invoked,
When a discipline function is invoked
for a variable that is not a type subvariable in the sense of
.I "Type Variables"\^
below, then
.B _
is initialized as a reference to the variable associated with
the call to this function.
Expand Down Expand Up @@ -4208,7 +4211,9 @@ is the subscript of the variable, and
will contain the value being assigned inside the
.B set
discipline function.
The variable
If the variable is not a type subvariable in the sense of
.I "Type Variables"\^
below, then the variable
.B _
is a reference to the variable including the subscript if any.
For the \f3set\fP discipline,
Expand Down
11 changes: 11 additions & 0 deletions src/cmd/ksh93/sh/nvtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -1469,3 +1469,14 @@ int sh_outtype(Sfio_t *out)
dtinsert(sh.var_base,L_ARGNOD);
return 0;
}

Namval_t *nv_typeparent(Namval_t *np)
{
Namchld_t *fp;
Namtype_t *tp;
if(fp = (Namchld_t*)nv_hasdisc(np,&chtype_disc))
return fp->ptype->parent;
if(tp = (Namtype_t*)nv_hasdisc(np,&type_disc))
return tp->parent;
return NULL;
}
2 changes: 2 additions & 0 deletions src/cmd/ksh93/sh/xec.c
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,8 @@ static long set_instance(Namval_t *nq, Namval_t *node, struct Namref *nr)
Namval_t *np;
if(!nv_isattr(nq,NV_MINIMAL|NV_EXPORT|NV_ARRAY) && (np = nq->nvmeta) && nv_isarray(np))
nq = np;
else if(nv_isattr(nq,NV_MINIMAL)==NV_MINIMAL && !nv_type(nq) && (np = nv_typeparent(nq)))
nq = np;
cp = nv_name(nq);
memset(nr,0,sizeof(*nr));
nr->np = nq;
Expand Down
27 changes: 27 additions & 0 deletions src/cmd/ksh93/tests/types.sh
Original file line number Diff line number Diff line change
Expand Up @@ -851,5 +851,32 @@ exp=$'( typeset TYPEVAR )\nOK'
[[ $got == "$exp" ]] || err_exit 'type definition overriding regular built-in' \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
# ======
# As of 93u+m/1.1, _ in types always refers to the type variable, even within a member discipline function.
# Change backported from ksh 93v- 2013-07-27 and 2013-08-29.
case ${.sh.version} in
Version*93u+m/1.0* | Version*93??\ * | Version*93?\ *)
;;
*)
typeset -T argnod_discfunc_test_t=(
typeset x
integer y=5
function x.getn
{
((.sh.value = ++_.y))
typeset -p _
}
)
argnod_discfunc_test_t argnod_discfunc_obj
exp=$'typeset -n _=argnod_discfunc_obj\n6'
got=$(set +x; redirect 2>&1; print -r -- "${argnod_discfunc_obj.x}")
[[ $got == "$exp" ]] || err_exit "_ does not refer to the type variable in a member discipline function" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
got=$(set +x; redirect 2>&1; print -r -- "$((argnod_discfunc_obj.x))")
[[ $got == "$exp" ]] || err_exit "_ does not refer to the type variable in a member discipline function" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
;;
esac
# ======
exit $((Errors<125?Errors:125))

0 comments on commit b75df92

Please sign in to comment.