Add “unset foo[*]” mksh extension, which allows to unset the *contents*
of foo[0] (but not its attributes), and the rest of the array, so that later “set +A foo bar” will set foo[0]=bar but retain the attributes. This is important, because, in the future, arrays will have different attributes per element, instead of all the same (which, actually, is not entirely true right now either, since “unset foo[0]” will not mo- dify the attributes of a foo[1] existing at that point in time), where foo[$newkey] will inherit from foo[0], but typeset foo will only affect foo[0] no longer foo[*] in the future. (The rules about typeset=local will still apply, as they affect creation of variables in a scope.)
This commit is contained in:
parent
1ac42c1c1c
commit
c700693d11
79
check.t
79
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.354 2010/01/08 22:21:03 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.355 2010/01/25 14:11:25 tg Exp $
|
||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||
@ -5224,6 +5224,83 @@ expected-stdout:
|
||||
!arz[0]:
|
||||
!arz[1]:
|
||||
---
|
||||
name: arrays-8
|
||||
description:
|
||||
Check some behavioural rules for arrays.
|
||||
stdin:
|
||||
fna() {
|
||||
set -A aa 9
|
||||
}
|
||||
fnb() {
|
||||
typeset ab
|
||||
set -A ab 9
|
||||
}
|
||||
fnc() {
|
||||
typeset ac
|
||||
set -A ac 91
|
||||
unset ac
|
||||
set -A ac 92
|
||||
}
|
||||
fnd() {
|
||||
set +A ad 9
|
||||
}
|
||||
fne() {
|
||||
unset ae
|
||||
set +A ae 9
|
||||
}
|
||||
fnf() {
|
||||
unset af[0]
|
||||
set +A af 9
|
||||
}
|
||||
fng() {
|
||||
unset ag[*]
|
||||
set +A ag 9
|
||||
}
|
||||
set -A aa 1 2
|
||||
set -A ab 1 2
|
||||
set -A ac 1 2
|
||||
set -A ad 1 2
|
||||
set -A ae 1 2
|
||||
set -A af 1 2
|
||||
set -A ag 1 2
|
||||
typeset -Z3 aa ab ac ad ae af ag
|
||||
print 1a ${aa[*]} .
|
||||
print 1b ${ab[*]} .
|
||||
print 1c ${ac[*]} .
|
||||
print 1d ${ad[*]} .
|
||||
print 1e ${ae[*]} .
|
||||
print 1f ${af[*]} .
|
||||
print 1g ${ag[*]} .
|
||||
fna
|
||||
fnb
|
||||
fnc
|
||||
fnd
|
||||
fne
|
||||
fnf
|
||||
fng
|
||||
print 2a ${aa[*]} .
|
||||
print 2b ${ab[*]} .
|
||||
print 2c ${ac[*]} .
|
||||
print 2d ${ad[*]} .
|
||||
print 2e ${ae[*]} .
|
||||
print 2f ${af[*]} .
|
||||
print 2g ${ag[*]} .
|
||||
expected-stdout:
|
||||
1a 001 002 .
|
||||
1b 001 002 .
|
||||
1c 001 002 .
|
||||
1d 001 002 .
|
||||
1e 001 002 .
|
||||
1f 001 002 .
|
||||
1g 001 002 .
|
||||
2a 9 .
|
||||
2b 001 002 .
|
||||
2c 92 .
|
||||
2d 009 002 .
|
||||
2e 9 .
|
||||
2f 9 002 .
|
||||
2g 009 .
|
||||
---
|
||||
name: varexpand-substr-1
|
||||
description:
|
||||
Check if bash-style substring expansion works
|
||||
|
24
funcs.c
24
funcs.c
@ -4,7 +4,7 @@
|
||||
/* $OpenBSD: c_ulimit.c,v 1.17 2008/03/21 12:51:19 millert Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
* Thorsten Glaser <tg@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.147 2009/12/12 22:27:07 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.148 2010/01/25 14:11:26 tg Exp $");
|
||||
|
||||
#if HAVE_KILLPG
|
||||
/*
|
||||
@ -1666,7 +1666,7 @@ c_getopts(const char **wp)
|
||||
if (voptarg->flag & INTEGER)
|
||||
typeset("OPTARG", 0, INTEGER, 0, 0);
|
||||
if (user_opt.optarg == NULL)
|
||||
unset(voptarg, 0);
|
||||
unset(voptarg, 1);
|
||||
else
|
||||
/* This can't fail (have cleared readonly/integer) */
|
||||
setstr(voptarg, user_opt.optarg, KSH_RETURN_ERROR);
|
||||
@ -2397,13 +2397,27 @@ c_unset(const char **wp)
|
||||
wp += builtin_opt.optind;
|
||||
for (; (id = *wp) != NULL; wp++)
|
||||
if (unset_var) { /* unset variable */
|
||||
struct tbl *vp = global(id);
|
||||
struct tbl *vp;
|
||||
char *cp = NULL;
|
||||
size_t n;
|
||||
|
||||
n = strlen(id);
|
||||
if (n > 3 && id[n-3] == '[' && id[n-2] == '*' &&
|
||||
id[n-1] == ']') {
|
||||
strndupx(cp, id, n - 3, ATEMP);
|
||||
id = cp;
|
||||
optc = 3;
|
||||
} else
|
||||
optc = vstrchr(id, '[') ? 0 : 1;
|
||||
|
||||
vp = global(id);
|
||||
afree(cp, ATEMP);
|
||||
|
||||
if ((vp->flag&RDONLY)) {
|
||||
bi_errorf("%s is read only", vp->name);
|
||||
return (1);
|
||||
}
|
||||
unset(vp, vstrchr(id, '[') ? 1 : 0);
|
||||
unset(vp, optc);
|
||||
} else /* unset function */
|
||||
define(id, NULL);
|
||||
return (0);
|
||||
|
7
mksh.1
7
mksh.1
@ -1,4 +1,4 @@
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.206 2010/01/08 22:21:05 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.207 2010/01/25 14:11:27 tg Exp $
|
||||
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
|
||||
.\"-
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
@ -71,7 +71,7 @@
|
||||
.\" with -mandoc, it might implement .Mx itself, but we want to
|
||||
.\" use our own definition. And .Dd must come *first*, always.
|
||||
.\"
|
||||
.Dd $Mdocdate: January 8 2010 $
|
||||
.Dd $Mdocdate: January 25 2010 $
|
||||
.\"
|
||||
.\" Check which macro package we use
|
||||
.\"
|
||||
@ -4652,6 +4652,9 @@ the default
|
||||
.Pc
|
||||
or functions
|
||||
.Pq Fl f .
|
||||
With
|
||||
.Ar parameter Ns [*] ,
|
||||
attributes are kept, only values are unset.
|
||||
.Pp
|
||||
.It Ic wait Op Ar job ...
|
||||
Wait for the specified job(s) to finish.
|
||||
|
22
var.c
22
var.c
@ -1,7 +1,7 @@
|
||||
/* $OpenBSD: var.c,v 1.34 2007/10/15 02:16:35 deraadt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
* Thorsten Glaser <tg@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.100 2009/12/05 17:43:50 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.101 2010/01/25 14:11:29 tg Exp $");
|
||||
|
||||
/*
|
||||
* Variables
|
||||
@ -834,15 +834,17 @@ typeset(const char *var, Tflag set, Tflag clr, int field, int base)
|
||||
return (vp);
|
||||
}
|
||||
|
||||
/* Unset a variable. array_ref is set if there was an array reference in
|
||||
* the name lookup (eg, x[2]).
|
||||
/**
|
||||
* Unset a variable. The flags can be:
|
||||
* |1 = tear down entire array
|
||||
* |2 = keep attributes, only unset content
|
||||
*/
|
||||
void
|
||||
unset(struct tbl *vp, int array_ref)
|
||||
unset(struct tbl *vp, int flags)
|
||||
{
|
||||
if (vp->flag & ALLOC)
|
||||
afree(vp->val.s, vp->areap);
|
||||
if ((vp->flag & ARRAY) && !array_ref) {
|
||||
if ((vp->flag & ARRAY) && (flags & 1)) {
|
||||
struct tbl *a, *tmp;
|
||||
|
||||
/* Free up entire array */
|
||||
@ -855,8 +857,12 @@ unset(struct tbl *vp, int array_ref)
|
||||
}
|
||||
vp->u.array = NULL;
|
||||
}
|
||||
if (flags & 2) {
|
||||
vp->flag &= ~(ALLOC|ISSET);
|
||||
return;
|
||||
}
|
||||
/* If foo[0] is being unset, the remainder of the array is kept... */
|
||||
vp->flag &= SPECIAL | (array_ref ? ARRAY|DEFINED : 0);
|
||||
vp->flag &= SPECIAL | ((flags & 1) ? 0 : ARRAY|DEFINED);
|
||||
if (vp->flag & SPECIAL)
|
||||
unsetspec(vp); /* responsible for 'unspecial'ing var */
|
||||
}
|
||||
@ -1363,7 +1369,7 @@ set_array(const char *var, bool reset, const char **vals)
|
||||
/* This code is quite non-optimal */
|
||||
if (reset)
|
||||
/* trash existing values and attributes */
|
||||
unset(vp, 0);
|
||||
unset(vp, 1);
|
||||
/* todo: would be nice for assignment to completely succeed or
|
||||
* completely fail. Only really effects integer arrays:
|
||||
* evaluation of some of vals[] may fail...
|
||||
|
Loading…
x
Reference in New Issue
Block a user