/*=export_func optionUnloadNested * * what: Deallocate the memory for a nested value * arg: + tOptionValue const * + pOptVal + the hierarchical value + * * doc: * A nested value needs to be deallocated. The pointer passed in should * have been gotten from a call to @code{configFileLoad()} (See * @pxref{libopts-configFileLoad}). =*/ void optionUnloadNested(tOptionValue const * opt_val) { if (opt_val == NULL) return; if (opt_val->valType != OPARG_TYPE_HIERARCHY) { errno = EINVAL; return; } unload_arg_list(opt_val->v.nestVal); AGFREE(opt_val); }
/** * Deallocate a list of option arguments. This must have been gotten from * a hierarchical option argument, not a stacked list of strings. It is * an internal call, so it is not validated. The caller is responsible for * knowing what they are doing. */ LOCAL void unload_arg_list(tArgList * arg_list) { int ct = arg_list->useCt; char const ** pnew_val = arg_list->apzArgs; while (ct-- > 0) { tOptionValue * new_val = (tOptionValue *)VOIDP(*(pnew_val++)); if (new_val->valType == OPARG_TYPE_HIERARCHY) unload_arg_list(new_val->v.nestVal); AGFREE(new_val); } AGFREE(arg_list); }
/*=export_func optionFree * * what: free allocated option processing memory * arg: tOptions*, pOpts, program options descriptor * * doc: AutoOpts sometimes allocates memory and puts pointers to it in the * option state structures. This routine deallocates all such memory. * * err: As long as memory has not been corrupted, * this routine is always successful. =*/ void optionFree(tOptions* pOpts) { free_saved_state: { tOptDesc* p = pOpts->pOptDesc; int ct = pOpts->optCt; do { if (p->fOptState & OPTST_ALLOC_ARG) { AGFREE(p->optArg.argString); p->optArg.argString = NULL; p->fOptState &= ~OPTST_ALLOC_ARG; } switch (OPTST_GET_ARGTYPE(p->fOptState)) { case OPARG_TYPE_STRING: #ifdef WITH_LIBREGEX if ( (p->fOptState & OPTST_STACKED) && (p->optCookie != NULL)) { p->optArg.argString = ".*"; optionUnstackArg(pOpts, p); } #else /* leak memory */; #endif break; case OPARG_TYPE_HIERARCHY: if (p->optCookie != NULL) unload_arg_list(p->optCookie); break; } p->optCookie = NULL; } while (p++, --ct > 0); } if (pOpts->pSavedState != NULL) { tOptions * p = (tOptions*)pOpts->pSavedState; memcpy(pOpts, p, sizeof(*p)); memcpy(pOpts->pOptDesc, p+1, (size_t)p->optCt * sizeof(tOptDesc)); AGFREE(pOpts->pSavedState); pOpts->pSavedState = NULL; goto free_saved_state; } }