1 2 /** 3 * \file autoopts.c 4 * 5 * This file contains all of the routines that must be linked into 6 * an executable to use the generated option processing. The optional 7 * routines are in separately compiled modules so that they will not 8 * necessarily be linked in. 9 * 10 * @addtogroup autoopts 11 * @{ 12 */ 13 /* 14 * This file is part of AutoOpts, a companion to AutoGen. 15 * AutoOpts is free software. 16 * AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved 17 * 18 * AutoOpts is available under any one of two licenses. The license 19 * in use must be one of these two and the choice is under the control 20 * of the user of the license. 21 * 22 * The GNU Lesser General Public License, version 3 or later 23 * See the files "COPYING.lgplv3" and "COPYING.gplv3" 24 * 25 * The Modified Berkeley Software Distribution License 26 * See the file "COPYING.mbsd" 27 * 28 * These files have the following sha256 sums: 29 * 30 * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 31 * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 32 * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd 33 */ 34 35 /** 36 * The number of tab characters to skip when printing continuation lines. 37 */ 38 static unsigned int tab_skip_ct = 0; 39 40 #ifndef HAVE_PATHFIND 41 # define pathfind(_p, _n, _m) option_pathfind(_p, _n, _m) 42 # include "compat/pathfind.c" 43 #endif 44 45 #ifndef HAVE_SNPRINTF 46 # define vsnprintf option_vsnprintf 47 # define snprintf option_snprintf 48 # include "compat/snprintf.c" 49 #endif 50 51 #ifndef HAVE_STRDUP 52 # define strdup(_s) option_strdup(_s) 53 # include "compat/strdup.c" 54 #endif 55 56 #ifndef HAVE_STRCHR 57 # define strrchr(_s, _c) option_strrchr(_s, _c) 58 # define strchr(_s, _c) option_strchr(_s, _c) 59 # include "compat/strchr.c" 60 #endif 61 62 LOCAL void * 63 ao_malloc(size_t sz) 64 { 65 void * res = malloc(sz); 66 if (res == NULL) { 67 fprintf(stderr, zalloc_fail, (int)sz); 68 option_exits(EXIT_FAILURE); 69 } 70 return res; 71 } 72 #undef malloc 73 #define malloc(_s) ao_malloc(_s) 74 75 LOCAL void * 76 ao_realloc(void *p, size_t sz) 77 { 78 void * res = (p == NULL) ? malloc(sz) : realloc(p, sz); 79 if (res == NULL) { 80 fprintf(stderr, zrealloc_fail, (int)sz, p); 81 option_exits(EXIT_FAILURE); 82 } 83 return res; 84 } 85 #undef realloc 86 #define realloc(_p,_s) ao_realloc(_p,_s) 87 88 LOCAL char * 89 ao_strdup(char const *str) 90 { 91 char * res = strdup(str); 92 if (res == NULL) { 93 fprintf(stderr, zalloc_fail, (int)strlen(str)); 94 option_exits(EXIT_FAILURE); 95 } 96 return res; 97 } 98 #undef strdup 99 #define strdup(_p) ao_strdup(_p) 100 101 /** 102 * handle an option. 103 * 104 * This routine handles equivalencing, sets the option state flags and 105 * invokes the handler procedure, if any. 106 */ 107 LOCAL tSuccess 108 handle_opt(tOptions * opts, tOptState * o_st) 109 { 110 /* 111 * Save a copy of the option procedure pointer. 112 * If this is an equivalence class option, we still want this proc. 113 */ 114 tOptDesc * od = o_st->pOD; 115 tOptProc * opt_proc = od->pOptProc; 116 if (od->fOptState & OPTST_ALLOC_ARG) 117 AGFREE(od->optArg.argString); 118 119 od->optArg.argString = o_st->pzOptArg; 120 121 /* 122 * IF we are presetting options, then we will ignore any un-presettable 123 * options. They are the ones either marked as such. 124 */ 125 if ( ((opts->fOptSet & OPTPROC_PRESETTING) != 0) 126 && ((od->fOptState & OPTST_NO_INIT) != 0) 127 ) 128 return PROBLEM; 129 130 /* 131 * IF this is an equivalence class option, 132 * THEN 133 * Save the option value that got us to this option 134 * entry. (It may not be od->optChar[0], if this is an 135 * equivalence entry.) 136 * set the pointer to the equivalence class base 137 */ 138 if (od->optEquivIndex != NO_EQUIVALENT) { 139 tOptDesc * eqv_od = opts->pOptDesc + od->optEquivIndex; 140 141 /* 142 * IF the current option state has not been defined (set on the 143 * command line), THEN we will allow continued resetting of 144 * the value. Once "defined", then it must not change. 145 */ 146 if ((od->fOptState & OPTST_DEFINED) != 0) { 147 /* 148 * The equivalenced-to option has been found on the command 149 * line before. Make sure new occurrences are the same type. 150 * 151 * IF this option has been previously equivalenced and 152 * it was not the same equivalenced-to option, 153 * THEN we have a usage problem. 154 */ 155 if (eqv_od->optActualIndex != od->optIndex) { 156 fprintf(stderr, zmultiway_bug, eqv_od->pz_Name, od->pz_Name, 157 (opts->pOptDesc + eqv_od->optActualIndex)->pz_Name); 158 return FAILURE; 159 } 160 } else { 161 /* 162 * Set the equivalenced-to actual option index to no-equivalent 163 * so that we set all the entries below. This option may either 164 * never have been selected before, or else it was selected by 165 * some sort of "presetting" mechanism. 166 */ 167 eqv_od->optActualIndex = NO_EQUIVALENT; 168 } 169 170 if (eqv_od->optActualIndex != od->optIndex) { 171 /* 172 * First time through, copy over the state 173 * and add in the equivalence flag 174 */ 175 eqv_od->optActualValue = od->optValue; 176 eqv_od->optActualIndex = od->optIndex; 177 o_st->flags |= OPTST_EQUIVALENCE; 178 } 179 180 /* 181 * Copy the most recent option argument. set membership state 182 * is kept in 'eqv_od->optCookie'. Do not overwrite. 183 */ 184 eqv_od->optArg.argString = od->optArg.argString; 185 od = eqv_od; 186 187 } else { 188 od->optActualValue = od->optValue; 189 od->optActualIndex = od->optIndex; 190 } 191 192 od->fOptState &= OPTST_PERSISTENT_MASK; 193 od->fOptState |= (o_st->flags & ~OPTST_PERSISTENT_MASK); 194 195 /* 196 * Keep track of count only for DEFINED (command line) options. 197 * IF we have too many, build up an error message and bail. 198 */ 199 if ( (od->fOptState & OPTST_DEFINED) 200 && (++od->optOccCt > od->optMaxCt) ) 201 return too_many_occurrences(opts, od); 202 /* 203 * If provided a procedure to call, call it 204 */ 205 if (opt_proc != NULL) 206 (*opt_proc)(opts, od); 207 208 return SUCCESS; 209 } 210 211 /** 212 * Find the option descriptor and option argument (if any) for the 213 * next command line argument. DO NOT modify the descriptor. Put 214 * all the state in the state argument so that the option can be skipped 215 * without consequence (side effect). 216 * 217 * @param opts the program option descriptor 218 * @param o_st the state of the next found option 219 */ 220 LOCAL tSuccess 221 next_opt(tOptions * opts, tOptState * o_st) 222 { 223 { 224 tSuccess res = find_opt(opts, o_st); 225 if (! SUCCESSFUL(res)) 226 return res; 227 } 228 229 if ( ((o_st->flags & OPTST_DEFINED) != 0) 230 && ((o_st->pOD->fOptState & OPTST_NO_COMMAND) != 0)) { 231 fprintf(stderr, zNotCmdOpt, o_st->pOD->pz_Name); 232 return FAILURE; 233 } 234 235 return get_opt_arg(opts, o_st); 236 } 237 238 /** 239 * Process all the options from our current position onward. (This allows 240 * interspersed options and arguments for the few non-standard programs that 241 * require it.) Thus, do not rewind option indexes because some programs 242 * choose to re-invoke after a non-option. 243 * 244 * @param[in,out] opts program options descriptor 245 * @returns SUCCESS or FAILURE 246 */ 247 LOCAL tSuccess 248 regular_opts(tOptions * opts) 249 { 250 /* assert: opts->fOptSet & OPTPROC_IMMEDIATE == 0 */ 251 for (;;) { 252 tOptState opt_st = OPTSTATE_INITIALIZER(DEFINED); 253 254 switch (next_opt(opts, &opt_st)) { 255 case FAILURE: goto failed_option; 256 case PROBLEM: return SUCCESS; /* no more args */ 257 case SUCCESS: break; 258 } 259 260 /* 261 * IF this is an immediate action option, 262 * THEN skip it (unless we are supposed to do it a second time). 263 */ 264 if (! DO_NORMALLY(opt_st.flags)) { 265 if (! DO_SECOND_TIME(opt_st.flags)) 266 continue; 267 opt_st.pOD->optOccCt--; /* don't count this repetition */ 268 } 269 270 if (! SUCCESSFUL(handle_opt(opts, &opt_st))) 271 break; 272 } failed_option:; 273 274 if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) 275 (*opts->pUsageProc)(opts, EXIT_FAILURE); 276 277 return FAILURE; 278 } 279 280 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 281 * 282 * THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE 283 */ 284 /*=--subblock=arg=arg_type,arg_name,arg_desc =*/ 285 /*=* 286 * library: opts 287 * header: your-opts.h 288 * 289 * lib_description: 290 * 291 * These are the routines that libopts users may call directly from their 292 * code. There are several other routines that can be called by code 293 * generated by the libopts option templates, but they are not to be 294 * called from any other user code. The @file{options.h} header is 295 * fairly clear about this, too. 296 =*/ 297 298 /*=export_func optionProcess 299 * 300 * what: this is the main option processing routine 301 * 302 * arg: + tOptions * + opts + program options descriptor + 303 * arg: + int + a_ct + program arg count + 304 * arg: + char ** + a_v + program arg vector + 305 * 306 * ret_type: int 307 * ret_desc: the count of the arguments processed 308 * 309 * doc: 310 * 311 * This is the main entry point for processing options. It is intended 312 * that this procedure be called once at the beginning of the execution of 313 * a program. Depending on options selected earlier, it is sometimes 314 * necessary to stop and restart option processing, or to select completely 315 * different sets of options. This can be done easily, but you generally 316 * do not want to do this. 317 * 318 * The number of arguments processed always includes the program name. 319 * If one of the arguments is "--", then it is counted and the processing 320 * stops. If an error was encountered and errors are to be tolerated, then 321 * the returned value is the index of the argument causing the error. 322 * A hyphen by itself ("-") will also cause processing to stop and will 323 * @emph{not} be counted among the processed arguments. A hyphen by itself 324 * is treated as an operand. Encountering an operand stops option 325 * processing. 326 * 327 * err: Errors will cause diagnostics to be printed. @code{exit(3)} may 328 * or may not be called. It depends upon whether or not the options 329 * were generated with the "allow-errors" attribute, or if the 330 * ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked. 331 =*/ 332 int 333 optionProcess(tOptions * opts, int a_ct, char ** a_v) 334 { 335 if (! SUCCESSFUL(validate_struct(opts, a_v[0]))) 336 ao_bug(zbad_data_msg); 337 338 /* 339 * Establish the real program name, the program full path, 340 * and do all the presetting the first time thru only. 341 */ 342 if (! ao_initialize(opts, a_ct, a_v)) 343 return 0; 344 345 /* 346 * IF we are (re)starting, 347 * THEN reset option location 348 */ 349 if (opts->curOptIdx <= 0) { 350 opts->curOptIdx = 1; 351 opts->pzCurOpt = NULL; 352 } 353 354 if (! SUCCESSFUL(regular_opts(opts))) 355 return (int)opts->origArgCt; 356 357 /* 358 * IF there were no errors 359 * AND we have RC/INI files 360 * AND there is a request to save the files 361 * THEN do that now before testing for conflicts. 362 * (conflicts are ignored in preset options) 363 */ 364 switch (opts->specOptIdx.save_opts) { 365 case 0: 366 case NO_EQUIVALENT: 367 break; 368 default: 369 { 370 tOptDesc * od = opts->pOptDesc + opts->specOptIdx.save_opts; 371 372 if (SELECTED_OPT(od)) { 373 optionSaveFile(opts); 374 option_exits(EXIT_SUCCESS); 375 } 376 } 377 } 378 379 /* 380 * IF we are checking for errors, 381 * THEN look for too few occurrences of required options 382 */ 383 if (((opts->fOptSet & OPTPROC_ERRSTOP) != 0) 384 && (! is_consistent(opts))) 385 (*opts->pUsageProc)(opts, EXIT_FAILURE); 386 387 return (int)opts->curOptIdx; 388 } 389 390 /** @} 391 * 392 * Local Variables: 393 * mode: C 394 * c-file-style: "stroustrup" 395 * indent-tabs-mode: nil 396 * End: 397 * end of autoopts/autoopts.c */ 398