diff options
Diffstat (limited to 'Src')
-rw-r--r-- | Src/builtin.c | 9 | ||||
-rw-r--r-- | Src/mem.c | 15 | ||||
-rw-r--r-- | Src/params.c | 29 |
3 files changed, 36 insertions, 17 deletions
diff --git a/Src/builtin.c b/Src/builtin.c index ce3aec0a2..1345b3006 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -1924,10 +1924,13 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), Param apm; char **x; if (PM_TYPE(pm->flags) == PM_ARRAY) { - x = zarrdup((*pm->gsu.a->getfn)(pm)); + x = (*pm->gsu.a->getfn)(pm); uniqarray(x); - pm->gsu.a->setfn(pm, x); - if (pm->ename && x) + if (pm->flags & PM_SPECIAL) { + if (zheapptr(x)) + x = zarrdup(x); + (*pm->gsu.a->setfn)(pm, x); + } else if (pm->ename && x) arrfixenv(pm->ename, x); } else if (PM_TYPE(pm->flags) == PM_SCALAR && pm->ename && (apm = diff --git a/Src/mem.c b/Src/mem.c index 499f7d7e4..bcdd1efe9 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -329,6 +329,21 @@ mmap_heap_alloc(size_t *n) } #endif +/* check whether a pointer is within a memory pool */ + +/**/ +mod_export void * +zheapptr(void *p) +{ + Heap h; + queue_signals(); + for (h = heaps; h; h = h->next) + if ((char *)p >= arena(h) && + (char *)p + H_ISIZE < arena(h) + ARENA_SIZEOF(h)) + break; + unqueue_signals(); + return (h ? p : 0); +} /* allocate memory from the current memory pool */ diff --git a/Src/params.c b/Src/params.c index efdb42aca..135c40f1d 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2820,11 +2820,11 @@ tiedarrsetfn(Param pm, char *x) *dptr->arrptr = sepsplit(x, sepbuf, 0, 0); if (pm->flags & PM_UNIQUE) uniqarray(*dptr->arrptr); + zsfree(x); } else *dptr->arrptr = NULL; if (pm->ename) arrfixenv(pm->nam, *dptr->arrptr); - zsfree(x); } /**/ @@ -2847,17 +2847,16 @@ tiedarrunsetfn(Param pm, UNUSED(int exp)) } /**/ -void -uniqarray(char **x) +static void +arrayuniq(char **x, int freeok) { char **t, **p = x; - if (!x || !*x) - return; while (*++p) for (t = x; t < p; t++) if (!strcmp(*p, *t)) { - zsfree(*p); + if (freeok) + zsfree(*p); for (t = p--; (*t = t[1]) != NULL; t++); break; } @@ -2865,18 +2864,20 @@ uniqarray(char **x) /**/ void -zhuniqarray(char **x) +uniqarray(char **x) { - char **t, **p = x; + if (!x || !*x) + return; + arrayuniq(x, !zheapptr(*x)); +} +/**/ +void +zhuniqarray(char **x) +{ if (!x || !*x) return; - while (*++p) - for (t = x; t < p; t++) - if (!strcmp(*p, *t)) { - for (t = p--; (*t = t[1]) != NULL; t++); - break; - } + arrayuniq(x, 0); } /* Function to get value of special parameter `#' and `ARGC' */ |