Skip to content

Expand stored nvflags from 16-bit to 64-bit#974

Open
JohnoKing wants to merge 3 commits intoksh93:devfrom
JohnoKing:expand-nvflags-v2
Open

Expand stored nvflags from 16-bit to 64-bit#974
JohnoKing wants to merge 3 commits intoksh93:devfrom
JohnoKing:expand-nvflags-v2

Conversation

@JohnoKing
Copy link
Copy Markdown

List of changes:

  • Backported the nvflag_t type from ksh2020, but changed it to uint64_t for the purpose of future-proofing nvflags expansion.
  • Moved the latter half of the nvflags into the 64-bit range. The flags can be moved back into the 32-bit range if that's desirable, but I would recommend against that. The nvflags struct member will have padding on 64-bit machines if it's 32-bit; we should just make the type 64-bit to take advantage of the otherwise unused bytes in the struct.
  • Backported a comment from ksh2020 noting that argflags are assumed to be stored as 8-bit (from ksh2020 commit 8943739).
  • Fixed a shadowing error in sh_exec namespace handling that caused nvflags to shadow the actual sh_exec() flags and thus result in the sh_exec() call getting passed invalid flags. (I'm unsure if this logic error materialized in any tangible user facing manner though.)

Change in the number of warnings on Linux when compiling with clang using -Wsign-compare -Wshorten-64-to-32 -Wsign-conversion -Wimplicit-int-conversion: 37 => 1

Fixes att#1038

List of changes:
- Backported the nvflag_t type from ksh2020, but changed it to
  uint64_t for the purpose of future-proofing nvflags expansion.
- Moved the latter half of the nvflags into the 64-bit range.
  The flags can be moved back into the 32-bit range if that's
  desirable, but I would recommend against that. The nvflags
  struct member will have padding on 64-bit machines if it's
  32-bit; we should just make the type 64-bit to take advantage
  of the otherwise unutilized bytes in the struct.
- Backport a comment from ksh2020 noting that argflags are assumed to
  be stored as 8-bit (from ksh2020 commit 8943739).
- Fix shadowing error in sh_exec namespace handling that caused nvflags
  to shadow the actual sh_exec flags and thus result in the sh_exec
  call getting passed invalid flags. (I'm unsure if this logic error
  materialized in any tangible user facing manner though.)

Change in the number of warnings on Linux when compiling with clang
using -Wsign-compare -Wshorten-64-to-32 -Wsign-conversion
-Wimplicit-int-conversion: 37 => 1

Fixes att#1038
NV_FPOSIX is passed along to sh_deparse, which is in 32-bits
but is usually stored in 64-bit nvflag_t.
@McDutchie
Copy link
Copy Markdown

This all seems quite sensible. Future-proofing is good.

I was concerned that using a 64-bit nvflag might cause a performance regression on 32-bit systems, but I did a shbench test before and after this PR on Slackware 15.0 i386, and found no significant difference.

I think it's still less than ideal that option bitmasks for nv_open and sh_macexpand are mixed in with nvflags and argflags respectively, but that's for some possible future commit to deal with.

@McDutchie
Copy link
Copy Markdown

Fixed a shadowing error in sh_exec namespace handling that caused nvflags to shadow the actual sh_exec() flags and thus result in the sh_exec() call getting passed invalid flags. (I'm unsure if this logic error materialized in any tangible user facing manner though.)

What is the specific change in this PR that fixes this problem?

@JohnoKing
Copy link
Copy Markdown
Author

The isolated change (with the affected sh_exec() call):

--- a/src/cmd/ksh93/sh/xec.c
+++ b/src/cmd/ksh93/sh/xec.c
@@ -2300,7 +2301,7 @@ int sh_exec(const Shnode_t *t, int flags)
 				Dt_t *root;
 				Namval_t *oldnspace = sh.namespace;
 				ptrdiff_t offset = stktell(sh.stk);
-				int	flags=NV_NOARRAY|NV_VARNAME;
+				nvflag_t nvflgs =NV_NOARRAY|NV_VARNAME;
 				struct checkpt *chkp = stkalloc(sh.stk,sizeof(struct checkpt));
 				int jmpval;
 				if(cp)
@@ -2315,7 +2316,7 @@ int sh_exec(const Shnode_t *t, int flags)
 				}
 				sfputc(sh.stk,'.');
 				sfputr(sh.stk,fname,0);
-				np = nv_open(stkptr(sh.stk,offset),sh.var_tree,flags);
+				np = nv_open(stkptr(sh.stk,offset),sh.var_tree,nvflgs);
 				offset = stktell(sh.stk);
 				if(nv_istable(np))
 					root = nv_dict(np);

ksh/src/cmd/ksh93/sh/xec.c

Lines 2333 to 2334 in 94b5851

if(!jmpval)
sh_exec(t->for_.fortre,flags|sh_state(SH_ERREXIT));

@McDutchie
Copy link
Copy Markdown

Merging this has been delayed somewhat because I need to test the changes on the 1.0 branch for potential complications involving handling of the magic A__z env var that transparently imports and exports attributes through the environment. That misfeature has been removed from the dev branch but is kept on the 1.0 branch for backward compatibility with AT&T ksh93 and ksh88. See env_import_attributes() in init.c and sh_envgen() in name.c on the 1.0 branch.

The attributes are encoded in the env var by taking their binary value, typecast to int, and adding the ASCII value of a space to it. So, it's important that the values of NV_UTOL, NV_LTOU, NV_RJUST, NV_LJUST, NV_ZFILL, NV_INTEGER, and NV_RDONLY, and the macros that combine bit values of these, don't change as long as we still support the 1.0 branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Changing size of nvflag in struct Namval breaks things

2 participants