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