/*=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 * pOV ) { if (pOV == NULL) return; if (pOV->valType != OPARG_TYPE_HIERARCHY) { errno = EINVAL; return; } unloadNestedArglist( pOV->v.nestVal ); AGFREE(pOV); }
/* unloadNestedArglist * * 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. */ static void unloadNestedArglist( tArgList* pAL ) { int ct = pAL->useCt; tCC** ppNV = pAL->apzArgs; while (ct-- > 0) { tOptionValue* pNV = (tOptionValue*)(void*)(intptr_t)*(ppNV++); if (pNV->valType == OPARG_TYPE_HIERARCHY) unloadNestedArglist( pNV->v.nestVal ); AGFREE( pNV ); } AGFREE( pAL ); }
/*=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) unloadNestedArglist(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, p->optCt * sizeof( tOptDesc )); AGFREE( pOpts->pSavedState ); pOpts->pSavedState = NULL; goto free_saved_state; } }