summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/builtin.c9
-rw-r--r--Src/mem.c15
-rw-r--r--Src/params.c29
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' */