dns_zone_detach(&zone);
}
if (zoneconf != NULL) {
- cfg_obj_destroy(cfg->add_parser, &zoneconf);
+ cfg_obj_destroy(&zoneconf);
}
if (dnsforwarders != NULL) {
dns_forwarders_detach(&dnsforwarders);
cleanup:
if (zoneconf != NULL) {
- cfg_obj_destroy(cfg->add_parser, &zoneconf);
+ cfg_obj_destroy(&zoneconf);
}
dns_zone_detach(&zone);
cleanup:
if (zoneconf != NULL) {
- cfg_obj_destroy(named_g_addparser, &zoneconf);
+ cfg_obj_destroy(&zoneconf);
}
return result;
/*
* Destroy the configuration object created in this iteration.
*/
- cfg_obj_destroy(named_g_addparser, &zconfigobj);
+ cfg_obj_destroy(&zconfigobj);
}
if (text != NULL) {
isc_buffer_free(&text);
}
if (zconfigobj != NULL) {
- cfg_obj_destroy(named_g_addparser, &zconfigobj);
+ cfg_obj_destroy(&zconfigobj);
}
mdb_cursor_close(cursor);
UNLOCK(&view->new_zone_lock);
if (zoneconf != NULL) {
- cfg_obj_destroy(named_g_addparser, &zoneconf);
+ cfg_obj_destroy(&zoneconf);
}
if (text != NULL) {
isc_buffer_free(&text);
cleanup:
if (bindkeys != NULL) {
- cfg_obj_destroy(parser, &bindkeys);
+ cfg_obj_destroy(&bindkeys);
}
if (config != NULL) {
- cfg_obj_destroy(parser, &config);
+ cfg_obj_destroy(&config);
}
cfg_parser_destroy(&parser);
cfg_aclconfctx_detach(&server->aclctx);
}
- cfg_obj_destroy(named_g_parser, &named_g_defaultconfig);
+ cfg_obj_destroy(&named_g_defaultconfig);
cfg_parser_destroy(&named_g_parser);
cfg_parser_destroy(&named_g_addparser);
}
if (nzf_config != NULL) {
- cfg_obj_destroy(named_g_addparser, &nzf_config);
+ cfg_obj_destroy(&nzf_config);
}
return result;
cleanup:
if (zoneconf != NULL) {
- cfg_obj_destroy(named_g_addparser, &zoneconf);
+ cfg_obj_destroy(&zoneconf);
}
if (view != NULL) {
dns_view_detach(&view);
e = UNCONST(elt);
ISC_LIST_UNLINK(*list, e, link);
- cfg_obj_destroy(pctx, &e->obj);
+ cfg_obj_destroy(&e->obj);
isc_mem_put(pctx->mctx, e, sizeof(*e));
result = ISC_R_SUCCESS;
break;
(void)putnull(text);
}
if (zoneconf != NULL) {
- cfg_obj_destroy(named_g_addparser, &zoneconf);
+ cfg_obj_destroy(&zoneconf);
}
if (view != NULL) {
dns_view_detach(&view);
cleanup:
#ifdef HAVE_LMDB
if (nzconfig != NULL) {
- cfg_obj_destroy(named_g_addparser, &nzconfig);
+ cfg_obj_destroy(&nzconfig);
}
#endif /* HAVE_LMDB */
if (isc_buffer_usedlength(*text) > 0) {
if (cfg->conf_parser != NULL) {
if (cfg->config != NULL) {
- cfg_obj_destroy(cfg->conf_parser, &cfg->config);
+ cfg_obj_destroy(&cfg->config);
}
if (cfg->vconfig != NULL) {
- cfg_obj_destroy(cfg->conf_parser, &cfg->vconfig);
+ cfg_obj_destroy(&cfg->vconfig);
}
cfg_parser_destroy(&cfg->conf_parser);
}
if (cfg->add_parser != NULL) {
if (cfg->nzf_config != NULL) {
- cfg_obj_destroy(cfg->add_parser, &cfg->nzf_config);
+ cfg_obj_destroy(&cfg->nzf_config);
}
cfg_parser_destroy(&cfg->add_parser);
}
} while (0)
/*% Clean up a configuration object if non-NULL. */
-#define CLEANUP_OBJ(obj) \
- do { \
- if ((obj) != NULL) \
- cfg_obj_destroy(pctx, &(obj)); \
+#define CLEANUP_OBJ(obj) \
+ do { \
+ if ((obj) != NULL) \
+ cfg_obj_destroy(&(obj)); \
} while (0)
/*%
strcasecmp(TOKEN_STRING(pctx), "local") == 0)
{
cfg_obj_t *obj = NULL;
- CHECK(cfg_create_obj(pctx, &cfg_type_ustring, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_ustring, &obj));
obj->value.string.length = strlen("local");
obj->value.string.base =
isc_mem_get(pctx->mctx, obj->value.string.length + 1);
if (pctx->token.type == isc_tokentype_string &&
strcasecmp(TOKEN_STRING(pctx), "none") == 0)
{
- return cfg_create_obj(pctx, &cfg_type_none, ret);
+ return cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_none, ret);
}
cfg_ungettoken(pctx);
return cfg_parse_qstring(pctx, type, ret);
if (pctx->token.type == isc_tokentype_string &&
strcasecmp(TOKEN_STRING(pctx), "auto") == 0)
{
- return cfg_create_obj(pctx, &cfg_type_auto, ret);
+ return cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_auto, ret);
}
cfg_ungettoken(pctx);
return cfg_parse_boolean(pctx, type, ret);
if (pctx->token.type == isc_tokentype_string &&
strcasecmp(TOKEN_STRING(pctx), "none") == 0)
{
- return cfg_create_obj(pctx, &cfg_type_none, ret);
+ return cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_none, ret);
}
if (pctx->token.type == isc_tokentype_string &&
strcasecmp(TOKEN_STRING(pctx), "hostname") == 0)
{
- result = cfg_create_obj(pctx, &cfg_type_hostname, ret);
+ result = cfg_create_obj(pctx->mctx,
+ cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_hostname, ret);
if (result == ISC_R_SUCCESS) {
(*ret)->value.boolean = true;
}
}
CHECK(parse_unitstring(TOKEN_STRING(pctx), &val));
- CHECK(cfg_create_obj(pctx, &cfg_type_uint64, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_uint64, &obj));
obj->value.uint64 = val;
*ret = obj;
return ISC_R_SUCCESS;
percent = strtoull(TOKEN_STRING(pctx), &endp, 10);
if (*endp == '%' && *(endp + 1) == 0) {
- CHECK(cfg_create_obj(pctx, &cfg_type_percentage, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_percentage, &obj));
obj->value.uint32 = (uint32_t)percent;
*ret = obj;
return ISC_R_SUCCESS;
} else {
CHECK(parse_unitstring(TOKEN_STRING(pctx), &val));
- CHECK(cfg_create_obj(pctx, &cfg_type_uint64, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_uint64, &obj));
obj->value.uint64 = val;
*ret = obj;
return ISC_R_SUCCESS;
strcasecmp(TOKEN_STRING(pctx), "none") == 0)
{
CHECK(cfg_gettoken(pctx, 0));
- CHECK(cfg_create_obj(pctx, &cfg_type_none, ret));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_none, ret));
} else {
CHECK(cfg_parse_sockaddr_generic(pctx, &cfg_type_querysource,
type, ret));
* This makes little sense, but we support it for
* compatibility with BIND 8.
*/
- CHECK(cfg_create_obj(pctx, &cfg_type_uint32, ret));
+ CHECK(cfg_create_obj(
+ pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_uint32, ret));
(*ret)->value.uint32 = 1;
}
(*ret)->type = &cfg_type_debuglevel; /* XXX kludge */
} while (0)
/* Clean up a configuration object if non-NULL. */
-#define CLEANUP_OBJ(obj) \
- do { \
- if ((obj) != NULL) \
- cfg_obj_destroy(pctx, &(obj)); \
+#define CLEANUP_OBJ(obj) \
+ do { \
+ if ((obj) != NULL) \
+ cfg_obj_destroy(&(obj)); \
} while (0)
+/* cfg_obj_t magic number */
+#define CFGOBJ_MAGIC ISC_MAGIC('c', 'f', 'g', 'o')
+
/*
* Forward declarations of static functions.
*/
static void
-free_tuple(cfg_parser_t *pctx, cfg_obj_t *obj);
+free_tuple(cfg_obj_t *obj);
static isc_result_t
parse_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
print_list(cfg_printer_t *pctx, const cfg_obj_t *obj);
static void
-free_list(cfg_parser_t *pctx, cfg_obj_t *obj);
+free_list(cfg_obj_t *obj);
static isc_result_t
create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp);
cfg_obj_t **ret);
static void
-free_string(cfg_parser_t *pctx, cfg_obj_t *obj);
+free_string(cfg_obj_t *obj);
static void
-free_sockaddrtls(cfg_parser_t *pctx, cfg_obj_t *obj);
+free_sockaddrtls(cfg_obj_t *obj);
static isc_result_t
create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
static void
-free_map(cfg_parser_t *pctx, cfg_obj_t *obj);
+free_map(cfg_obj_t *obj);
static isc_result_t
parse_symtab_elt(cfg_parser_t *pctx, const char *name, cfg_type_t *elttype,
isc_symtab_t *symtab, bool callback);
static void
-free_noop(cfg_parser_t *pctx, cfg_obj_t *obj);
+free_noop(cfg_obj_t *obj);
static isc_result_t
cfg_getstringtoken(cfg_parser_t *pctx);
cfg_print_cstr(pctx, "}");
}
+cfg_obj_t *
+cfg_parser_currentfile(cfg_parser_t *pctx) {
+ cfg_listelt_t *elt = NULL;
+ cfg_obj_t *fileobj = NULL;
+
+ if (pctx->open_files == NULL) {
+ return NULL;
+ }
+
+ elt = ISC_LIST_TAIL(pctx->open_files->value.list);
+ if (elt == NULL) {
+ return NULL;
+ }
+
+ fileobj = elt->obj;
+ INSIST(fileobj->type == &cfg_type_qstring);
+ return fileobj;
+}
+
isc_result_t
cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
nfields++;
}
- CHECK(cfg_create_obj(pctx, type, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, type, &obj));
obj->value.tuple = isc_mem_cget(pctx->mctx, nfields,
sizeof(cfg_obj_t *));
for (f = fields, i = 0; f->name != NULL; f++, i++) {
}
static void
-free_tuple(cfg_parser_t *pctx, cfg_obj_t *obj) {
+free_tuple(cfg_obj_t *obj) {
unsigned int i;
const cfg_tuplefielddef_t *fields = obj->type->of;
const cfg_tuplefielddef_t *f;
CLEANUP_OBJ(obj->value.tuple[i]);
nfields++;
}
- isc_mem_cput(pctx->mctx, obj->value.tuple, nfields,
- sizeof(cfg_obj_t *));
+ isc_mem_cput(obj->mctx, obj->value.tuple, nfields, sizeof(cfg_obj_t *));
}
bool
UNUSED(type);
- return cfg_create_obj(pctx, &cfg_type_void, ret);
+ return cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_void, ret);
}
void
return ISC_R_UNEXPECTEDTOKEN;
}
- CHECK(cfg_create_obj(pctx, &cfg_type_percentage, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_percentage, &obj));
obj->value.uint32 = (uint32_t)percent;
*ret = obj;
return ISC_R_UNEXPECTEDTOKEN;
}
- CHECK(cfg_create_obj(pctx, &cfg_type_fixedpoint, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_fixedpoint, &obj));
obj->value.uint32 = strtoul(p, NULL, 10) * 100;
switch (n3) {
return ISC_R_UNEXPECTEDTOKEN;
}
- CHECK(cfg_create_obj(pctx, &cfg_type_uint32, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_uint32, &obj));
obj->value.uint32 = pctx->token.value.as_ulong;
*ret = obj;
goto cleanup;
}
- CHECK(cfg_create_obj(pctx, &cfg_type_duration, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_duration, &obj));
obj->value.duration = duration;
*ret = obj;
duration.iso8601 = false;
duration.unlimited = true;
- CHECK(cfg_create_obj(pctx, &cfg_type_duration, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_duration, &obj));
obj->value.duration = duration;
*ret = obj;
return ISC_R_SUCCESS;
cfg_obj_t *obj = NULL;
int len;
- CHECK(cfg_create_obj(pctx, type, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, type, &obj));
len = strlen(contents);
obj->value.string.length = len;
obj->value.string.base = isc_mem_get(pctx->mctx, len + 1);
}
static void
-free_string(cfg_parser_t *pctx, cfg_obj_t *obj) {
- isc_mem_put(pctx->mctx, obj->value.string.base,
+free_string(cfg_obj_t *obj) {
+ isc_mem_put(obj->mctx, obj->value.string.base,
obj->value.string.length + 1);
}
static void
-free_sockaddrtls(cfg_parser_t *pctx, cfg_obj_t *obj) {
+free_sockaddrtls(cfg_obj_t *obj) {
if (obj->value.sockaddrtls.tls.base != NULL) {
INSIST(obj->value.sockaddrtls.tls.length != 0);
- isc_mem_put(pctx->mctx, obj->value.sockaddrtls.tls.base,
+ isc_mem_put(obj->mctx, obj->value.sockaddrtls.tls.base,
obj->value.sockaddrtls.tls.length + 1);
}
}
goto bad_boolean;
}
- CHECK(cfg_create_obj(pctx, &cfg_type_boolean, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_boolean, &obj));
obj->value.boolean = value;
*ret = obj;
return result;
REQUIRE(type != NULL);
REQUIRE(obj != NULL && *obj == NULL);
- CHECK(cfg_create_obj(pctx, type, obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, type, obj));
ISC_LIST_INIT((*obj)->value.list);
cleanup:
return result;
}
static void
-free_listelt(cfg_parser_t *pctx, cfg_listelt_t *elt) {
+free_listelt(isc_mem_t *mctx, cfg_listelt_t *elt) {
if (elt->obj != NULL) {
- cfg_obj_destroy(pctx, &elt->obj);
+ cfg_obj_destroy(&elt->obj);
}
- isc_mem_put(pctx->mctx, elt, sizeof(*elt));
+ isc_mem_put(mctx, elt, sizeof(*elt));
}
static void
-free_list(cfg_parser_t *pctx, cfg_obj_t *obj) {
+free_list(cfg_obj_t *obj) {
ISC_LIST_FOREACH(obj->value.list, elt, link) {
- free_listelt(pctx, elt);
+ free_listelt(obj->mctx, elt);
}
}
cleanup:
if (elt != NULL) {
- free_listelt(pctx, elt);
+ free_listelt(pctx->mctx, elt);
}
CLEANUP_OBJ(listobj);
return result;
CHECK(parser_openfile(pctx, g.gl_pathv[i]));
}
- cfg_obj_destroy(pctx, &includename);
+ cfg_obj_destroy(&includename);
globfree(&g);
goto redo;
*/
CHECK(cfg_parse_obj(pctx, &cfg_type_unsupported,
&eltobj));
- cfg_obj_destroy(pctx, &eltobj);
+ cfg_obj_destroy(&eltobj);
CHECK(parse_semicolon(pctx));
continue;
}
UNUSED(type);
- CHECK(cfg_create_obj(pctx, &cfg_type_token, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_token, &obj));
CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
if (pctx->token.type == isc_tokentype_eof) {
cfg_ungettoken(pctx);
isc_netaddr_t netaddr;
unsigned int flags = *(const unsigned int *)type->of;
- CHECK(cfg_create_obj(pctx, type, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, type, &obj));
CHECK(cfg_parse_rawaddr(pctx, flags, &netaddr));
isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, 0);
*ret = obj;
}
prefixlen = addrlen;
}
- CHECK(cfg_create_obj(pctx, &cfg_type_netprefix, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, &cfg_type_netprefix, &obj));
obj->value.netprefix.address = netaddr;
obj->value.netprefix.prefixlen = prefixlen;
*ret = obj;
goto cleanup;
}
- CHECK(cfg_create_obj(pctx, type, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, type, &obj));
if (have_tls == 1) {
obj->value.sockaddrtls.tls = tls;
}
#define MAX_LOG_TOKEN 30 /* How much of a token to quote in log messages. */
-static bool
-have_current_file(cfg_parser_t *pctx) {
- cfg_listelt_t *elt;
- if (pctx->open_files == NULL) {
- return false;
- }
-
- elt = ISC_LIST_TAIL(pctx->open_files->value.list);
- if (elt == NULL) {
- return false;
- }
-
- return true;
-}
-
-static cfg_obj_t *
-current_file(cfg_parser_t *pctx) {
- cfg_listelt_t *elt;
- cfg_obj_t *fileobj;
-
- if (!have_current_file(pctx)) {
- return NULL;
- }
-
- elt = ISC_LIST_TAIL(pctx->open_files->value.list);
- if (elt == NULL) { /* shouldn't be possible, but... */
- return NULL;
- }
-
- fileobj = elt->obj;
- INSIST(fileobj->type == &cfg_type_qstring);
- return fileobj;
-}
-
static void
parser_complain(cfg_parser_t *pctx, bool is_warning, unsigned int flags,
const char *format, va_list args) {
static char message[2048];
int level = ISC_LOG_ERROR;
const char *prep = "";
+ const cfg_obj_t *file = NULL;
size_t len;
if (is_warning) {
}
where[0] = '\0';
- if (have_current_file(pctx)) {
+ file = cfg_parser_currentfile(pctx);
+ if (file != NULL) {
snprintf(where, sizeof(where),
- "%s:%u: ", cfg_obj_asstring(current_file(pctx)),
- pctx->line);
+ "%s:%u: ", cfg_obj_asstring(file), pctx->line);
} else if (pctx->buf_name != NULL) {
snprintf(where, sizeof(where), "%s: ", pctx->buf_name);
}
}
isc_result_t
-cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+cfg_create_obj(isc_mem_t *mctx, cfg_obj_t *file, size_t line,
+ const cfg_type_t *type, cfg_obj_t **ret) {
cfg_obj_t *obj;
- cfg_obj_t *file = NULL;
- REQUIRE(pctx != NULL);
+ REQUIRE(mctx != NULL);
REQUIRE(type != NULL);
REQUIRE(ret != NULL && *ret == NULL);
- obj = isc_mem_get(pctx->mctx, sizeof(cfg_obj_t));
- *obj = (cfg_obj_t){ .type = type, .line = pctx->line, .pctx = pctx };
- isc_refcount_init(&obj->references, 1);
+ obj = isc_mem_get(mctx, sizeof(cfg_obj_t));
+ *obj = (cfg_obj_t){ .magic = CFGOBJ_MAGIC, .type = type, .line = line };
- file = current_file(pctx);
+ isc_refcount_init(&obj->references, 1);
+ isc_mem_attach(mctx, &obj->mctx);
if (file != NULL) {
cfg_obj_attach(file, &obj->file);
}
map_symtabitem_destroy(char *key, unsigned int type, isc_symvalue_t symval,
void *userarg) {
cfg_obj_t *obj = symval.as_pointer;
- cfg_parser_t *pctx = (cfg_parser_t *)userarg;
UNUSED(key);
UNUSED(type);
+ UNUSED(userarg);
- cfg_obj_destroy(pctx, &obj);
+ cfg_obj_destroy(&obj);
}
static isc_result_t
isc_symtab_t *symtab = NULL;
cfg_obj_t *obj = NULL;
- CHECK(cfg_create_obj(pctx, type, &obj));
+ CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx),
+ pctx->line, type, &obj));
isc_symtab_create(pctx->mctx, map_symtabitem_destroy, pctx, false,
&symtab);
obj->value.map.symtab = symtab;
}
static void
-free_map(cfg_parser_t *pctx, cfg_obj_t *obj) {
+free_map(cfg_obj_t *obj) {
CLEANUP_OBJ(obj->value.map.id);
isc_symtab_destroy(&obj->value.map.symtab);
}
* Destroy 'obj', a configuration object created in 'pctx'.
*/
void
-cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **objp) {
+cfg_obj_destroy(cfg_obj_t **objp) {
REQUIRE(objp != NULL && *objp != NULL);
- REQUIRE(pctx != NULL);
+ REQUIRE((*objp)->magic == CFGOBJ_MAGIC);
cfg_obj_t *obj = *objp;
*objp = NULL;
if (isc_refcount_decrement(&obj->references) == 1) {
+ obj->magic = 0;
+
if (obj->file != NULL) {
- cfg_obj_destroy(obj->file->pctx, &obj->file);
+ cfg_obj_destroy(&obj->file);
}
- obj->type->rep->free(pctx, obj);
+ obj->type->rep->free(obj);
+
isc_refcount_destroy(&obj->references);
- isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t));
+ isc_mem_putanddetach(&obj->mctx, obj, sizeof(cfg_obj_t));
}
}
}
static void
-free_noop(cfg_parser_t *pctx, cfg_obj_t *obj) {
- UNUSED(pctx);
+free_noop(cfg_obj_t *obj) {
UNUSED(obj);
}
cleanup:
if (elt != NULL) {
- free_listelt(pctx, elt);
+ free_listelt(pctx->mctx, elt);
}
CLEANUP_OBJ(destobj);