summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2003-09-24 14:55:32 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2003-09-24 14:55:32 +0000
commiteeb9ec471493312d44588026c18bd5440a3fd1eb (patch)
tree6bc698feb429c899daa9b15a6cb9a54bef8b72a1
parent0c82828e8679105adcb53765f8a65f666b08f7c4 (diff)
downloadzsh-eeb9ec471493312d44588026c18bd5440a3fd1eb.tar.gz
zsh-eeb9ec471493312d44588026c18bd5440a3fd1eb.zip
19129: extra argument to typeset -T gives character for joining array
-rw-r--r--ChangeLog4
-rw-r--r--Doc/Zsh/builtins.yo34
-rw-r--r--Src/builtin.c41
-rw-r--r--Src/params.c79
-rw-r--r--Src/utils.c22
-rw-r--r--Src/zsh.h26
6 files changed, 160 insertions, 46 deletions
diff --git a/ChangeLog b/ChangeLog
index 25c4157b6..e24c905b9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2003-09-24 Peter Stephenson <pws@csr.com>
+ * 19129: Doc/Zsh/builtins.yo, Src/builtin.c, Src/params.c,
+ Src/utils.c, Src/zsh.h: extra tie arguemnt in
+ "typeset -T PAGER pager ' '" used for joining and splitting.
+
* unposted: Completion/Unix/Command/_perforce: improve handling
of label completion: now faster and uses filename to narrow
range if after `@'.
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index b5217abaf..3f6f3c450 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -1160,7 +1160,7 @@ cindex(parameters, declaring)
xitem(tt(typeset) [ {tt(PLUS())|tt(-)}tt(AEFHLRUZafghilprtuxm) [var(n)]] [ \
var(name)[tt(=)var(value)] ... ])
item(tt(typeset) -T [ {tt(PLUS()|tt(-))}tt(LRUZrux) ] \
- var(SCALAR)[tt(=)var(value)] var(array))(
+ var(SCALAR)[tt(=)var(value)] var(array) tt([) var(sep) tt(]))(
Set or display attributes and values for shell parameters.
A parameter is created for each var(name) that does not already refer
@@ -1189,20 +1189,24 @@ separately for arrays and associative arrays), regardless of other flags
and options. Note that the tt(-h) flag on parameters is respected; no
value will be shown for these parameters.
-If the tt(-T) option is given, exactly two (or zero) var(name)
-arguments must be present. They represent a scalar and an array (in
-that order) that will be tied together in the manner of tt($PATH) and
-tt($path). In other words, an array present in the latter variable
-appears as a scalar with the elements of the array joined by colons in
-the former. Only the scalar may have an initial value. Both the
-scalar and the array may otherwise be manipulated as normal. If one
-is unset, the other will automatically be unset too. There is no way
-of untying the variables without unsetting them, or converting the
-type of one of them with another tt(typeset) command; tt(+T) does not
-work, assigning an array to var(SCALAR) is an error, and assigning a
-scalar to var(array) sets it to be a single-element array. Note that
-both `tt(typeset -xT ...)' and `tt(export -T ...)' work, but only the
-scalar will be marked for export.
+If the tt(-T) option is given, two or three arguments must be present (an
+exception is that zero arguments are allowed to show the list of parameters
+created in this fashion). The first two are the name of a scalar and an
+array parameter (in that order) that will be tied together in the manner of
+tt($PATH) and tt($path). The optional third argument is a single-character
+separator which will be used to join the elements of the array to form the
+scalar; if absent, a colon is used, as with tt($PATH). Only the first
+character of the separator is significant; any remaining characters are
+ignored. Only the scalar parameter may be assigned an initial value. Both
+the scalar and the array may otherwise be manipulated as normal. If one is
+unset, the other will automatically be unset too. There is no way of
+untying the variables without unsetting them, or converting the type of one
+of them with another tt(typeset) command; tt(+T) does not work, assigning
+an array to var(SCALAR) is an error, and assigning a scalar to var(array)
+sets it to be a single-element array. Note that both `tt(typeset -xT ...)'
+and `tt(export -T ...)' work, but only the scalar will be marked for
+export. Setting the value using the scalar version causes a split on all
+separators (which cannot be quoted).
The tt(-g) (global) flag is treated specially: it means that any
resulting parameter will not be restricted to local scope. Note that this
diff --git a/Src/builtin.c b/Src/builtin.c
index 62426facb..988a342fd 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -1677,7 +1677,7 @@ enum {
static Param
typeset_single(char *cname, char *pname, Param pm, int func,
int on, int off, int roff, char *value, Param altpm,
- Options ops, int auxlen)
+ Options ops, int auxlen, int joinchar)
{
int usepm, tc, keeplocal = 0, newspecial = NS_NONE, readonly;
char *subscript;
@@ -1997,9 +1997,17 @@ typeset_single(char *cname, char *pname, Param pm, int func,
* to make sure we only ever use the colonarr functions
* when u.data is correctly set.
*/
- pm->sets.cfn = colonarrsetfn;
- pm->gets.cfn = colonarrgetfn;
- pm->u.data = &altpm->u.arr;
+ struct tieddata *tdp = (struct tieddata *)
+ zalloc(sizeof(struct tieddata));
+ if (!tdp)
+ return NULL;
+ tdp->joinchar = joinchar;
+ tdp->arrptr = &altpm->u.arr;
+
+ pm->sets.cfn = tiedarrsetfn;
+ pm->gets.cfn = tiedarrgetfn;
+ pm->unsetfn = tiedarrunsetfn;
+ pm->u.data = tdp;
}
if (keeplocal)
@@ -2155,6 +2163,7 @@ bin_typeset(char *name, char **argv, Options ops, int func)
Param apm;
struct asgment asg0;
char *oldval = NULL;
+ int joinchar;
if (OPT_ISSET(ops,'m')) {
zwarnnam(name, "incompatible options for -T", NULL, 0);
@@ -2162,12 +2171,25 @@ bin_typeset(char *name, char **argv, Options ops, int func)
return 1;
}
on &= ~off;
- if (!argv[1] || argv[2]) {
+ if (!argv[1] || argv[3]) {
zwarnnam(name, "-T requires names of scalar and array", NULL, 0);
unqueue_signals();
return 1;
}
+ /*
+ * Third argument, if given, is character used to join
+ * the elements of the array in the scalar.
+ */
+ if (!argv[2])
+ joinchar = ':';
+ else if (!*argv[2])
+ joinchar = 0;
+ else if (*argv[2] == Meta)
+ joinchar = argv[2][1] ^ 32;
+ else
+ joinchar = *argv[2];
+
if (!(asg = getasg(argv[0]))) {
unqueue_signals();
return 1;
@@ -2212,7 +2234,8 @@ bin_typeset(char *name, char **argv, Options ops, int func)
(Param)paramtab->getnode(paramtab,
asg->name),
func, (on | PM_ARRAY) & ~PM_EXPORTED,
- off, roff, asg->value, NULL, ops, auxlen))) {
+ off, roff, asg->value, NULL, ops, auxlen,
+ 0))) {
unqueue_signals();
return 1;
}
@@ -2224,7 +2247,7 @@ bin_typeset(char *name, char **argv, Options ops, int func)
(Param)paramtab->getnode(paramtab,
asg0.name),
func, on, off, roff, asg0.value, apm,
- ops, auxlen))) {
+ ops, auxlen, joinchar))) {
if (oldval)
zsfree(oldval);
unsetparam_pm(apm, 1, 1);
@@ -2291,7 +2314,7 @@ bin_typeset(char *name, char **argv, Options ops, int func)
for (pmnode = firstnode(pmlist); pmnode; incnode(pmnode)) {
pm = (Param) getdata(pmnode);
if (!typeset_single(name, pm->nam, pm, func, on, off, roff,
- asg->value, NULL, ops, auxlen))
+ asg->value, NULL, ops, auxlen, 0))
returnval = 1;
}
}
@@ -2306,7 +2329,7 @@ bin_typeset(char *name, char **argv, Options ops, int func)
gethashnode2(paramtab, asg->name) :
paramtab->getnode(paramtab, asg->name)),
func, on, off, roff, asg->value, NULL,
- ops, auxlen))
+ ops, auxlen, 0))
returnval = 1;
}
unqueue_signals();
diff --git a/Src/params.c b/Src/params.c
index a4890bcb0..079378180 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -2595,22 +2595,77 @@ void
colonarrsetfn(Param pm, char *x)
{
char ***dptr = (char ***)pm->u.data;
-
/*
- * If this is tied to a parameter (rather than internal) array,
- * the array itself may be NULL. Otherwise, we have to make
- * sure it doesn't ever get null.
+ * We have to make sure this is never NULL, since that
+ * can cause problems.
*/
if (*dptr)
freearray(*dptr);
- *dptr = x ? colonsplit(x, pm->flags & PM_UNIQUE) :
- (pm->flags & PM_TIED) ? NULL : mkarray(NULL);
+ if (x)
+ *dptr = colonsplit(x, pm->flags & PM_UNIQUE);
+ else
+ *dptr = mkarray(NULL);
if (pm->ename)
arrfixenv(pm->nam, *dptr);
zsfree(x);
}
/**/
+char *
+tiedarrgetfn(Param pm)
+{
+ struct tieddata *dptr = (struct tieddata *)pm->u.data;
+ return *dptr->arrptr ? zjoin(*dptr->arrptr, dptr->joinchar, 1) : "";
+}
+
+/**/
+void
+tiedarrsetfn(Param pm, char *x)
+{
+ struct tieddata *dptr = (struct tieddata *)pm->u.data;
+
+ if (*dptr->arrptr)
+ freearray(*dptr->arrptr);
+ if (x) {
+ char sepbuf[3];
+ if (imeta(dptr->joinchar))
+ {
+ sepbuf[0] = Meta;
+ sepbuf[1] = dptr->joinchar;
+ sepbuf[2] = '\0';
+ }
+ else
+ {
+ sepbuf[0] = dptr->joinchar;
+ sepbuf[1] = '\0';
+ }
+ *dptr->arrptr = sepsplit(x, sepbuf, 0, 0);
+ if (pm->flags & PM_UNIQUE)
+ uniqarray(*dptr->arrptr);
+ } else
+ *dptr->arrptr = NULL;
+ if (pm->ename)
+ arrfixenv(pm->nam, *dptr->arrptr);
+ zsfree(x);
+}
+
+/**/
+void
+tiedarrunsetfn(Param pm, int exp)
+{
+ /*
+ * Special unset function because we allocated a struct tieddata
+ * in typeset_single to hold the special data which we now
+ * need to delete.
+ */
+ pm->sets.cfn(pm, NULL);
+ zfree(pm->u.data, sizeof(struct tieddata));
+ /* paranoia -- shouldn't need these, but in case we reuse the struct... */
+ pm->u.data = NULL;
+ pm->flags &= ~PM_TIED;
+}
+
+/**/
void
uniqarray(char **x)
{
@@ -3187,6 +3242,7 @@ void
arrfixenv(char *s, char **t)
{
Param pm;
+ int joinchar;
if (t == path)
cmdnamtab->emptytable(cmdnamtab);
@@ -3208,8 +3264,15 @@ arrfixenv(char *s, char **t)
* Do not "fix" parameters that were not exported
*/
- if (pm->flags & PM_EXPORTED)
- pm->env = addenv(s, t ? zjoin(t, ':', 1) : "", pm->flags);
+ if (!(pm->flags & PM_EXPORTED))
+ return;
+
+ if (pm->flags & PM_TIED)
+ joinchar = ((struct tieddata *)pm->u.data)->joinchar;
+ else
+ joinchar = ':';
+
+ pm->env = addenv(s, t ? zjoin(t, joinchar, 1) : "", pm->flags);
}
diff --git a/Src/utils.c b/Src/utils.c
index 0d9f9f9c3..56230fddb 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1793,14 +1793,20 @@ zjoin(char **arr, int delim, int heap)
char **s, *ret, *ptr;
for (s = arr; *s; s++)
- len += strlen(*s) + 1;
+ len += strlen(*s) + 1 + (imeta(delim) ? 1 : 0);
if (!len)
return heap? "" : ztrdup("");
ptr = ret = (heap ? (char *) hcalloc(len) : (char *) zcalloc(len));
for (s = arr; *s; s++) {
strucpy(&ptr, *s);
- if (delim)
- *ptr++ = delim;
+ if (delim) {
+ if (imeta(delim)) {
+ *ptr++ = Meta;
+ *ptr++ = delim ^ 32;
+ }
+ else
+ *ptr++ = delim;
+ }
}
ptr[-1] = '\0';
return ret;
@@ -1856,7 +1862,15 @@ skipwsep(char **s)
return i;
}
-/* see findsep() below for handling of `quote' argument */
+/*
+ * haven't worked out what allownull does; it's passed down from
+ * sepsplit but all the cases it's used are either 0 or 1 without
+ * a comment. it seems to be something to do with the `nulstring'
+ * which i think is some kind of a metafication thing, so probably
+ * allownull's value is associated with whether we are using
+ * metafied strings.
+ * see findsep() below for handling of `quote' argument
+ */
/**/
mod_export char **
diff --git a/Src/zsh.h b/Src/zsh.h
index 2dca01722..158717dea 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1156,6 +1156,12 @@ struct param {
int level; /* if (old != NULL), level of localness */
};
+/* structure stored in struct param's u.data by tied arrays */
+struct tieddata {
+ char ***arrptr; /* pointer to corresponding array */
+ int joinchar; /* character used to join arrays */
+};
+
/* flags for parameters */
/* parameter types */
@@ -1193,16 +1199,16 @@ struct param {
#define PM_TIED (1<<16) /* array tied to colon-path or v.v. */
/* Remaining flags do not correspond directly to command line arguments */
-#define PM_LOCAL (1<<17) /* this parameter will be made local */
-#define PM_SPECIAL (1<<18) /* special builtin parameter */
-#define PM_DONTIMPORT (1<<19) /* do not import this variable */
-#define PM_RESTRICTED (1<<20) /* cannot be changed in restricted mode */
-#define PM_UNSET (1<<21) /* has null value */
-#define PM_REMOVABLE (1<<22) /* special can be removed from paramtab */
-#define PM_AUTOLOAD (1<<23) /* autoloaded from module */
-#define PM_NORESTORE (1<<24) /* do not restore value of local special */
-#define PM_HASHELEM (1<<25) /* is a hash-element */
-#define PM_NAMEDDIR (1<<26) /* has a corresponding nameddirtab entry */
+#define PM_LOCAL (1<<21) /* this parameter will be made local */
+#define PM_SPECIAL (1<<22) /* special builtin parameter */
+#define PM_DONTIMPORT (1<<23) /* do not import this variable */
+#define PM_RESTRICTED (1<<24) /* cannot be changed in restricted mode */
+#define PM_UNSET (1<<25) /* has null value */
+#define PM_REMOVABLE (1<<26) /* special can be removed from paramtab */
+#define PM_AUTOLOAD (1<<27) /* autoloaded from module */
+#define PM_NORESTORE (1<<28) /* do not restore value of local special */
+#define PM_HASHELEM (1<<29) /* is a hash-element */
+#define PM_NAMEDDIR (1<<30) /* has a corresponding nameddirtab entry */
/* The option string corresponds to the first of the variables above */
#define TYPESET_OPTSTR "aiEFALRZlurtxUhHT"