2009-03-22 17:55:38 +01:00
|
|
|
#include "sh.h"
|
|
|
|
|
2009-03-23 11:31:15 +01:00
|
|
|
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.3 2009/03/23 10:31:15 tg Exp $");
|
|
|
|
|
|
|
|
#ifndef SIZE_MAX
|
|
|
|
#ifdef SIZE_T_MAX
|
|
|
|
#define SIZE_MAX SIZE_T_MAX
|
|
|
|
#else
|
|
|
|
#define SIZE_MAX ((size_t)-1)
|
|
|
|
#endif
|
|
|
|
#endif
|
2009-03-22 17:55:38 +01:00
|
|
|
|
|
|
|
struct lalloc {
|
|
|
|
struct lalloc *next; /* entry pointer, must be first */
|
|
|
|
Area *group; /* group backpointer */
|
|
|
|
};
|
|
|
|
|
|
|
|
static void findptr(struct lalloc **, struct lalloc **, char *, Area *);
|
|
|
|
|
|
|
|
void
|
|
|
|
ainit(Area *ap)
|
|
|
|
{
|
|
|
|
ap->ent = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
findptr(struct lalloc **lpp, struct lalloc **ppp, char *ptr, Area *ap)
|
|
|
|
{
|
|
|
|
*lpp = (struct lalloc *)(ptr - sizeof (struct lalloc));
|
|
|
|
if ((*lpp)->group != ap)
|
|
|
|
notfound:
|
|
|
|
internal_errorf("pointer %p not in group %p", ptr, ap);
|
|
|
|
*ppp = (struct lalloc *)ap;
|
|
|
|
while ((*ppp)->next != *lpp)
|
|
|
|
if (((*ppp) = (*ppp)->next) == NULL)
|
|
|
|
goto notfound;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
aresize(void *ptr, size_t numb, Area *ap)
|
|
|
|
{
|
|
|
|
struct lalloc *lp, *pp;
|
|
|
|
|
|
|
|
if (numb >= SIZE_MAX - sizeof (struct lalloc))
|
2009-03-23 10:08:35 +01:00
|
|
|
goto failure;
|
2009-03-22 17:55:38 +01:00
|
|
|
|
|
|
|
if (ptr == NULL) {
|
|
|
|
pp = (struct lalloc *)ap;
|
|
|
|
lp = malloc(numb + sizeof (struct lalloc));
|
|
|
|
} else {
|
|
|
|
findptr(&lp, &pp, ptr, ap);
|
|
|
|
lp = realloc(lp, numb + sizeof (struct lalloc));
|
|
|
|
}
|
2009-03-23 10:08:35 +01:00
|
|
|
if (lp == NULL) {
|
|
|
|
failure:
|
|
|
|
internal_errorf("cannot allocate %lu data bytes",
|
|
|
|
(unsigned long)numb);
|
|
|
|
}
|
2009-03-22 17:55:38 +01:00
|
|
|
if (ptr == NULL) {
|
|
|
|
lp->group = ap;
|
|
|
|
lp->next = ap->ent;
|
|
|
|
}
|
|
|
|
pp->next = lp;
|
|
|
|
return ((char *)lp + sizeof (struct lalloc));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
afree(void *ptr, Area *ap)
|
|
|
|
{
|
|
|
|
struct lalloc *lp, *pp;
|
|
|
|
|
|
|
|
if (ptr == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
findptr(&lp, &pp, ptr, ap);
|
|
|
|
pp->next = lp->next;
|
|
|
|
/* lp->group = NULL; */
|
|
|
|
free(lp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
afreeall(Area *ap)
|
|
|
|
{
|
|
|
|
struct lalloc *lp;
|
|
|
|
|
|
|
|
while ((lp = ap->ent) != NULL) {
|
|
|
|
#ifndef MKSH_SMALL
|
|
|
|
if (lp->group != ap)
|
|
|
|
internal_errorf("rogue pointer in group %p", ap);
|
|
|
|
#endif
|
|
|
|
ap->ent = lp->next;
|
|
|
|
/* lp->group = NULL; */
|
|
|
|
free(lp);
|
|
|
|
}
|
|
|
|
}
|