From eeb9ec471493312d44588026c18bd5440a3fd1eb Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 24 Sep 2003 14:55:32 +0000 Subject: 19129: extra argument to typeset -T gives character for joining array --- Src/builtin.c | 41 ++++++++++++++++++++++++------- Src/params.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ Src/utils.c | 22 ++++++++++++++--- Src/zsh.h | 26 ++++++++++++-------- 4 files changed, 137 insertions(+), 31 deletions(-) (limited to 'Src') 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,21 +2595,76 @@ 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" -- cgit 1.4.1