diff options
author | Bart Schaefer <schaefer@zsh.org> | 2023-09-05 18:04:09 -0700 |
---|---|---|
committer | Bart Schaefer <schaefer@zsh.org> | 2023-09-05 18:04:09 -0700 |
commit | e3c2af216b1f77202ef5240179dabcf4aab66f91 (patch) | |
tree | b78c5b8af9da519162f313aad3bd0623a136bc20 /Src/Modules | |
parent | c0caef561323b91ea0c4aa101b564f92ab51b68d (diff) | |
download | zsh-e3c2af216b1f77202ef5240179dabcf4aab66f91.tar.gz zsh-e3c2af216b1f77202ef5240179dabcf4aab66f91.tar.xz zsh-e3c2af216b1f77202ef5240179dabcf4aab66f91.zip |
52115: permit repeated "private" declarations as long as types aren't changed
Diffstat (limited to 'Src/Modules')
-rw-r--r-- | Src/Modules/param_private.c | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/Src/Modules/param_private.c b/Src/Modules/param_private.c index 8e04b2b95..7ef6633da 100644 --- a/Src/Modules/param_private.c +++ b/Src/Modules/param_private.c @@ -87,9 +87,52 @@ makeprivate(HashNode hn, UNUSED(int flags)) ((pm->node.flags & (PM_SPECIAL|PM_REMOVABLE)) == PM_SPECIAL && /* typeset_single() line 2300 discards PM_REMOVABLE -- why? */ !is_private(pm->old))))) { - zwarnnam("private", "can't change scope of existing param: %s", - pm->node.nam); - makeprivate_error = 1; + if (is_private(pm->old)) { + if (pm->old->node.flags & PM_READONLY) { + zerr("read-only variable: %s", pm->node.nam); + makeprivate_error = 1; + } else if ((pm->node.flags | pm->old->node.flags) == + pm->old->node.flags) { + /* private called twice on same parameter */ + Param tpm = pm; + pm = pm->old; + --locallevel; + /* why have a union if we need this switch anyway? */ + switch (PM_TYPE(pm->node.flags)) { + case PM_SCALAR: + pm->gsu.s->setfn(pm, tpm->u.str); + tpm->u.str = NULL; + break; + case PM_INTEGER: + pm->gsu.i->setfn(pm, tpm->u.val); + break; + case PM_EFLOAT: + case PM_FFLOAT: + pm->gsu.f->setfn(pm, tpm->u.dval); + break; + case PM_ARRAY: + pm->gsu.a->setfn(pm, tpm->u.arr); + tpm->u.arr = NULL; + break; + case PM_HASHED: + pm->gsu.h->setfn(pm, tpm->u.hash); + tpm->u.hash = NULL; + break; + } + ++locallevel; + if (!(tpm->node.flags & PM_UNSET)) + pm->node.flags &= ~PM_UNSET; + } else { + zerrnam("private", + "can't change type of private param: %s", + pm->node.nam); + makeprivate_error = 1; + } + } else { + zerrnam("private", "can't change scope of existing param: %s", + pm->node.nam); + makeprivate_error = 1; + } return; } struct gsu_closure *gsu = zalloc(sizeof(struct gsu_closure)); |