📄 autoopts.c
字号:
/* * doImmediateOpts - scan the command line for immediate action options */LOCAL tSuccessdoImmediateOpts( tOptions* pOpts ){ pOpts->curOptIdx = 1; /* start by skipping program name */ pOpts->pzCurOpt = NULL; /* * Examine all the options from the start. We process any options that * are marked for immediate processing. */ for (;;) { tOptState optState = OPTSTATE_INITIALIZER(PRESET); switch (nextOption( pOpts, &optState )) { case FAILURE: goto optionsDone; case PROBLEM: return SUCCESS; /* no more args */ case SUCCESS: break; } /* * IF this *is* an immediate-attribute option, then do it. */ if (! DO_IMMEDIATELY(optState.flags)) continue; if (! SUCCESSFUL( handleOption( pOpts, &optState ))) break; } optionsDone:; if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE ); return FAILURE;}LOCAL tSuccessdoRegularOpts( tOptions* pOpts ){ /* * Now, process all the options from our current position onward. * (This allows interspersed options and arguments for the few * non-standard programs that require it.) */ for (;;) { tOptState optState = OPTSTATE_INITIALIZER(DEFINED); switch (nextOption( pOpts, &optState )) { case FAILURE: goto optionsDone; case PROBLEM: return SUCCESS; /* no more args */ case SUCCESS: break; } /* * IF this is not being processed normally (i.e. is immediate action) * THEN skip it (unless we are supposed to do it a second time). */ if (! DO_NORMALLY(optState.flags)) { if (! DO_SECOND_TIME(optState.flags)) continue; optState.pOD->optOccCt--; /* don't count last time */ } if (! SUCCESSFUL( handleOption( pOpts, &optState ))) break; } optionsDone:; if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE ); return FAILURE;}/* * doPresets - check for preset values from a config file or the envrionment */static tSuccessdoPresets( tOptions* pOpts ){ tOptDesc * pOD = NULL; if (! SUCCESSFUL( doImmediateOpts( pOpts ))) return FAILURE; /* * IF this option set has a --save-opts option, then it also * has a --load-opts option. See if a command line option has disabled * option presetting. */ if (pOpts->specOptIdx.save_opts != 0) { pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1; if (DISABLED_OPT(pOD)) return SUCCESS; } /* * Until we return from this procedure, disable non-presettable opts */ pOpts->fOptSet |= OPTPROC_PRESETTING; /* * IF there are no config files, * THEN do any environment presets and leave. */ if (pOpts->papzHomeList == NULL) { doEnvPresets( pOpts, ENV_ALL ); } else { doEnvPresets( pOpts, ENV_IMM ); /* * Check to see if environment variables have disabled presetting. */ if ((pOD != NULL) && ! DISABLED_OPT(pOD)) internalFileLoad( pOpts ); /* * ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment * variable options. Only the loading of .rc files. */ doEnvPresets( pOpts, ENV_NON_IMM ); } pOpts->fOptSet &= ~OPTPROC_PRESETTING; return SUCCESS;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERIFY OPTION CONSISTENCY * * Make sure that the argument list passes our consistency tests. */static intcheckConsistency( tOptions* pOpts ){ int errCt = 0; tOptDesc* pOD = pOpts->pOptDesc; int oCt = pOpts->presetOptCt; /* * FOR each of "oCt" options, ... */ for (;;) { const int* pMust = pOD->pOptMust; const int* pCant = pOD->pOptCant; /* * IF the current option was provided on the command line * THEN ensure that any "MUST" requirements are not * "DEFAULT" (unspecified) *AND* ensure that any * "CANT" options have not been SET or DEFINED. */ if (SELECTED_OPT(pOD)) { if (pMust != NULL) for (;;) { tOptDesc* p = pOpts->pOptDesc + *(pMust++); if (UNUSED_OPT(p)) { const tOptDesc* pN = pOpts->pOptDesc + pMust[-1]; errCt++; fprintf( stderr, zReqFmt, pOD->pz_Name, pN->pz_Name ); } if (*pMust == NO_EQUIVALENT) break; } if (pCant != NULL) for (;;) { tOptDesc* p = pOpts->pOptDesc + *(pCant++); if (SELECTED_OPT(p)) { const tOptDesc* pN = pOpts->pOptDesc + pCant[-1]; errCt++; fprintf( stderr, zCantFmt, pOD->pz_Name, pN->pz_Name ); } if (*pCant == NO_EQUIVALENT) break; } } /* * IF this option is not equivalenced to another, * OR it is equivalenced to itself (is the equiv. root) * THEN we need to make sure it occurs often enough. */ if ( (pOD->optEquivIndex == NO_EQUIVALENT) || (pOD->optEquivIndex == pOD->optIndex) ) do { /* * IF the occurrence counts have been satisfied, * THEN there is no problem. */ if (pOD->optOccCt >= pOD->optMinCt) break; /* * IF MUST_SET means SET and PRESET are okay, * so min occurrence count doesn't count */ if ( (pOD->fOptState & OPTST_MUST_SET) && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) ) break; errCt++; if (pOD->optMinCt > 1) fprintf( stderr, zNotEnough, pOD->pz_Name, pOD->optMinCt ); else fprintf( stderr, zNeedOne, pOD->pz_Name ); } while (0); if (--oCt <= 0) break; pOD++; } /* * IF we are stopping on errors, check to see if any remaining * arguments are required to be there or prohibited from being there. */ if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { /* * Check for prohibition */ if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) { if (pOpts->origArgCt > pOpts->curOptIdx) { fprintf( stderr, zNoArgs, pOpts->pzProgName ); ++errCt; } } /* * ELSE not prohibited, check for being required */ else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) { if (pOpts->origArgCt <= pOpts->curOptIdx) { fprintf( stderr, zArgsMust, pOpts->pzProgName ); ++errCt; } } } return errCt;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE *//*=--subblock=arg=arg_type,arg_name,arg_desc =*//*=* * library: opts * header: your-opts.h * * lib_description: * * These are the routines that libopts users may call directly from their * code. There are several other routines that can be called by code * generated by the libopts option templates, but they are not to be * called from any other user code. The @file{options.h} header is * fairly clear about this, too.=*//*=export_func optionProcess * * what: this is the main option processing routine * * arg: + tOptions* + pOpts + program options descriptor + * arg: + int + argc + program arg count + * arg: + char** + argv + program arg vector + * * ret_type: int * ret_desc: the count of the arguments processed * * doc: * * This is the main entry point for processing options. It is intended * that this procedure be called once at the beginning of the execution of * a program. Depending on options selected earlier, it is sometimes * necessary to stop and restart option processing, or to select completely * different sets of options. This can be done easily, but you generally * do not want to do this. * * The number of arguments processed always includes the program name. * If one of the arguments is "--", then it is counted and the processing * stops. If an error was encountered and errors are to be tolerated, then * the returned value is the index of the argument causing the error. * A hyphen by itself ("-") will also cause processing to stop and will * @emph{not} be counted among the processed arguments. A hyphen by itself * is treated as an operand. Encountering an operand stops option * processing. * * err: Errors will cause diagnostics to be printed. @code{exit(3)} may * or may not be called. It depends upon whether or not the options * were generated with the "allow-errors" attribute, or if the * ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked.=*/intoptionProcess( tOptions* pOpts, int argCt, char** argVect ){ if (! SUCCESSFUL( validateOptionsStruct( pOpts, argVect[0] ))) exit( EX_SOFTWARE ); /* * Establish the real program name, the program full path, * and do all the presetting the first time thru only. */ if ((pOpts->fOptSet & OPTPROC_INITDONE) == 0) { pOpts->origArgCt = argCt; pOpts->origArgVect = argVect; pOpts->fOptSet |= OPTPROC_INITDONE; if (! SUCCESSFUL( doPresets( pOpts ))) return 0; if ((pOpts->fOptSet & OPTPROC_REORDER) != 0) optionSort( pOpts ); pOpts->curOptIdx = 1; pOpts->pzCurOpt = NULL; } /* * IF we are (re)starting, * THEN reset option location */ else if (pOpts->curOptIdx <= 0) { pOpts->curOptIdx = 1; pOpts->pzCurOpt = NULL; } if (! SUCCESSFUL( doRegularOpts( pOpts ))) return pOpts->origArgCt; /* * IF there were no errors * AND we have RC/INI files * AND there is a request to save the files * THEN do that now before testing for conflicts. * (conflicts are ignored in preset options) */ if (pOpts->specOptIdx.save_opts != 0) { tOptDesc* pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts; if (SELECTED_OPT( pOD )) { optionSaveFile( pOpts ); exit( EXIT_SUCCESS ); } } /* * IF we are checking for errors, * THEN look for too few occurrences of required options */ if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { if (checkConsistency( pOpts ) != 0) (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE ); } return pOpts->curOptIdx;}/* * Local Variables: * mode: C * c-file-style: "stroustrup" * indent-tabs-mode: nil * End: * end of autoopts/autoopts.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -