/*=export_func configFileLoad * * what: parse a configuration file * arg: + char const* + fname + the file to load + * * ret_type: const tOptionValue* * ret_desc: An allocated, compound value structure * * doc: * This routine will load a named configuration file and parse the * text as a hierarchically valued option. The option descriptor * created from an option definition file is not used via this interface. * The returned value is "named" with the input file name and is of * type "@code{OPARG_TYPE_HIERARCHY}". It may be used in calls to * @code{optionGetValue()}, @code{optionNextValue()} and * @code{optionUnloadNested()}. * * err: * If the file cannot be loaded or processed, @code{NULL} is returned and * @var{errno} is set. It may be set by a call to either @code{open(2)} * @code{mmap(2)} or other file system calls, or it may be: * @itemize @bullet * @item * @code{ENOENT} - the file was not found. * @item * @code{ENOMSG} - the file was empty. * @item * @code{EINVAL} - the file contents are invalid -- not properly formed. * @item * @code{ENOMEM} - not enough memory to allocate the needed structures. * @end itemize =*/ const tOptionValue * configFileLoad(char const * fname) { tmap_info_t cfgfile; tOptionValue * res = NULL; tOptionLoadMode save_mode = option_load_mode; char * txt = text_mmap(fname, PROT_READ, MAP_PRIVATE, &cfgfile); if (TEXT_MMAP_FAILED_ADDR(txt)) return NULL; /* errno is set */ option_load_mode = OPTION_LOAD_COOKED; res = optionLoadNested(txt, fname, strlen(fname)); if (res == NULL) { int err = errno; text_munmap(&cfgfile); errno = err; } else text_munmap(&cfgfile); option_load_mode = save_mode; return res; }
/*=export_func optionNestedVal * private: * * what: parse a hierarchical option argument * arg: + tOptions * + opts + program options descriptor + * arg: + tOptDesc * + od + the descriptor for this arg + * * doc: * Nested value was found on the command line =*/ void optionNestedVal(tOptions * opts, tOptDesc * od) { if (opts < OPTPROC_EMIT_LIMIT) return; if (od->fOptState & OPTST_RESET) { tArgList * arg_list = od->optCookie; int ct; char const ** av; if (arg_list == NULL) return; ct = arg_list->useCt; av = arg_list->apzArgs; while (--ct >= 0) { void * p = VOIDP(*(av++)); optionUnloadNested((tOptionValue const *)p); } AGFREE(od->optCookie); } else { tOptionValue * opt_val = optionLoadNested( od->optArg.argString, od->pz_Name, strlen(od->pz_Name)); if (opt_val != NULL) addArgListEntry(&(od->optCookie), VOIDP(opt_val)); } }
/*=export_func optionNestedVal * private: * * what: parse a hierarchical option argument * arg: + tOptions* + pOpts + program options descriptor + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + * * doc: * Nested value was found on the command line =*/ void optionNestedVal(tOptions* pOpts, tOptDesc* pOD) { if (pOpts < OPTPROC_EMIT_LIMIT) return; if (pOD->fOptState & OPTST_RESET) { tArgList* pAL = pOD->optCookie; int ct; tCC ** av; if (pAL == NULL) return; ct = pAL->useCt; av = pAL->apzArgs; while (--ct >= 0) { void * p = (void *)(intptr_t)*(av++); optionUnloadNested((tOptionValue const *)p); } AGFREE(pOD->optCookie); } else { tOptionValue* pOV = optionLoadNested( pOD->optArg.argString, pOD->pz_Name, strlen(pOD->pz_Name)); if (pOV != NULL) addArgListEntry( &(pOD->optCookie), (void*)pOV ); } }
/* addNestedValue * * Associate a name with either a string or no value. */ static tOptionValue* addNestedValue( void** pp, char const* pzName, size_t nameLen, char* pzValue, size_t dataLen ) { tOptionValue* pNV; if (dataLen == 0) { size_t sz = nameLen + sizeof(*pNV) + 1; pNV = AGALOC( sz, "empty nested value pair" ); if (pNV == NULL) return NULL; pNV->v.nestVal = NULL; pNV->valType = OPARG_TYPE_HIERARCHY; pNV->pzName = (char*)(pNV + 1); memcpy( pNV->pzName, pzName, nameLen ); pNV->pzName[ nameLen ] = NUL; } else { pNV = optionLoadNested( pzValue, pzName, nameLen ); } if (pNV != NULL) addArgListEntry( pp, pNV ); return pNV; }
/** * Associate a name with a nested/hierarchical value. * * @param[in,out] pp argument list to add to * @param[in] name the name of the "suboption" * @param[in] nm_len the length of the name * @param[in] val the nested values for the suboption * @param[in] d_len the length of the value * * @returns the new value structure */ static tOptionValue * add_nested(void ** pp, char const * name, size_t nm_len, char * val, size_t d_len) { tOptionValue * new_val; if (d_len == 0) { size_t sz = nm_len + sizeof(*new_val) + 1; new_val = AGALOC(sz, "empty nest"); new_val->v.nestVal = NULL; new_val->valType = OPARG_TYPE_HIERARCHY; new_val->pzName = (char *)(new_val + 1); memcpy(new_val->pzName, name, nm_len); new_val->pzName[ nm_len ] = NUL; } else { new_val = optionLoadNested(val, name, nm_len); } if (new_val != NULL) addArgListEntry(pp, new_val); return new_val; }