1 /* Implements a somewhat more powerful command line getopt interface
2 * than the standard UNIX/POSIX call.
3 *
4 * Contents:
5 * 1. The ESL_GETOPTS object.
6 * 2. Setting and testing a configuration.
7 * 3. Retrieving option settings and command line args.
8 * 4. Formatting option help.
9 * 5. Private functions.
10 * 6. Test driver.
11 * 7. Examples.
12 *
13 * xref STL8/p152; STL9/p5.
14 */
15 #include "esl_config.h"
16
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <ctype.h>
21
22 #include "easel.h"
23 #include "esl_getopts.h"
24
25 /* Forward declarations of private functions. */
26 static int set_option(ESL_GETOPTS *g, int opti, char *optarg,
27 int setby, int do_alloc);
28 static int get_optidx_exactly(const ESL_GETOPTS *g, char *optname, int *ret_opti);
29 static int get_optidx_abbrev(ESL_GETOPTS *g, char *optname, int n,
30 int *ret_opti);
31 static int esl_getopts(ESL_GETOPTS *g, int *ret_opti, char **ret_optarg);
32 static int process_longopt(ESL_GETOPTS *g, int *ret_opti, char **ret_optarg);
33 static int process_stdopt(ESL_GETOPTS *g, int *ret_opti, char **ret_optarg);
34 static int verify_type_and_range(ESL_GETOPTS *g, int i, char *val, int setby);
35 static int verify_integer_range(char *arg, char *range);
36 static int verify_real_range(char *arg, char *range);
37 static int verify_char_range(char *arg, char *range);
38 static int parse_rangestring(char *range, char c, char **ret_lowerp,
39 int *ret_geq, char **ret_upperp, int *ret_leq);
40 static int process_optlist(ESL_GETOPTS *g, char **ret_s, int *ret_opti);
41
42
43
44 /*****************************************************************
45 *# 1. The <ESL_GETOPTS> object
46 *****************************************************************/
47
48 /* Function: esl_getopts_Create()
49 * Synopsis: Create a new <ESL_GETOPTS> object.
50 *
51 * Purpose: Creates an <ESL_GETOPTS> object, given the
52 * array of valid options <opt> (NULL-element-terminated).
53 * Sets default values for all config
54 * options (as defined in <opt>).
55 *
56 * Returns: ptr to the new <ESL_GETOPTS> object.
57 *
58 * Throws: NULL on failure, including allocation failures or
59 * an invalid <ESL_OPTIONS> structure.
60 */
61 ESL_GETOPTS *
esl_getopts_Create(const ESL_OPTIONS * opt)62 esl_getopts_Create(const ESL_OPTIONS *opt)
63 {
64 ESL_GETOPTS *g = NULL;
65 int status;
66 int i;
67
68 ESL_ALLOC(g, sizeof(ESL_GETOPTS));
69
70 g->opt = opt;
71 g->argc = 0;
72 g->argv = NULL;
73 g->optind = 1;
74 g->nfiles = 0;
75 g->val = NULL;
76 g->setby = NULL;
77 g->valloc = NULL;
78 g->optstring = NULL;
79 g->spoof = NULL;
80 g->spoof_argv= NULL;
81 g->errbuf[0] = '\0';
82
83 /* Figure out the number of options.
84 *
85 * Using the NULL-terminated structure array is a design decision.
86 * Alternatively, the caller could provide us with noptions, and use
87 * a #define noptions (sizeof(options) / sizeof(ESL_GETOPTS)) idiom.
88 * Note that we can't use sizeof() here, because now <opt> is just a
89 * pointer.
90 *
91 * A drawback of requiring NULL termination is, what happens when
92 * the caller forgets? Thus the check for a leading '-' on all
93 * options; if we start straying into memory, that check should
94 * catch us.
95 */
96 g->nopts = 0;
97 while (g->opt[g->nopts].name != NULL) {
98 if (g->opt[g->nopts].name[0] != '-')
99 ESL_XEXCEPTION(eslEINVAL, "option %d didn't start with '-';\nyou may have forgotten to NULL-terminate the ESL_OPTIONS array", g->nopts);
100 g->nopts++;
101 }
102
103 /* Set default values for all options.
104 * Note the valloc[] setting: we only need to dup strings
105 * into allocated space if the value is volatile memory, and
106 * that only happens in config files; not in defaults, cmdline,
107 * or environment.
108 */
109 ESL_ALLOC(g->val, sizeof(char *) * g->nopts);
110 ESL_ALLOC(g->setby, sizeof(int) * g->nopts);
111 ESL_ALLOC(g->valloc, sizeof(int) * g->nopts);
112
113 for (i = 0; i < g->nopts; i++)
114 {
115 g->val[i] = g->opt[i].defval;
116 g->setby[i] = eslARG_SETBY_DEFAULT;
117 g->valloc[i] = 0;
118 }
119
120 /* Verify type/range of the defaults, even though it's
121 * an application error (not user error) if they're invalid.
122 */
123 for (i = 0; i < g->nopts; i++)
124 if (verify_type_and_range(g, i, g->val[i], eslARG_SETBY_DEFAULT) != eslOK)
125 ESL_XEXCEPTION(eslEINVAL, "%s\n", g->errbuf);
126 return g;
127
128 ERROR:
129 esl_getopts_Destroy(g);
130 return NULL;
131 }
132
133 /* Function: esl_getopts_CreateDefaultApp()
134 * Synopsis: Initialize a standard Easel application.
135 *
136 * Purpose: Carry out the usual sequence of events in initializing a
137 * small Easel-based application: parses the command line,
138 * process the <-h> option to produce a (single-sectioned)
139 * help page, and check that the number of command line
140 * options is right.
141 *
142 * <options> is an array of <ESL_OPTIONS> structures describing
143 * the options, terminated by an all-<NULL> structure.
144 *
145 * <nargs> is the number of commandline arguments
146 * expected. If the number of commandline arguments isn't
147 * equal to this, an error message is printed, with the
148 * <usage> string, and <exit()> is called. If <nargs> is
149 * -1, this check isn't done; if your program deliberately
150 * has a variable number of commandline arguments (i.e.
151 * if the number is unknown at compile time), pass -1
152 * for <nargs>.
153 *
154 * <argc> and <argv> are the command line
155 * arguments (number and pointer array) from <main()>.
156 *
157 * <banner> is an optional one-line description of the
158 * program's function, such as <"compare RNA structures">.
159 * When the <-h> help option is selected, this description
160 * will be combined with the program's name (the tail of
161 * <argv[0]>) and Easel's copyright and license information
162 * to give a header like:
163 *
164 * \begin{cchunk}
165 * # esl-compstruct :: compare RNA structures
166 * # Easel 0.1 (February 2005)
167 * # Copyright (C) 2004-2007 HHMI Janelia Farm Research Campus
168 * # Freely licensed under the Janelia Software License.
169 * # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
170 * \end{cchunk}
171 *
172 * <usage> is an optional one-line description of command
173 * line usage (without the command name), such as
174 * \begin{cchunk}
175 * [options] <trusted file> <test file>
176 * \end{cchunk}
177 * On errors, or
178 * on the help page, this usage string is combined with
179 * the program's name to give a usage line like:
180 *
181 * \begin{cchunk}
182 * Usage: esl-compstruct [options] <trusted file> <test file>
183 * \end{cchunk}
184 *
185 * <banner> and <usage> are optional, meaning that either
186 * can be provided as <NULL> and they won't be shown.
187 *
188 * Returns: a pointer to a new <ESL_GETOPTS> object, which contains
189 * all the option settings and command line arguments.
190 *
191 * On command line errors, this routine exits with abnormal
192 * (1) status.
193 *
194 * If the <-h> help option is seen, this routine exits with
195 * normal (0) status after printing a help page.
196 *
197 */
198 ESL_GETOPTS *
esl_getopts_CreateDefaultApp(const ESL_OPTIONS * options,int nargs,int argc,char ** argv,char * banner,char * usage)199 esl_getopts_CreateDefaultApp(const ESL_OPTIONS *options, int nargs, int argc, char **argv, char *banner, char *usage)
200 {
201 ESL_GETOPTS *go = NULL;
202
203 go = esl_getopts_Create(options);
204 if (esl_opt_ProcessCmdline(go, argc, argv) != eslOK ||
205 esl_opt_VerifyConfig(go) != eslOK)
206 {
207 printf("Failed to parse command line: %s\n", go->errbuf);
208 if (usage != NULL) esl_usage(stdout, argv[0], usage);
209 printf("\nTo see more help on available options, do %s -h\n\n", argv[0]);
210 exit(1);
211 }
212 if (esl_opt_GetBoolean(go, "-h") == TRUE)
213 {
214 if (banner != NULL) esl_banner(stdout, argv[0], banner);
215 if (usage != NULL) esl_usage (stdout, argv[0], usage);
216 puts("\nOptions:");
217 esl_opt_DisplayHelp(stdout, go, 0, 2, 80);
218 exit(0);
219 }
220 if (nargs != -1 && esl_opt_ArgNumber(go) != nargs)
221 {
222 puts("Incorrect number of command line arguments.");
223 esl_usage(stdout, argv[0], usage);
224 printf("\nTo see more help on available options, do %s -h\n\n", argv[0]);
225 exit(1);
226 }
227 return go;
228 }
229
230
231 /* Function: esl_getopts_Reuse()
232 * Synopsis: Reset application state to default.
233 *
234 * Purpose: Reset application configuration <g> to initial defaults,
235 * as if it were newly created (before any
236 * processing of environment, config files, or
237 * command line).
238 *
239 * Returns: <eslOK> on success.
240 *
241 * Throws: (no abnormal error conditions)
242 *
243 * Xref: J4/24.
244 */
245 int
esl_getopts_Reuse(ESL_GETOPTS * g)246 esl_getopts_Reuse(ESL_GETOPTS *g)
247 {
248 int i;
249
250 /* Restore defaults for all options */
251 for (i = 0; i < g->nopts; i++)
252 {
253 if (g->valloc[i] > 0) { free(g->val[i]); }
254 g->val[i] = g->opt[i].defval;
255 g->setby[i] = eslARG_SETBY_DEFAULT;
256 g->valloc[i] = 0;
257 }
258
259 if (g->spoof != NULL) free(g->spoof);
260 if (g->spoof_argv != NULL) free(g->spoof_argv);
261
262 g->argc = 0;
263 g->argv = NULL;
264 g->optind = 1;
265 g->nfiles = 0;
266 g->optstring = NULL;
267 g->spoof = NULL;
268 g->spoof_argv = NULL;
269 g->errbuf[0] = '\0';
270 return eslOK;
271 }
272
273
274 /* Function: esl_getopts_Destroy()
275 * Synopsis: Destroys an <ESL_GETOPTS> object.
276 *
277 * Purpose: Free's a created <ESL_GETOPTS> object.
278 *
279 * Returns: void.
280 */
281 void
esl_getopts_Destroy(ESL_GETOPTS * g)282 esl_getopts_Destroy(ESL_GETOPTS *g)
283 {
284 int i;
285
286 if (g != NULL)
287 {
288 if (g->val != NULL)
289 {
290 /* A few of our vals may have been allocated.
291 */
292 for (i = 0; i < g->nopts; i++)
293 if (g->valloc[i] > 0)
294 free(g->val[i]);
295 free(g->val);
296 }
297 if (g->setby != NULL) free(g->setby);
298 if (g->valloc != NULL) free(g->valloc);
299 if (g->spoof != NULL) free(g->spoof);
300 if (g->spoof_argv != NULL) free(g->spoof_argv);
301 free(g);
302 }
303 }
304
305
306 /* Function: esl_getopts_Dump()
307 * Synopsis: Dumps a summary of a <ESL_GETOPTS> configuration.
308 *
309 * Purpose: Dump the state of <g> to an output stream
310 * <ofp>, often stdout or stderr.
311 */
312 void
esl_getopts_Dump(FILE * ofp,ESL_GETOPTS * g)313 esl_getopts_Dump(FILE *ofp, ESL_GETOPTS *g)
314 {
315 int i, j;
316
317 if (g->argv != NULL)
318 {
319 fprintf(ofp, "argv[0]: %s\n", g->argv[0]);
320 for (i = 1, j = g->optind; j < g->argc; j++, i++)
321 fprintf(ofp, "argument %2d (argv[%2d]): %s\n", i, j, g->argv[j]);
322 fputc('\n', ofp);
323 }
324
325 fprintf(ofp, "%12s %12s %9s\n", "Option", "Setting", "Set by");
326 fprintf(ofp, "------------ ------------ ---------\n");
327
328 for (i = 0; i < g->nopts; i++)
329 {
330 fprintf(ofp, "%-12s ", g->opt[i].name);
331
332 if (g->opt[i].type == eslARG_NONE) fprintf(ofp, "%-12s ", g->val[i] == NULL ? "off" : "on");
333 else fprintf(ofp, "%-12s ", g->val[i]);
334
335 if (g->setby[i] == eslARG_SETBY_DEFAULT) fprintf(ofp, "(default) ");
336 else if (g->setby[i] == eslARG_SETBY_CMDLINE) fprintf(ofp, "cmdline ");
337 else if (g->setby[i] == eslARG_SETBY_ENV) fprintf(ofp, "environ ");
338 else if (g->setby[i] >= eslARG_SETBY_CFGFILE) fprintf(ofp, "cfgfile ");
339
340 fprintf(ofp, "\n");
341 }
342 return;
343 }
344
345
346 /*****************************************************************
347 *# 2. Setting and testing a configuration
348 *****************************************************************/
349
350 /* Function: esl_opt_ProcessConfigfile()
351 * Synopsis: Parses options in a config file.
352 *
353 * Purpose: Given an open configuration file <fp> (and
354 * its name <filename>, for error reporting),
355 * parse it and set options in <g> accordingly.
356 * Anything following a <\#> in the file is a
357 * comment. Blank (or all-comment) lines are
358 * ignored. Data lines contain one option and
359 * its optional argument: for example <--foo arg>
360 * or <-a>. All option arguments are type and
361 * range checked, as specified in <g>.
362 *
363 * Returns: <eslOK> on success.
364 *
365 * Returns <eslESYNTAX> on parse or format error in the
366 * file, or f option argument fails a type or range check,
367 * or if an option is set twice by the same config file.
368 * In any of these "normal" (user) error cases, <g->errbuf>
369 * is set to a useful error message to indicate the error.
370 *
371 * Throws: <eslEMEM> on allocation problem.
372 */
373 int
esl_opt_ProcessConfigfile(ESL_GETOPTS * g,char * filename,FILE * fp)374 esl_opt_ProcessConfigfile(ESL_GETOPTS *g, char *filename, FILE *fp)
375 {
376 char *buf = NULL;
377 int n = 0;
378 char *s;
379 char *optname; /* tainted: from user's input file */
380 char *optarg; /* tainted: from user's input file */
381 char *comment;
382 int line;
383 int opti;
384 int status;
385
386 line = 0;
387 while ((status = esl_fgets(&buf, &n, fp)) != eslEOF)
388 {
389 if (status != eslOK) return status; /* esl_fgets() failed (EMEM) */
390
391 line++;
392 optname = NULL;
393 optarg = NULL;
394
395 /* First token is the option, e.g. "--foo"
396 */
397 s = buf;
398 esl_strtok(&s, " \t\n", &optname);
399 if (optname == NULL) continue; /* blank line */
400 if (*optname == '#') continue; /* comment line */
401 if (*optname != '-')
402 ESL_FAIL(eslESYNTAX, g->errbuf,
403 "Parse failed at line %d of cfg file %.24s (saw %.24s, not an option)\n",
404 line, filename, optname);
405
406 /* Second token, if present, is the arg
407 */
408 if (*s == '"') esl_strtok(&s, "\"", &optarg); /* quote-delimited arg */
409 else esl_strtok(&s, " \t\n", &optarg); /* space-delimited arg */
410
411 /* Anything else on the line had better be a comment
412 */
413 esl_strtok(&s, " \t\n", &comment);
414 if (comment != NULL && *comment != '#')
415 ESL_FAIL(eslESYNTAX, g->errbuf,
416 "Parse failed at line %d of cfg file %.24s (saw %.24s, not a comment)\n",
417 line, filename, comment);
418
419 /* Now we've got an optname and an optional optarg;
420 * figure out what option this is.
421 */
422 if (get_optidx_exactly(g, optname, &opti) != eslOK)
423 ESL_FAIL(eslESYNTAX, g->errbuf,
424 "%.24s is not a recognized option (config file %.24s, line %d)\n",
425 optname, filename, line);
426
427 /* Set that option.
428 * Pass TRUE to set_option's do_alloc flag, because our buffer
429 * is volatile memory that's going away soon - set_option needs
430 * to strdup the arg, not just point to it.
431 */
432 status = set_option(g, opti, optarg,
433 eslARG_SETBY_CFGFILE+g->nfiles,
434 TRUE);
435 if (status != eslOK) return status;
436 }
437
438 if (buf != NULL) free(buf);
439 g->nfiles++;
440 return eslOK;
441 }
442
443
444
445
446 /* Function: esl_opt_ProcessEnvironment()
447 * Synopsis: Parses options in the environment.
448 *
449 * Purpose: For any option defined in <g> that can be modified
450 * by an environment variable, check the environment
451 * and set that option accordingly. The value provided
452 * by the environment is type and range checked.
453 * When an option is turned on that has other options
454 * toggle-tied to it, those options are turned off.
455 * An option's state may only be changed once by the
456 * environment (even indirectly thru toggle-tying);
457 * else an error is generated.
458 *
459 * Returns: <eslOK> on success, and <g> is loaded with all
460 * options specified in the environment.
461 *
462 * Returns <eslEINVAL> on user input problems,
463 * including type/range check failures, and
464 * sets <g->errbuf> to a useful error message.
465 *
466 * Throws: <eslEMEM> on allocation problem.
467 */
468 int
esl_opt_ProcessEnvironment(ESL_GETOPTS * g)469 esl_opt_ProcessEnvironment(ESL_GETOPTS *g)
470 {
471 int i;
472 char *optarg;
473 int status;
474
475 for (i = 0; i < g->nopts; i++)
476 if (g->opt[i].envvar != NULL &&
477 (optarg = getenv(g->opt[i].envvar)) != NULL)
478 {
479 status = set_option(g, i, optarg, eslARG_SETBY_ENV, FALSE);
480 if (status != eslOK) return status;
481 }
482 return eslOK;
483 }
484
485
486
487 /* Function: esl_opt_ProcessCmdline()
488 * Synopsis: Parses options from the command line.
489 *
490 * Purpose: Process a command line (<argc> and <argv>), parsing out
491 * and setting application options in <g>. Option arguments
492 * are type and range checked before they are set, if type
493 * and range information was set when <g> was created.
494 * When an option is set, if it has any other options
495 * "toggle-tied" to it, those options are also turned off.
496 *
497 * Any given option can only change state (on/off) once
498 * per command line; trying to set the same option more than
499 * once generates an error.
500 *
501 * On successful return, <g> contains settings of all
502 * command line options and their option arguments, for
503 * subsequent retrieval by <esl_opt_Get*()>
504 * functions. <g> also contains an <optind> state variable
505 * pointing to the next <argv[]> element that is not an
506 * option. <esl_opt_GetArg()> needs this to know
507 * where the options end and command line arguments begin
508 * in <argv[0]>.
509 *
510 * The parser starts with <argv[1]> and reads <argv[]> elements
511 * in order until it reaches an element that is not an option;
512 * at this point, all subsequent <argv[]> elements are
513 * interpreted as arguments to the application.
514 *
515 * Any <argv[]> element encountered in the command line that
516 * starts with <- > is an option, except <- > or <-- > by
517 * themselves. <- > by itself is interpreted as a command
518 * line argument (usually meaning ``read from stdin instead
519 * of a filename''). <-- > by itself is interpreted as
520 * ``end of options''; all subsequent <argv[]> elements are
521 * interpreted as command-line arguments even if they
522 * begin with <- >.
523 *
524 * Returns: <eslOK> on success. <g> is loaded with
525 * all option settings specified on the cmdline.
526 * Returns <eslEINVAL> on any cmdline parsing problem,
527 * including option argument type/range check failures,
528 * and sets <g->errbuf> to a useful error message for
529 * the user.
530 *
531 * Throws: <eslEMEM> on allocation problem.
532 */
533 int
esl_opt_ProcessCmdline(ESL_GETOPTS * g,int argc,char ** argv)534 esl_opt_ProcessCmdline(ESL_GETOPTS *g, int argc, char **argv)
535 {
536 int opti;
537 char *optarg;
538 int status, setstatus;
539
540 g->argc = argc;
541 g->argv = argv;
542 g->optind = 1; /* start at argv[1] */
543 g->optstring = NULL; /* not in a -abc optstring yet */
544
545 /* Walk through each option in the command line using esl_getopts(),
546 * which advances g->optind as the index of the next argv element we need
547 * to look at.
548 */
549 while ((status = esl_getopts(g, &opti, &optarg)) == eslOK)
550 {
551 setstatus = set_option(g, opti, optarg, eslARG_SETBY_CMDLINE, FALSE);
552 if (setstatus != eslOK) return setstatus;
553 }
554 if (status == eslEOD) return eslOK;
555 else return status;
556 }
557
558
559 /* Function: esl_opt_ProcessSpoof()
560 * Synopsis: Parses a string as if it were a command line.
561 *
562 * Purpose: Process the string <cmdline> as if it were a
563 * complete command line.
564 *
565 * Essentially the same as <esl_opt_ProcessCmdline()>
566 * except that whitespace-delimited tokens first need to be
567 * identified in the <cmdline> first, then passed as
568 * <argc>,<argv> to <esl_opt_ProcessCmdline()>.
569 *
570 * Returns: <eslOK> on success, and <g> is loaded with the
571 * application configuration.
572 *
573 * Returns <eslEINVAL> on any parsing problem, and sets
574 * <g->errbuf> to an informative error message.
575 *
576 * Throws: <eslEMEM> on allocation failure.
577 *
578 * Xref: J4/24.
579 */
580 int
esl_opt_ProcessSpoof(ESL_GETOPTS * g,const char * cmdline)581 esl_opt_ProcessSpoof(ESL_GETOPTS *g, const char *cmdline)
582 {
583 int argc = 0;
584 char *s = NULL;
585 void *p;
586 char *tok;
587 int status;
588
589 if (g->spoof != NULL || g->spoof_argv != NULL)
590 ESL_XFAIL(eslEINVAL, g->errbuf, "cannot process more than one spoofed command line");
591
592 if ((status = esl_strdup(cmdline, -1, &(g->spoof))) != eslOK) goto ERROR;
593 s = g->spoof;
594
595 while (esl_strtok(&s, " \t\n", &tok) == eslOK)
596 {
597 argc++;
598 ESL_RALLOC(g->spoof_argv, p, sizeof(char *) * argc);
599 g->spoof_argv[argc-1] = tok;
600 }
601
602 status = esl_opt_ProcessCmdline(g, argc, g->spoof_argv);
603 return status;
604
605 ERROR:
606 if (g->spoof != NULL) { free(g->spoof); g->spoof = NULL; }
607 if (g->spoof_argv != NULL) { free(g->spoof_argv); g->spoof_argv = NULL; }
608 return status;
609 }
610
611 /* Function: esl_opt_VerifyConfig()
612 * Synopsis: Validates configuration after options are set.
613 *
614 * Purpose: Given a <g> that we think is fully configured now --
615 * from config file(s), environment, and command line --
616 * verify that the configuration is self-consistent:
617 * for every option that is set, make sure that any
618 * required options are also set, and that no
619 * incompatible options are set. ``Set'' means
620 * the configured value is non-default and non-NULL (including booleans),
621 * and ``not set'' means the value is default or NULL. (That is,
622 * we don't go solely by <setby>, which refers to who
623 * determined the state of an option, even if
624 * it is turned off.)
625 *
626 * Returns: <eslOK> on success.
627 * <eslESYNTAX> if a required option is not set, or
628 * if an incompatible option is set; in this case, sets
629 * <g->errbuf> to contain a useful error message for
630 * the user.
631 *
632 * Throws: <eslEINVAL> if something's wrong with the <ESL_OPTIONS>
633 * structure itself -- a coding error in the application.
634 */
635 int
esl_opt_VerifyConfig(ESL_GETOPTS * g)636 esl_opt_VerifyConfig(ESL_GETOPTS *g)
637 {
638 int i,reqi,incompati;
639 char *s;
640 int status;
641
642 /* For all options that are set (not in default configuration,
643 * and turned on with non-NULL vals),
644 * verify that all their required_opts are set.
645 */
646 for (i = 0; i < g->nopts; i++)
647 {
648 if (g->setby[i] != eslARG_SETBY_DEFAULT && g->val[i] != NULL)
649 {
650 s = g->opt[i].required_opts;
651 while ((status = process_optlist(g, &s, &reqi)) != eslEOD)
652 {
653 if (status != eslOK) ESL_EXCEPTION(eslEINVAL, "something's wrong with format of optlist: %s\n", s);
654 if (g->val[reqi] == NULL)
655 {
656 if (g->setby[i] >= eslARG_SETBY_CFGFILE)
657 ESL_FAIL(eslESYNTAX, g->errbuf, "Option %.24s (set by cfg file %d) requires (or has no effect without) option(s) %.24s",
658 g->opt[i].name, g->setby[i]-2, g->opt[i].required_opts);
659 else if (g->setby[i] == eslARG_SETBY_ENV)
660 ESL_FAIL(eslESYNTAX, g->errbuf, "Option %.24s (set by env var %s) requires (or has no effect without) option(s) %.24s",
661 g->opt[i].name, g->opt[i].envvar, g->opt[i].required_opts);
662 else
663 ESL_FAIL(eslESYNTAX, g->errbuf, "Option %.24s requires (or has no effect without) option(s) %.24s",
664 g->opt[i].name, g->opt[i].required_opts);
665 }
666 }
667 }
668 }
669
670 /* For all options that are set (turned on with non-NULL vals),
671 * verify that no incompatible options are set to non-default
672 * values (notice the setby[incompati] check)
673 */
674 for (i = 0; i < g->nopts; i++)
675 {
676 if (g->setby[i] != eslARG_SETBY_DEFAULT && g->val[i] != NULL)
677 {
678 s = g->opt[i].incompat_opts;
679 while ((status = process_optlist(g, &s, &incompati)) != eslEOD)
680 {
681 if (status != eslOK) ESL_EXCEPTION(eslEINVAL, "something's wrong with format of optlist: %s\n", s);
682 if (incompati != i && (g->setby[incompati] != eslARG_SETBY_DEFAULT && g->val[incompati] != NULL))
683 {
684 if (g->setby[i] >= eslARG_SETBY_CFGFILE)
685 ESL_FAIL(eslESYNTAX, g->errbuf, "Option %.24s (set by cfg file %d) is incompatible with option(s) %.24s",
686 g->opt[i].name, g->setby[i]-2, g->opt[i].incompat_opts);
687
688 else if (g->setby[i] == eslARG_SETBY_ENV)
689 ESL_FAIL(eslESYNTAX, g->errbuf, "Option %.24s (set by env var %s) is incompatible with option(s) %.24s",
690 g->opt[i].name, g->opt[i].envvar, g->opt[i].incompat_opts);
691 else
692 ESL_FAIL(eslESYNTAX, g->errbuf, "Option %.24s is incompatible with option(s) %.24s",
693 g->opt[i].name, g->opt[i].incompat_opts);
694 }
695 }
696 }
697 }
698 return eslOK;
699 }
700
701 /* Function: esl_opt_ArgNumber()
702 * Synopsis: Returns number of command line arguments.
703 *
704 * Purpose: Returns the number of command line arguments.
705 *
706 * Caller must have already called
707 * <esl_opt_ProcessCmdline()>, in order for all the options
708 * to be parsed first. Everything left on the command line
709 * is taken to be an argument.
710 */
711 int
esl_opt_ArgNumber(const ESL_GETOPTS * g)712 esl_opt_ArgNumber(const ESL_GETOPTS *g)
713 {
714 return ((g)->argc - (g)->optind);
715 }
716
717
718 /* Function: esl_opt_SpoofCmdline()
719 * Synopsis: Create faux command line from current option configuration.
720 *
721 * Purpose: Given the current configuration state of the application
722 * <g>, create a command line that would recreate the same
723 * state by itself (without any environment or config file
724 * settings), and return it in <*ret_cmdline>.
725 *
726 * Returns: <eslOK> on success. The <*ret_cmdline> is allocated here,
727 * and caller is responsible for freeing it.
728 *
729 * Throws: <eslEMEM> on allocation error, and <*ret_cmdline> is <NULL>.
730 *
731 * Xref: J4/24
732 */
733 int
esl_opt_SpoofCmdline(const ESL_GETOPTS * g,char ** ret_cmdline)734 esl_opt_SpoofCmdline(const ESL_GETOPTS *g, char **ret_cmdline)
735 {
736 char *cmdline = NULL;
737 char *p = NULL;
738 int ntot = 0;
739 int n;
740 int i, j;
741 int status;
742
743 /* Application name/path */
744 ntot = strlen(g->argv[0]) + 1;
745 ESL_ALLOC(cmdline, sizeof(char) * (ntot+1));
746 sprintf(cmdline, "%s ", g->argv[0]);
747
748 /* Options */
749 for (i = 0; i < g->nopts; i++)
750 if (g->setby[i] != eslARG_SETBY_DEFAULT)
751 {
752 if (g->opt[i].type == eslARG_NONE) n = strlen(g->opt[i].name) + 1;
753 else n = (strlen(g->opt[i].name) + strlen(g->val[i])) + 2;
754
755 ESL_RALLOC(cmdline, p, sizeof(char) * (ntot + n + 1));
756
757 if (g->opt[i].type == eslARG_NONE) sprintf(cmdline + ntot, "%s ", g->opt[i].name);
758 else sprintf(cmdline + ntot, "%s %s ", g->opt[i].name, g->val[i]);
759
760 ntot += n;
761 }
762
763 /* Arguments */
764 for (j = g->optind; j < g->argc; j++)
765 {
766 n = strlen(g->argv[j]) + 1;
767 ESL_RALLOC(cmdline, p, sizeof(char) * (ntot + n + 1));
768 sprintf(cmdline + ntot, "%s ", g->argv[j]);
769 ntot += n;
770 }
771
772 /* Terminate */
773 cmdline[ntot] = '\0';
774 *ret_cmdline = cmdline;
775 return eslOK;
776
777 ERROR:
778 if (cmdline != NULL) free(cmdline);
779 *ret_cmdline = NULL;
780 return status;
781 }
782
783 /*****************************************************************
784 *# 3. Retrieving option settings and command line args
785 *****************************************************************/
786
787 /* Function: esl_opt_IsDefault()
788 * Synopsis: Returns <TRUE> if option remained at default setting.
789 *
790 * Purpose: Returns <TRUE> if option <optname> is in its
791 * default state; returns <FALSE> if <optname> was
792 * changed on the command line, in the environment, or in
793 * a configuration file.
794 */
795 int
esl_opt_IsDefault(const ESL_GETOPTS * g,char * optname)796 esl_opt_IsDefault(const ESL_GETOPTS *g, char *optname)
797 {
798 int opti;
799
800 if (get_optidx_exactly(g, optname, &opti) != eslOK) esl_fatal("no such option %s\n", optname);
801 if (g->setby[opti] == eslARG_SETBY_DEFAULT) return TRUE;
802
803 if (g->val[opti] == NULL && g->opt[opti].defval == NULL) return TRUE;
804 if (esl_strcmp(g->opt[opti].defval, g->val[opti]) == 0) return TRUE; /* option may have been set but restored to original default value */
805 return FALSE;
806 }
807
808 /* Function: esl_opt_IsOn()
809 * Synopsis: Returns <TRUE> if option is set to a non-<NULL> value.
810 *
811 * Purpose: Returns <TRUE> if option is on (set to a non-<NULL>
812 * value).
813 *
814 * This is most useful when using integer-, real-, char-,
815 * or string-valued options also as boolean switches, where
816 * they can either be OFF, or they can be turned ON by
817 * having a value. Caller can test <esl_opt_IsOn()> to see
818 * if the option's active at all, then use
819 * <esl_opt_GetString()> or whatever to extract the option
820 * value.
821 *
822 * For a boolean option, the result is identical to
823 * <esl_opt_GetBoolean()>.
824 *
825 * Xref: J4/83.
826 */
827 int
esl_opt_IsOn(const ESL_GETOPTS * g,char * optname)828 esl_opt_IsOn(const ESL_GETOPTS *g, char *optname)
829 {
830 int opti;
831
832 if (get_optidx_exactly(g, optname, &opti) != eslOK) esl_fatal("no such option %s\n", optname);
833 if (g->val[opti] == NULL) return FALSE;
834 else return TRUE;
835 }
836
837
838 /* Function: esl_opt_IsUsed()
839 * Synopsis: Returns <TRUE> if option is on, and this is not the default.
840 *
841 * Purpose: Returns <TRUE> if option <optname> is in use: it has been
842 * set to a non-default value, and that value correspond to
843 * the option being "on" (a non-<NULL> value).
844 *
845 * This is used in printing application headers, where
846 * we want to report all the options that are in effect that
847 * weren't already on by default.
848 *
849 * Xref: J4/83
850 */
851 int
esl_opt_IsUsed(const ESL_GETOPTS * g,char * optname)852 esl_opt_IsUsed(const ESL_GETOPTS *g, char *optname)
853 {
854 int opti;
855
856 if (get_optidx_exactly(g, optname, &opti) != eslOK) esl_fatal("no such option %s\n", optname);
857 if (esl_opt_IsDefault(g, optname)) return FALSE;
858 if (g->val[opti] == NULL) return FALSE;
859 return TRUE;
860 }
861
862
863 /* Function: esl_opt_GetSetter()
864 * Synopsis: Returns code for who set this option.
865 *
866 * Purpose: For a processed options object <g>, return the code
867 * for who set option <optname>. This code is <eslARG_SETBY_DEFAULT>,
868 * <eslARG_SETBY_CMDLINE>, <eslARG_SETBY_ENV>, or it
869 * is $\geq$ <eslARG_SETBY_CFGFILE>. If the option
870 * was configured by a config file, the file number (the order
871 * of <esl_opt_ProcessConfigFile()> calls) is encoded in codes
872 * $\geq <eslARG_SETBY_CFGFILE>$ as
873 * file number $=$ <code> - <eslARG_SETBY_CFGFILE> + 1.
874 */
875 int
esl_opt_GetSetter(const ESL_GETOPTS * g,char * optname)876 esl_opt_GetSetter(const ESL_GETOPTS *g, char *optname)
877 {
878 int opti;
879
880 if (get_optidx_exactly(g, optname, &opti) != eslOK) esl_fatal("no such option %s\n", optname);
881 return g->setby[opti];
882 }
883
884
885 /* Function: esl_opt_GetBoolean()
886 * Synopsis: Retrieve <TRUE>/<FALSE> for a boolean option.
887 *
888 * Purpose: Retrieves the configured TRUE/FALSE value for option <optname>
889 * from <g>.
890 */
891 int
esl_opt_GetBoolean(const ESL_GETOPTS * g,char * optname)892 esl_opt_GetBoolean(const ESL_GETOPTS *g, char *optname)
893 {
894 int opti;
895
896 if (get_optidx_exactly(g, optname, &opti) == eslENOTFOUND)
897 esl_fatal("no such option %s\n", optname);
898 if (g->opt[opti].type != eslARG_NONE)
899 esl_fatal("option %s is not a boolean; code called _GetBoolean", optname);
900
901 if (g->val[opti] == NULL) return FALSE;
902 else return TRUE;
903 }
904
905 /* Function: esl_opt_GetInteger()
906 * Synopsis: Retrieve value of an integer option.
907 *
908 * Purpose: Retrieves the configured value for option <optname>
909 * from <g>.
910 */
911 int
esl_opt_GetInteger(const ESL_GETOPTS * g,char * optname)912 esl_opt_GetInteger(const ESL_GETOPTS *g, char *optname)
913 {
914 int opti;
915
916 if (get_optidx_exactly(g, optname, &opti) == eslENOTFOUND)
917 esl_fatal("no such option %s\n", optname);
918 if (g->opt[opti].type != eslARG_INT)
919 esl_fatal("option %s does not take an integer arg; code called _GetInteger", optname);
920 return atoi(g->val[opti]);
921 }
922
923 /* Function: esl_opt_GetReal()
924 * Synopsis: Retrieve value of a real-valued option.
925 *
926 * Purpose: Retrieves the configured value for option <optname>
927 * from <g>.
928 */
929 double
esl_opt_GetReal(const ESL_GETOPTS * g,char * optname)930 esl_opt_GetReal(const ESL_GETOPTS *g, char *optname)
931 {
932 int opti;
933
934 if (get_optidx_exactly(g, optname, &opti) == eslENOTFOUND)
935 esl_fatal("no such option %s\n", optname);
936 if (g->opt[opti].type != eslARG_REAL)
937 esl_fatal("option %s does not take a real-valued arg; code called _GetReal", optname);
938
939 return (atof(g->val[opti]));
940 }
941
942 /* Function: esl_opt_GetChar()
943 * Synopsis: Retrieve value of a character option.
944 *
945 * Purpose: Retrieves the configured value for option <optname>
946 * from <g>.
947 */
948 char
esl_opt_GetChar(const ESL_GETOPTS * g,char * optname)949 esl_opt_GetChar(const ESL_GETOPTS *g, char *optname)
950 {
951 int opti;
952
953 if (get_optidx_exactly(g, optname, &opti) == eslENOTFOUND)
954 esl_fatal("no such option %s\n", optname);
955 if (g->opt[opti].type != eslARG_CHAR)
956 esl_fatal("option %s does not take a char arg; code called _GetChar", optname);
957
958 return (*g->val[opti]);
959 }
960
961 /* Function: esl_opt_GetString()
962 * Synopsis: Retrieve value of a string option.
963 *
964 * Purpose: Retrieves the configured value for option <optname>
965 * from <g>.
966 *
967 * This retrieves options of type <eslARG_STRING>,
968 * obviously, but also options of type <eslARG_INFILE>
969 * and <eslARG_OUTFILE>.
970 */
971 char *
esl_opt_GetString(const ESL_GETOPTS * g,char * optname)972 esl_opt_GetString(const ESL_GETOPTS *g, char *optname)
973 {
974 int opti;
975
976 if (get_optidx_exactly(g, optname, &opti) == eslENOTFOUND)
977 esl_fatal("no such option %s\n", optname);
978 if (g->opt[opti].type != eslARG_STRING &&
979 g->opt[opti].type != eslARG_INFILE &&
980 g->opt[opti].type != eslARG_OUTFILE)
981 esl_fatal("option %s does not take a string arg; code called _GetString", optname);
982
983 return g->val[opti];
984 }
985
986
987 /* Function: esl_opt_GetArg()
988 * Synopsis: Retrieve numbered command line argument.
989 *
990 * Purpose: Returns a pointer to command line argument number
991 * <which>, where <which> ranges from <1..n> for <n>
992 * total arguments.
993 *
994 * If the caller has already verified that <n> arguments
995 * exist by testing <esl_opt_ArgNumber(g) == n>,
996 * <esl_opt_GetArg()> is guaranteed to return non-<NULL>
997 * arguments for <which = 1..n>.
998 *
999 * Caller is responsible for verifying that the argument
1000 * makes sense for what it's supposed to be.
1001 *
1002 * Returns: A pointer to command line argument <which> on success, or
1003 * <NULL> if there is no such argument.
1004 */
1005 char *
esl_opt_GetArg(const ESL_GETOPTS * g,int which)1006 esl_opt_GetArg(const ESL_GETOPTS *g, int which)
1007 {
1008 if (which <= 0) return NULL;
1009 if (g->optind+which-1 >= g->argc) return NULL;
1010 return g->argv[g->optind+which-1];
1011 }
1012
1013
1014 /*****************************************************************
1015 * 4. Formatting option help
1016 *****************************************************************/
1017
1018 /* Function: esl_opt_DisplayHelp()
1019 * Synopsis: Formats one-line help for each option.
1020 *
1021 * Purpose: For each option in <go>, print one line of brief
1022 * documentation for it, consisting of the option name
1023 * (and argument, if any) and the help string. If space
1024 * allows, default values for the options (if any) are
1025 * shown in brackets. If space still allows, range restrictions
1026 * for the options (if any) are shown in parentheses.
1027 *
1028 * If <docgroup> is non-zero, help lines are only printed
1029 * for options with the matching <go->opt[i].docgrouptag>.
1030 * This allows the caller to group option documentation
1031 * into multiple sections with different headers. To
1032 * print all options in one call, pass 0 for <docgroup>.
1033 *
1034 * <indent> specifies how many spaces to prefix each line with.
1035 *
1036 * <textwidth> specifies the maximum text width for the
1037 * line. This would typically be 80 characters. Lines are
1038 * not allowed to exceed this length. If a line does exceed
1039 * this length, range restriction display is silently
1040 * dropped (for all options). If any line still exceeds
1041 * <textwidth>, the default value display is silently dropped,
1042 * for all options. If any line still exceeds <textwidth>, even
1043 * though it now consists almost solely of the option name and
1044 * its help string, an <eslEINVAL> error is thrown. The
1045 * caller should either shorten the help string(s) or
1046 * increase the <textwidth>.
1047 *
1048 * Returns: <eslOK> on success.
1049 *
1050 * Throws: <eslEINVAL> if one or more help lines are too long for
1051 * the specified <textwidth>.
1052 * <eslEWRITE> if a write fails.
1053 */
1054 int
esl_opt_DisplayHelp(FILE * ofp,const ESL_GETOPTS * go,int docgroup,int indent,int textwidth)1055 esl_opt_DisplayHelp(FILE *ofp, const ESL_GETOPTS *go, int docgroup, int indent,
1056 int textwidth)
1057 {
1058 int optwidth = 0; /* maximum width for "-foo <n>" options */
1059 int helpwidth[3] = {0,0,0}; /* 0=everything; 1=with defaults, no range; 2=help string only */
1060 int show_defaults;
1061 int show_ranges;
1062 int i, n;
1063
1064 /* Figure out the field widths we need in the output.
1065 */
1066 for (i = 0; i < go->nopts; i++)
1067 if (! docgroup || docgroup == go->opt[i].docgrouptag)
1068 {
1069 n = strlen(go->opt[i].name); /* "--foo" */
1070 if (go->opt[i].type != eslARG_NONE) n += 4; /* + " <n>" */
1071 if (n > optwidth) optwidth = n;
1072
1073 n = 2; /* init with " : " */
1074 if (go->opt[i].help != NULL)
1075 n = strlen(go->opt[i].help) + 1; /* include " " in width */
1076 if (n > helpwidth[2]) helpwidth[2] = n;
1077
1078 if (go->opt[i].defval != NULL)
1079 n += strlen(go->opt[i].defval) + 4; /* include " []" in width */
1080 if (n > helpwidth[1]) helpwidth[1] = n;
1081
1082 if (go->opt[i].range != NULL)
1083 n += strlen(go->opt[i].range) + 4; /* include " ()" in width */
1084 if (n > helpwidth[0]) helpwidth[0] = n;
1085 }
1086
1087 /* Figure out what we have room for.
1088 */
1089 if (indent + optwidth + helpwidth[0] <= textwidth)
1090 {
1091 show_defaults = TRUE;
1092 show_ranges = TRUE;
1093 }
1094 else if (indent + optwidth + helpwidth[1] <= textwidth)
1095 {
1096 show_defaults = TRUE;
1097 show_ranges = FALSE;
1098 }
1099 else if (indent + optwidth + helpwidth[2] <= textwidth)
1100 {
1101 show_defaults = FALSE;
1102 show_ranges = FALSE;
1103 }
1104 else ESL_EXCEPTION(eslEINVAL, "Help line too long");
1105
1106 /* Format and print the options in this docgroup. */
1107 for (i = 0; i < go->nopts; i++)
1108 if (! docgroup || docgroup == go->opt[i].docgrouptag)
1109 {
1110 if (fprintf(ofp, "%*s", indent, "") < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed");
1111 n = 0;
1112 if (fprintf(ofp, "%s", go->opt[i].name) < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed");
1113 n += strlen(go->opt[i].name);
1114
1115 switch (go->opt[i].type) {
1116 case eslARG_NONE: break;
1117 case eslARG_INT: if (fprintf(ofp, " <n>") < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed"); n += 4; break;
1118 case eslARG_REAL: if (fprintf(ofp, " <x>") < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed"); n += 4; break;
1119 case eslARG_CHAR: if (fprintf(ofp, " <c>") < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed"); n += 4; break;
1120 case eslARG_STRING: if (fprintf(ofp, " <s>") < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed"); n += 4; break;
1121 case eslARG_INFILE: if (fprintf(ofp, " <f>") < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed"); n += 4; break;
1122 case eslARG_OUTFILE: if (fprintf(ofp, " <f>") < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed"); n += 4; break;
1123 }
1124
1125 if (fprintf(ofp, "%*s", optwidth-n, "") < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed");
1126 if (fprintf(ofp, " :") < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed");
1127
1128 if (go->opt[i].help != NULL)
1129 { if (fprintf(ofp, " %s", go->opt[i].help) < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed"); }
1130
1131 if (show_defaults && go->opt[i].defval != NULL)
1132 if (go->opt[i].type != eslARG_CHAR || *(go->opt[i].defval) != '\0')
1133 { if (fprintf(ofp, " [%s]", go->opt[i].defval) < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed"); }
1134
1135 if (show_ranges && go->opt[i].range != NULL)
1136 { if (fprintf(ofp, " (%s)", go->opt[i].range) < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed"); }
1137
1138 if (fprintf(ofp, "\n") < 0) ESL_EXCEPTION_SYS(eslEWRITE, "write failed");
1139 }
1140 return eslOK;
1141 }
1142 /*------------------ end of the public API -----------------------*/
1143
1144
1145
1146
1147
1148 /*****************************************************************
1149 * 5. Miscellaneous private functions
1150 *****************************************************************/
1151
1152 /* set_option()
1153 *
1154 * Turn option <opti> ON (if it's a boolean) or set its option
1155 * argument to <optarg>. Record that it was set by <setby> (e.g.
1156 * <eslARG_SETBY_CMDLINE>).
1157 *
1158 * <do_alloc> is a TRUE/FALSE flag. If <arg> is a pointer to a string
1159 * that isn't going to go away (e.g. into argv[], or into the
1160 * environment) we can get away with just pointing our option's val
1161 * at <arg>. But if <arg> is pointing to something volatile (e.g.
1162 * the line buffer as we're reading a file) then we need to
1163 * strdup the arg -- and remember that we did that, so we free()
1164 * it when we destroy the getopts object.
1165 *
1166 * All user errors (problems with optarg) are normal (returned) errors of
1167 * type <eslESYNTAX>, which leave an error message in <g->errbuf>.
1168 *
1169 * May also throw <eslEMEM> on allocation failure, or <eslEINVAL>
1170 * if something's wrong internally, usually indicating a coding error
1171 * in the application's <ESL_OPTIONS> structure.
1172 */
1173 int
set_option(ESL_GETOPTS * g,int opti,char * optarg,int setby,int do_alloc)1174 set_option(ESL_GETOPTS *g, int opti, char *optarg, int setby, int do_alloc)
1175 {
1176 int arglen;
1177 char *where = NULL;
1178 char *s;
1179 int togi;
1180 int status;
1181 void *tmp;
1182
1183 if (setby == eslARG_SETBY_DEFAULT) where = "as default";
1184 else if (setby == eslARG_SETBY_CMDLINE) where = "on cmdline";
1185 else if (setby == eslARG_SETBY_ENV) where = "in env";
1186 else if (setby >= eslARG_SETBY_CFGFILE) where = "in cfgfile";
1187
1188 /* Have we already set this option? */
1189 if (g->setby[opti] == setby)
1190 ESL_FAIL(eslESYNTAX, g->errbuf,
1191 "Option %.24s has already been set %s.",
1192 g->opt[opti].name, where);
1193
1194 /* Type and range check the option argument.
1195 */
1196 if (verify_type_and_range(g, opti, optarg, setby) != eslOK) return eslESYNTAX;
1197
1198 /* Set the option, being careful about when val
1199 * is alloc'ed vs. not.
1200 */
1201 g->setby[opti] = setby;
1202 if (g->opt[opti].type == eslARG_NONE) /* booleans: any non-NULL is TRUE... */
1203 { /* watch out for booleans getting toggled off/on */
1204 if (g->opt[opti].defval) g->val[opti] = g->opt[opti].defval; /* use default string if provided: IsDefault() needs this */
1205 else g->val[opti] = (char *) TRUE; /* else 0x1 will do fine. */
1206 }
1207 else
1208 {
1209 /* If do_alloc is FALSE or the optarg is NULL, then:
1210 * - free any previous alloc;
1211 * - set the pointer.
1212 */
1213 if (!do_alloc || optarg == NULL)
1214 {
1215 if (g->valloc[opti] > 0) { free(g->val[opti]); g->valloc[opti] = 0; }
1216 g->val[opti] = optarg;
1217 }
1218 /* else do_alloc is TRUE, so:
1219 * - make sure we have enough room, either reallocating or allocating
1220 * - copy the arg.
1221 */
1222 else
1223 {
1224 arglen = strlen(optarg);
1225 if (g->valloc[opti] < arglen+1)
1226 {
1227 if (g->valloc[opti] == 0) ESL_ALLOC (g->val[opti], sizeof(char) * (arglen+1));
1228 else ESL_RALLOC(g->val[opti], tmp, sizeof(char) * (arglen+1));
1229 g->valloc[opti] = arglen+1;
1230 }
1231 strcpy(g->val[opti], optarg);
1232 }
1233 }
1234
1235 /* Unset all options toggle-tied to this one.
1236 */
1237 s = g->opt[opti].toggle_opts;
1238 while ((status = process_optlist(g, &s, &togi)) != eslEOD)
1239 {
1240 if (status != eslOK) ESL_EXCEPTION(eslEINVAL, "something's wrong with format of optlist: %s\n", s);
1241 if (togi == opti) continue; /* ignore ourself, so we can have one toggle list per group */
1242 if (g->val[togi] == NULL) continue; /* it's already off; don't touch it */
1243
1244 if (g->setby[togi] == setby)
1245 ESL_FAIL(eslESYNTAX, g->errbuf,
1246 "Options %.24s and %.24s conflict, toggling each other.",
1247 g->opt[togi].name, g->opt[opti].name);
1248
1249 g->setby[togi] = setby; /* indirectly, but still */
1250 if (g->valloc[togi] > 0) /* careful about val's that were alloc'ed */
1251 { free(g->val[togi]); g->valloc[togi] = 0; }
1252 g->val[togi] = NULL; /* ok for false booleans too */
1253 }
1254 return eslOK;
1255
1256 ERROR:
1257 return status;
1258 }
1259
1260 /* get_optidx_exactly():
1261 *
1262 * Find option named <optname> in <g>; set <ret_opti> to be
1263 * the index of the option, and return eslOK. <optname>
1264 * must exactly match one of the options in <g>.
1265 *
1266 * If the option is not found, return <eslENOTFOUND>; in this
1267 * case <*ret_opti> is -1 (and caller should not use it!)
1268 */
1269 static int
get_optidx_exactly(const ESL_GETOPTS * g,char * optname,int * ret_opti)1270 get_optidx_exactly(const ESL_GETOPTS *g, char *optname, int *ret_opti)
1271 {
1272 int i;
1273
1274 for (i = 0; i < g->nopts; i++)
1275 if (strcmp(optname, g->opt[i].name) == 0) { *ret_opti = i; return eslOK; }
1276 *ret_opti = -1;
1277 return eslENOTFOUND;
1278 }
1279
1280 /* get_optidx_abbrev():
1281 *
1282 * Find option named <optname> in <g>; set <ret_opti> to be the index
1283 * of the option, and return eslOK. Allow <optname> to be an
1284 * abbreviation of one of the option names in <g>, so long as it is
1285 * unambiguous. If <n> is >0, the <optname> has an attached argument
1286 * (--foo=arg) and <n> is the # of characters before the = character
1287 * that we should match to find the option (5, in this example).
1288 *
1289 * If the option is not found, return <eslENOTFOUND>.
1290 * If <optname> ambiguously matches two or more options in <g>,
1291 * return <eslEAMBIGUOUS>.
1292 */
1293 static int
get_optidx_abbrev(ESL_GETOPTS * g,char * optname,int n,int * ret_opti)1294 get_optidx_abbrev(ESL_GETOPTS *g, char *optname, int n, int *ret_opti)
1295 {
1296 int nabbrev = 0;
1297 int nexact = 0;
1298 int i;
1299
1300 if (n == 0) /* unless we're told otherwise: */
1301 n = strlen(optname); /* all of optname abbrev must match against the real name */
1302
1303 for (i = 0; i < g->nopts; i++)
1304 if (strncmp(g->opt[i].name, optname, n) == 0)
1305 {
1306 nabbrev++;
1307 *ret_opti = i;
1308 if (n == strlen(g->opt[i].name)) { nexact++; break; } /* an exact match; can stop now (xref bug #e4) */
1309 }
1310 if (nexact != 1 && nabbrev > 1) return eslEAMBIGUOUS;
1311 if (nabbrev == 0) return eslENOTFOUND;
1312 return eslOK;
1313 }
1314 /*----------- end of private functions for retrieving option indices -------------*/
1315
1316
1317
1318 /*****************************************************************
1319 * Private functions for processing options out of a command line
1320 *****************************************************************/
1321
1322 /* esl_getopts():
1323 *
1324 * Get the next option in argv[], and its argument (if any),
1325 * and pass this information back via <ret_opti> (index of
1326 * next option) and <ret_optarg).
1327 *
1328 * Return <eslOK> on success, <eslEOD> if we're out of
1329 * options.
1330 *
1331 * Returns <eslESYNTAX> and sets <g->errbuf> to a useful error
1332 * message if something's wrong with one of the user's options.
1333 *
1334 * Throws <eslEINVAL> if something's wrong internally with the
1335 * <ESL_OPTIONS> structure.
1336 */
1337 static int
esl_getopts(ESL_GETOPTS * g,int * ret_opti,char ** ret_optarg)1338 esl_getopts(ESL_GETOPTS *g, int *ret_opti, char **ret_optarg)
1339 {
1340 *ret_optarg = NULL;
1341
1342 /* Check to see if we've run out of options.
1343 * A '-' by itself is an argument (e.g. "read from stdin"), not an option.
1344 */
1345 if (g->optstring == NULL &&
1346 (g->optind >= g->argc || g->argv[g->optind][0] != '-' || strcmp(g->argv[g->optind], "-") == 0))
1347 return eslEOD; /* normal end-of-data (end of options) return */
1348
1349 /* Check to see if we're being told that this is the end
1350 * of the options with the special "--" flag.
1351 */
1352 if (g->optstring == NULL &&
1353 strcmp(g->argv[g->optind], "--") == 0)
1354 {
1355 g->optind++;
1356 return eslEOD; /* also a normal end-of-data return */
1357 }
1358
1359 /* We have an option: an argv element that starts with -, but is
1360 * not "-" or "--".
1361 *
1362 * We know the strncmp() test is ok for 2 chars, because if the option was
1363 * 1 char, we would've already caught it above (either it's a bare "-"
1364 * or it's a single non-option char, and in either case it's not an option
1365 * and we returned eslEOD.
1366 *
1367 * Watch out for the case where we're in the middle of a concatenated optstring
1368 * of single-letter options, a la -abc
1369 */
1370 if (g->optstring == NULL && strncmp(g->argv[g->optind], "--", 2) == 0)
1371 return process_longopt(g, ret_opti, ret_optarg);
1372 else
1373 return process_stdopt(g, ret_opti, ret_optarg);
1374 }
1375
1376 /* process_longopt():
1377 *
1378 * optind is sitting on a long option, w/ syntax of one of these forms:
1379 * --foo
1380 * --foo arg
1381 * --foo=arg
1382 * (GNU getopt long option syntax.)
1383 *
1384 * Allow unambiguous abbreviations of long options when matching;
1385 * e.g. --foo is ok for matching a long option --foobar.
1386 *
1387 * Returns <eslOK> on success, returning the option number through
1388 * <ret_opti>, and a ptr to its argument through <ret_optarg> (or NULL
1389 * if this option takes no argument.) Internally, g->optind is
1390 * advanced to next argv element (+1, +2, +1, respectively, for --foo,
1391 * --foo arg, --foo=arg).
1392 *
1393 * Returns <eslESYNTAX> and sets a useful error mesg in <g->errbuf> if:
1394 * 1. Option can't be found in opt[].
1395 * 2. Option abbreviation is ambiguous, matching opt[] nonuniquely.
1396 * 3. Option takes an argument, but no argument found.
1397 * 4. Option does not take an argument, but one was provided by =arg syntax.
1398 * All of these are user input errors.
1399
1400 */
1401 static int
process_longopt(ESL_GETOPTS * g,int * ret_opti,char ** ret_optarg)1402 process_longopt(ESL_GETOPTS *g, int *ret_opti, char **ret_optarg)
1403 {
1404 int opti; /* option number found */
1405 char *argptr; /* ptr to arg in --foo=arg syntax */
1406 int n; /* length of argv elem's option part (up to = or \0) */
1407 int status;
1408
1409 /* Deal with options of syntax "--foo=arg" w/o modifying argv.
1410 */
1411 if ((argptr = strchr(g->argv[g->optind], '=')) != NULL)
1412 { n = argptr - g->argv[g->optind]; argptr++; } /* bump argptr off the = to the arg itself */
1413 else
1414 { n = strlen(g->argv[g->optind]); } /* and argptr == NULL from above. */
1415
1416 /* Figure out which option this is.
1417 * The trick here is to allow abbreviations, and identify
1418 * ambiguities while we're doing it. (GNU getopt allows abbrevs.)
1419 */
1420 status = get_optidx_abbrev(g, g->argv[g->optind], n, &opti);
1421 if (status == eslEAMBIGUOUS)
1422 ESL_FAIL(eslESYNTAX, g->errbuf, "Abbreviated option \"%.24s\" is ambiguous.", g->argv[g->optind]);
1423 else if (status == eslENOTFOUND)
1424 ESL_FAIL(eslESYNTAX, g->errbuf, "No such option \"%.24s\".", g->argv[g->optind]);
1425 else if (status != eslOK)
1426 ESL_EXCEPTION(eslEINCONCEIVABLE, "Something went wrong with option \"%.24s\".", g->argv[g->optind]);
1427
1428 *ret_opti = opti;
1429 g->optind++; /* optind was on the option --foo; advance the counter to next argv element */
1430
1431 /* Find the argument, if there is supposed to be one.
1432 */
1433 if (g->opt[opti].type != eslARG_NONE)
1434 {
1435 if (argptr != NULL) /* if --foo=arg syntax, then we already found it */
1436 *ret_optarg = argptr;
1437 else if (g->optind >= g->argc)
1438 ESL_FAIL(eslESYNTAX, g->errbuf, "Option %.24s requires an argument.", g->opt[opti].name);
1439 else { /* "--foo 666" style, with a space */
1440 *ret_optarg = g->argv[g->optind++]; /* assign optind as the arg, advance counter */
1441
1442 /* Watch out for options masquerading as missing arguments. */
1443 if ((g->opt[opti].type == eslARG_STRING || g->opt[opti].type == eslARG_INFILE || g->opt[opti].type == eslARG_OUTFILE)
1444 && **ret_optarg == '-')
1445 ESL_FAIL(eslESYNTAX, g->errbuf,
1446 "Arg looks like option? Use %.24s=%.24s if you really mean it.",
1447 g->opt[opti].name, *ret_optarg);
1448 }
1449 }
1450 else /* if there's not supposed to be an arg, but there is, then die */
1451 {
1452 if (argptr != NULL)
1453 ESL_FAIL(eslESYNTAX, g->errbuf, "Option %.24s does not take an argument.", g->opt[opti].name);
1454 *ret_optarg = NULL;
1455 }
1456 return eslOK;
1457 }
1458
1459 /* process_stdopt():
1460 *
1461 * Either we're in the middle of working on an optstring (and optind
1462 * is sitting on the next argv element, which may be an argument of
1463 * the last char in the optstring), or optind is sitting on a "-"
1464 * option and we should start working on a new optstring. That is,
1465 * we're dealing with standard one-char options, which may be
1466 * concatenated into an optstring.
1467 *
1468 * Only the last optchar in a optstring may take an argument. The argument
1469 * is either the remainder of the argv element (if any) or if not, the
1470 * next argv element.
1471 *
1472 * Examples of syntax:
1473 * -a
1474 * -W arg
1475 * -Warg
1476 * -abc
1477 * -abcW arg
1478 * -abcWarg
1479 *
1480 * Process next optchar; return <eslOK> on success, returning option
1481 * number through <ret_opti> and a pointer to any argument through
1482 * <ret_optarg>. Internally, optind is advanced to the next argv element;
1483 * either 0, +1, or +2, depending on whether we're still processing an
1484 * optstring from a prev optind, starting a new optstring, or reading
1485 * a "-W arg" form, respectively.
1486 *
1487 * Returns <eslESYNTAX> and sets <g->errbuf> to a helpful error mesg if:
1488 * 1. The option doesn't exist.
1489 * 2. The option takes an argument, but none was found.
1490 * 3. The option takes an untypechecked argument (eslARG_STRING,
1491 * eslARG_INFILE, or eslARG_OUTFILE), the argument is unattached
1492 * (space-delimited), and it appears to be an option instead of
1493 * an argument, because it starts with '-'.
1494 * All these are user input errors.
1495 */
1496 static int
process_stdopt(ESL_GETOPTS * g,int * ret_opti,char ** ret_optarg)1497 process_stdopt(ESL_GETOPTS *g, int *ret_opti, char **ret_optarg)
1498 {
1499 int opti;
1500
1501 /* Do we need to start a new optstring in a new argv element?
1502 * (as opposed to still being in an optstring from a prev parse)
1503 */
1504 if (g->optstring == NULL)
1505 g->optstring = g->argv[g->optind++]+1; /* init optstring on first option char; advance optind */
1506
1507 /* Figure out what option this optchar is
1508 */
1509 for (opti = 0; opti < g->nopts; opti++)
1510 if (*(g->optstring) == g->opt[opti].name[1]) break; /* this'll also fail appropriately for long opts. */
1511 if (opti == g->nopts)
1512 ESL_FAIL(eslESYNTAX, g->errbuf, "No such option \"-%c\".", *(g->optstring));
1513 *ret_opti = opti;
1514
1515 /* Find the argument, if there's supposed to be one */
1516 if (g->opt[opti].type != eslARG_NONE)
1517 {
1518 if (*(g->optstring+1) != '\0') /* attached argument case, a la -Warg */
1519 *ret_optarg = g->optstring+1;
1520 else if (g->optind < g->argc) { /* unattached argument; assign optind, advance counter */
1521 *ret_optarg = g->argv[g->optind++];
1522
1523 /* Watch out for options masquerading as missing arguments. */
1524 if ((g->opt[opti].type == eslARG_STRING || g->opt[opti].type == eslARG_INFILE || g->opt[opti].type == eslARG_OUTFILE)
1525 && **ret_optarg == '-')
1526 ESL_FAIL(eslESYNTAX, g->errbuf,
1527 "Arg looks like option? Use %.24s%.24s if you really mean it.",
1528 g->opt[opti].name, *ret_optarg);
1529 } else
1530 ESL_FAIL(eslESYNTAX, g->errbuf, "Option %.24s requires an argument", g->opt[opti].name);
1531
1532 g->optstring = NULL; /* An optchar that takes an arg must terminate an optstring. */
1533 }
1534 else /* if there's not supposed to be an argument, then check if we're still in an optstring */
1535 {
1536 *ret_optarg = NULL;
1537 if (*(g->optstring+1) != '\0') /* yup, we're still in an optstring */
1538 g->optstring++;
1539 else
1540 g->optstring = NULL; /* nope, that's it; move to next field in args */
1541 }
1542 return eslOK;
1543 }
1544 /*----------- end of private functions for processing command line options -------------*/
1545
1546
1547
1548
1549 /*****************************************************************
1550 * Private functions for type and range checking.
1551 *****************************************************************/
1552
1553 /* verify_type_and_range():
1554 *
1555 * Implementation of type and range checking for options.
1556 *
1557 * Given a value <val> (as a string) for option <i> in the option
1558 * object <g>, verify that <val> satisfies the appropriate type and
1559 * range. If successful, return <eslOK>.
1560 *
1561 * The <setby> flag is used to help format useful error messages,
1562 * by saying who was responsible for a bad <val>.
1563 *
1564 * Returns: <eslOK> on success.
1565 * Returns <eslESYNTAX> if <val> fails type/range checking,
1566 * and <g->errbuf> is set to contain an error report for the user.
1567 *
1568 * Throws: <eslEINVAL>: a range string format was bogus.
1569 * <eslEINCONCEIVABLE>: "can't happen" internal errors.
1570 */
1571 static int
verify_type_and_range(ESL_GETOPTS * g,int i,char * val,int setby)1572 verify_type_and_range(ESL_GETOPTS *g, int i, char *val, int setby)
1573 {
1574 char *where = NULL;
1575
1576 if (setby == eslARG_SETBY_DEFAULT) where = "as default";
1577 else if (setby == eslARG_SETBY_CMDLINE) where = "on cmdline";
1578 else if (setby == eslARG_SETBY_ENV) where = "in env";
1579 else if (setby >= eslARG_SETBY_CFGFILE) where = "in cfgfile";
1580
1581 /* A special case: Any option may be "unset" by default by having a
1582 * NULL default value. Thus, for instance, an eslARG_REAL can be
1583 * off by default, or set to a value by a command line option.
1584 */
1585 if (setby == eslARG_SETBY_DEFAULT && val == NULL)
1586 return eslOK;
1587
1588 switch (g->opt[i].type) {
1589 case eslARG_NONE:
1590 /* treat as unchecked, because val may be "on", 0x1, "true", etc.:
1591 * any non-NULL ptr means on, and NULL means off.
1592 */
1593 break;
1594
1595 case eslARG_INT:
1596 if (! esl_str_IsInteger(val))
1597 ESL_FAIL(eslESYNTAX, g->errbuf,
1598 "Option %.24s takes integer arg; got %.24s %s",
1599 g->opt[i].name, val, where);
1600
1601 if (verify_integer_range(val, g->opt[i].range) != eslOK)
1602 ESL_FAIL(eslESYNTAX, g->errbuf,
1603 "option %.24s takes integer arg in range %.24s; got %.24s %s",
1604 g->opt[i].name, g->opt[i].range, val, where);
1605 break;
1606
1607 case eslARG_REAL:
1608 if (! esl_str_IsReal(val))
1609 ESL_FAIL(eslESYNTAX, g->errbuf,
1610 "Option %.24s takes real-valued arg; got %.24s %s",
1611 g->opt[i].name, val, where);
1612
1613 if (verify_real_range(val, g->opt[i].range) != eslOK)
1614 ESL_FAIL(eslESYNTAX, g->errbuf,
1615 "Option %.24s takes real-valued arg in range %.24s; got %.24s %s",
1616 g->opt[i].name, g->opt[i].range, val, where);
1617 break;
1618
1619 case eslARG_CHAR:
1620 if (strlen(val) > 1)
1621 ESL_FAIL(eslESYNTAX, g->errbuf,
1622 "Option %.24s takes char arg; got %.24s %s",
1623 g->opt[i].name, val, where);
1624
1625 if (verify_char_range(val, g->opt[i].range) != eslOK)
1626 ESL_FAIL(eslESYNTAX, g->errbuf,
1627 "Option %.24s takes char arg in range %.24s; got %.24s %s",
1628 g->opt[i].name, g->opt[i].range, val, where);
1629 break;
1630
1631 case eslARG_STRING: /* unchecked type. */
1632 case eslARG_INFILE:
1633 case eslARG_OUTFILE:
1634 if (g->opt[i].range != NULL)
1635 ESL_EXCEPTION(eslEINVAL, "option %s takes a string arg that can't be range checked", g->opt[i].name);
1636 break;
1637
1638 default:
1639 ESL_EXCEPTION(eslEINVAL, "no such argument type");
1640 }
1641
1642 return eslOK;
1643 }
1644
1645
1646 /* verify_integer_range():
1647 *
1648 * Returns <eslOK> if the string <arg>, when converted to an integer
1649 * by atoi(), gives a value that lies within the given <range>, if
1650 * <range> is non-NULL. (If <range> is NULL, there is no constraint on
1651 * the range of this <arg>, so return TRUE.) Else, <arg> does not lie
1652 * in the <range>; return <eslERANGE> (a user input error). If <range>
1653 * itself is misformatted, return <eslEINVAL> (a coding error).
1654 *
1655 * Range must be in one of three formats, matched
1656 * by these regexps (though regexps aren't used by the
1657 * parser):
1658 * n>=?(\d+) lower bound
1659 * n<=?(\d+) upper bound
1660 * (\d+)<=?n<=?(\d+) lower and upper bound
1661 * Optional = signs indicate whether a bound is
1662 * inclusive or not. The "n" character indicates the
1663 * given integer value.
1664 *
1665 * Returns: <eslOK>: <arg> is within allowed <range>.
1666 * <eslERANGE>: <arg> is not within allowed <range>.
1667 * <eslEINVAL>: something wrong with <range> string.
1668 */
1669 static int
verify_integer_range(char * arg,char * range)1670 verify_integer_range(char *arg, char *range)
1671 {
1672 int n;
1673 int upper, lower; /* upper, lower bounds */
1674 char *up, *lp;
1675 int geq, leq; /* use >=, <= instead of >, < */
1676
1677 if (range == NULL) return eslOK;
1678 n = atoi(arg);
1679
1680 if (parse_rangestring(range, 'n', &lp, &geq, &up, &leq) != eslOK) return eslEINVAL;
1681
1682 if (lp != NULL) {
1683 lower = atoi(lp);
1684 if ((geq && ! (n >= lower)) || (!geq && !(n > lower))) return eslERANGE;
1685 }
1686
1687 if (up != NULL) {
1688 upper = atoi(up);
1689 if ((leq && ! (n <= upper)) || (!leq && !(n < upper))) return eslERANGE;
1690 }
1691 return eslOK;
1692 }
1693
1694
1695
1696 /* verify_real_range():
1697 *
1698 * Verify that a string <arg>, when converted to a
1699 * double-precision real by atof(), gives a value that lies
1700 * within the range defined by <range>. If <range> is NULL,
1701 * there is no range constraint, and any <arg> is valid.
1702 *
1703 * Returns: <eslOK>: <arg> is within allowed <range>.
1704 * <eslERANGE>: <arg> is not within allowed <range>.
1705 * <eslEINVAL>: something wrong with <range> string.
1706 */
1707 static int
verify_real_range(char * arg,char * range)1708 verify_real_range(char *arg, char *range)
1709 {
1710 double x;
1711 double upper, lower; /* upper, lower bounds */
1712 char *up, *lp;
1713 int geq, leq; /* use >=, <= instead of >, < */
1714
1715 if (range == NULL) return eslOK;
1716 x = atof(arg);
1717
1718 if (parse_rangestring(range, 'x', &lp, &geq, &up, &leq) != eslOK)
1719 return eslEINVAL;
1720
1721 if (lp != NULL)
1722 {
1723 lower = atof(lp);
1724 if ((geq && ! (x >= lower)) || (!geq && !(x > lower)))
1725 return eslERANGE;
1726 }
1727
1728 if (up != NULL)
1729 {
1730 upper = atof(up);
1731 if ((leq && ! (x <= upper)) || (!leq && !(x < upper)))
1732 return eslERANGE;
1733 }
1734 return eslOK;
1735 }
1736
1737
1738 /* verify_char_range():
1739 *
1740 * Verify that a string <arg>, when interpreted as a single
1741 * char argument, is a character that lies within the defined
1742 * <range>. If <range> is NULL, there is no range constraint,
1743 * and any <arg> is valid.
1744 *
1745 * Currently, <range> expression is limited to ASCII chars that can be
1746 * expressed as single chars. Could improve by allowing integer ASCII
1747 * codes, or backslash escapes.
1748 *
1749 * Returns: <eslOK>: <arg> is within allowed <range>.
1750 * <eslERANGE>: <arg> is not within allowed <range>.
1751 * <eslEINVAL>: something wrong with <range> string.
1752 */
1753 static int
verify_char_range(char * arg,char * range)1754 verify_char_range(char *arg, char *range)
1755 {
1756 char c;
1757 char *upper, *lower;
1758 int geq, leq; /* use >=, <= instead of >, < */
1759
1760 if (range == NULL) return eslOK;
1761 c = *arg;
1762
1763 if (parse_rangestring(range, 'c', &lower, &geq, &upper, &leq) != eslOK)
1764 return eslEINVAL;
1765
1766 if (lower != NULL)
1767 {
1768 if ((geq && ! (c >= *lower)) || (!geq && !(c > *lower)))
1769 return eslERANGE;
1770 }
1771
1772 if (upper != NULL)
1773 {
1774 if ((leq && ! (c <= *upper)) || (!leq && !(c < *upper)))
1775 return eslERANGE;
1776 }
1777 return eslOK;
1778 }
1779
1780
1781
1782 /* parse_rangestring():
1783 *
1784 * Given a range definition string in one of the following forms:
1785 * c>=?(\d+) lower bound
1786 * c<=?(\d+) upper bound
1787 * (\d+)<=?c<=?(\d+) lower and upper bound
1788 * where <c> is a one-character marker expected for the
1789 * argument type ('n' for integers, 'f' for floating-point values,
1790 * 'c' for characters).
1791 *
1792 * Sets pointers to upper and lower bound strings, for parsing by
1793 * atoi() or atof() as appropriate.
1794 * Sets geq, leq flags to TRUE if bounds are supposed to be inclusive.
1795 *
1796 * Returns <eslOK> on success, <eslEINVAL> if the range string
1797 * is invalid. No errors are thrown here, so caller can format a
1798 * useful error message if range string is bogus.
1799 */
1800 static int
parse_rangestring(char * range,char c,char ** ret_lowerp,int * ret_geq,char ** ret_upperp,int * ret_leq)1801 parse_rangestring(char *range, char c, char **ret_lowerp, int *ret_geq, char **ret_upperp, int *ret_leq)
1802 {
1803 char *ptr;
1804
1805 *ret_geq = *ret_leq = FALSE; /* 'til proven otherwise */
1806 *ret_lowerp = *ret_upperp = NULL; /* 'til proven otherwise */
1807
1808 if ((ptr = strchr(range, c)) == NULL) return eslEINVAL;
1809 if (ptr == range) /* we're "n>=a" or "n<=b" form, where n came first */
1810 {
1811 if (ptr[1] == '>') /* "n>=a" form; lower bound */
1812 {
1813 if (ptr[2] == '=') { *ret_geq = TRUE; *ret_lowerp = ptr+3; }
1814 else *ret_lowerp = ptr+2;
1815 }
1816 else if (ptr[1] == '<') /* "n<=a" form; upper bound */
1817 {
1818 if (ptr[2] == '=') { *ret_leq = TRUE; *ret_upperp = ptr+3; }
1819 else *ret_upperp = ptr+2;
1820 }
1821 else return eslEINVAL;
1822 }
1823 else /* we're in a<=n<=b form; upper bound after n, lower before */
1824 {
1825 if (*(ptr+1) != '<') return eslEINVAL;
1826 if (*(ptr+2) == '=') { *ret_leq = TRUE; *ret_upperp = ptr+3; } else *ret_upperp = ptr+2;
1827
1828 ptr--;
1829 if (*ptr == '=') { *ret_geq = TRUE; ptr--; }
1830 if (*ptr != '<') return eslEINVAL;
1831 *ret_lowerp = range; /* start of string */
1832 }
1833 return eslOK;
1834 }
1835
1836 /*-------------- end of private type/range-checking functions ----------------*/
1837
1838
1839
1840
1841 /*****************************************************************
1842 * Private functions for checking optlists (toggles, required options,
1843 * and incompatible options
1844 *****************************************************************/
1845
1846 /* process_optlist():
1847 *
1848 * Given a pointer <s> to the next option name in
1849 * a comma-delimited list, figure out what option
1850 * this is; set <ret_opti> to its index. If another
1851 * option remains in the optlist, reset <s> to
1852 * the start of it, for the next call to process_optlist().
1853 * If no options remain after this one, reset <s> to NULL.
1854 *
1855 * Returns: <eslOK> if an option has been successfully parsed
1856 * out of the list and <ret_opti> is valid;
1857 * <eslEOD> if no more option remains (<s> is NULL,
1858 * or points to a \0).
1859 * <eslEINVAL> if an option in the list isn't
1860 * recognized (a coding error).
1861 */
1862 static int
process_optlist(ESL_GETOPTS * g,char ** ret_s,int * ret_opti)1863 process_optlist(ESL_GETOPTS *g, char **ret_s, int *ret_opti)
1864 {
1865 char *s;
1866 int i;
1867 int n;
1868
1869 if ((s = *ret_s) == NULL) return eslEOD;
1870 if (*s == '\0') return eslEOD;
1871
1872 n = strcspn(s, ",");
1873
1874 /* a little weak here; we're only matching a n-long prefix, so we're
1875 * not going to catch the case where the optlist contains a
1876 * truncated, ambiguous optionname. but optlists are not user
1877 * input, so the answer to this problem is "don't do that".
1878 */
1879 for (i = 0; i < g->nopts; i++)
1880 if (strncmp(g->opt[i].name, s, n) == 0) break;
1881 if (i == g->nopts) return eslEINVAL;
1882
1883 *ret_opti = i;
1884 if (s[n] == ',') *ret_s = s+n+1;
1885 else *ret_s = NULL;
1886
1887 return eslOK;
1888 }
1889
1890 /*------- end of private functions for processing optlists -----------*/
1891
1892
1893
1894 /*****************************************************************
1895 * 6. Test driver.
1896 *****************************************************************/
1897
1898 #ifdef eslGETOPTS_TESTDRIVE
1899 /* gcc -g -Wall -o getopts_utest -I. -DeslGETOPTS_TESTDRIVE esl_getopts.c easel.c
1900 */
1901 #include <stdlib.h>
1902 #include <stdio.h>
1903
1904 #include "easel.h"
1905 #include "esl_getopts.h"
1906
1907 /*::cexcerpt::getopts_bigarray::begin::*/
1908 #define BGROUP "-b,--no-b"
1909 static ESL_OPTIONS options[] = {
1910 /* name type default env_var range toggles req incompat help docgroup */
1911 { "-a", eslARG_NONE, FALSE,"FOOTEST",NULL, NULL, NULL, NULL, "toggle a on", 1 },
1912 { "-b", eslARG_NONE, FALSE, NULL, NULL, BGROUP, NULL, NULL, "toggle b on", 1 },
1913 { "--no-b", eslARG_NONE,"TRUE", NULL, NULL, BGROUP, NULL, NULL, "toggle b off", 1 },
1914 { "-c", eslARG_CHAR, "x", NULL,"a<=c<=z",NULL, NULL, NULL, "character arg", 2 },
1915 { "--d1", eslARG_NONE,"TRUE", NULL, NULL, "--d2", NULL, NULL, "toggle d1 on, d2 off", 2 },
1916 { "--d2", eslARG_NONE, FALSE, NULL, NULL, "--d1", NULL, NULL, "toggle d2 on, d1 off", 2 },
1917 { "-n", eslARG_INT, "0", NULL,"0<=n<10",NULL, NULL, NULL, "integer arg", 2 },
1918 { "-x", eslARG_REAL, "0.8", NULL, "0<x<1", NULL, NULL, NULL, "real-value arg", 2 },
1919 { "--lowx", eslARG_REAL, "1.0", NULL, "x>0", NULL, NULL, NULL, "real arg with lower bound", 2 },
1920 { "--hix", eslARG_REAL, "0.9", NULL, "x<1", NULL, NULL, NULL, "real arg with upper bound", 2 },
1921 { "--lown", eslARG_INT, "42", NULL, "n>0", NULL,"-a,-b", NULL, "int arg with lower bound", 2 },
1922 { "--hin", eslARG_INT, "-1", NULL, "n<0", NULL, NULL,"--no-b","int arg with upper bound", 2 },
1923 { "--host", eslARG_STRING, "","HOSTTEST",NULL, NULL, NULL, NULL, "string arg with env var", 3 },
1924 { "--multi",eslARG_STRING,NULL, NULL, NULL, NULL, NULL, NULL, "test quoted configfile arg",3 },
1925 { "--mul", eslARG_NONE, FALSE, NULL, NULL, NULL, NULL, NULL, "test long opt abbreviation",3 }, /* xref bug #e4 */
1926 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1927 };
1928 /*::cexcerpt::getopts_bigarray::end::*/
1929
1930 int
main(void)1931 main(void)
1932 {
1933 ESL_GETOPTS *go;
1934 char file1[32] = "esltmpXXXXXX";
1935 char file2[32] = "esltmpXXXXXX";
1936 char *errmsg = "getopts unit test failure";
1937 FILE *f1, *f2;
1938 int i;
1939
1940 /* Declare a "command line" internally. */
1941 int argc = 11; /* progname; 8 options; 2 args */
1942 char *argv[] = { "progname", "-bc", "y", "--d1", "-n9", "--hix=0.0", "--lown", "43", "--mul", "arg1", "2005"};
1943
1944 /* Create a config file #1. */
1945 if (esl_tmpfile_named(file1, &f1) != eslOK) esl_fatal("failed to create named tmpfile 1");
1946 fprintf(f1, "# Test config file #1\n");
1947 fprintf(f1, "#\n");
1948 fprintf(f1, "-b\n");
1949 fprintf(f1, "--d2\n");
1950 fprintf(f1, "-n 3\n");
1951 fprintf(f1, "-x 0.5\n");
1952 fprintf(f1, "--multi \"one two three\"\n");
1953 fclose(f1);
1954
1955 /* Create config file #2. */
1956 if (esl_tmpfile_named(file2, &f2) != eslOK) esl_fatal("failed to create named tmpfile 2");
1957 fprintf(f2, "# Test config file #2\n");
1958 fprintf(f2, "#\n");
1959 fprintf(f2, "--no-b\n");
1960 fprintf(f2, "--hin -33\n");
1961 fprintf(f2, "--host www.nytimes.com\n");
1962 fclose(f2);
1963
1964 /* Put some test vars in the environment.
1965 * (Note: apparently, on some OS's (Mac OS/X), setenv() necessarily leaks memory.)
1966 */
1967 setenv("FOOTEST", "", 1);
1968 setenv("HOSTTEST", "wasp.cryptogenomicon.org", 1);
1969
1970 /* Open the test config files for reading.
1971 */
1972 if ((f1 = fopen(file1, "r")) == NULL) esl_fatal("getopts fopen() 1 failed");
1973 if ((f2 = fopen(file2, "r")) == NULL) esl_fatal("getopts fopen() 2 failed");
1974
1975 go = esl_getopts_Create(options);
1976 if (esl_opt_ProcessConfigfile(go, file1, f1) != eslOK) esl_fatal("getopts failed to process config file 1\n%s\n", go->errbuf);
1977 if (esl_opt_ProcessConfigfile(go, file2, f2) != eslOK) esl_fatal("getopts failed to process config file 2\n%s\n", go->errbuf);
1978 if (esl_opt_ProcessEnvironment(go) != eslOK) esl_fatal("getopts failed to process environment:\n%s\n", go->errbuf);
1979 if (esl_opt_ProcessCmdline(go, argc, argv) != eslOK) esl_fatal("getopts failed to process command line:\n%s\n", go->errbuf);
1980 if (esl_opt_VerifyConfig(go) != eslOK) esl_fatal("getopts config fails validation:\n%s\n", go->errbuf);
1981
1982 fclose(f1);
1983 fclose(f2);
1984
1985 if (esl_opt_GetBoolean(go, "-a") != TRUE) esl_fatal("getopts failed on -a"); /* -a is ON: by environment */
1986 if (esl_opt_GetBoolean(go, "-b") != TRUE) esl_fatal("getopts failed on -b"); /* -b is toggled thrice, ends up ON */
1987 if (esl_opt_GetBoolean(go, "--no-b") != FALSE) esl_fatal("getopts failed on --no-b"); /* so --no-b is OFF */
1988 if (esl_opt_GetChar (go, "-c") != 'y') esl_fatal("getopts failed on -c"); /* set to y on cmdline in an optstring */
1989 if (esl_opt_GetInteger(go, "-n") != 9) esl_fatal("getopts failed on -n"); /* cfgfile, then on cmdline as linked arg*/
1990 if (esl_opt_GetReal (go, "-x") != 0.5) esl_fatal("getopts failed on -x"); /* cfgfile #1 */
1991 if (esl_opt_GetReal (go, "--lowx") != 1.0) esl_fatal("getopts failed on --lowx"); /* stays at default */
1992 if (esl_opt_GetReal (go, "--hix") != 0.0) esl_fatal("getopts failed on --hix"); /* arg=x format on cmdline */
1993 if (esl_opt_GetInteger(go, "--lown") != 43) esl_fatal("getopts failed on --lown"); /* cmdline; requires -a -b */
1994 if (esl_opt_GetInteger(go, "--hin") != -33) esl_fatal("getopts failed on --hin"); /* cfgfile 2; requires --no-b to be off */
1995 if (esl_opt_GetBoolean(go, "--mul") != TRUE) esl_fatal("getopts failed on --mul"); /* --mul should not be confused with --multi by abbrev parser*/
1996 if (strcmp(esl_opt_GetString(go, "--host"), "wasp.cryptogenomicon.org") != 0)
1997 esl_fatal("getopts failed on --host"); /* cfgfile 2, then overridden by environment */
1998 if (strcmp(esl_opt_GetString(go, "--multi"), "one two three") != 0)
1999 esl_fatal("config file didn't handle quoted argument");
2000
2001 /* --d1, --d2 test that we can resolve the difference between IsDefault(), IsOn(), and IsUsed() */
2002 /* these options, despite getting toggled twice on/off, remain at default values;
2003 * so d1 is default, on, and not used (because it's default); d2 is default, off, and not used.
2004 * IsDefault IsOn IsUsed
2005 * ------- ----- -------
2006 * true true true [can't happen: option must be non-default to be considered "in use"]
2007 * true true false --d1 for example, despite being toggled twice
2008 * true false true [can't happen: option must be non-default to be considered "in use"]
2009 * true false false --d2 for example, despite being toggled twice
2010 * false true true -a,-b for example
2011 * false true false [can't happen: if option is ON and not in default state, it's "in use"]
2012 * false false true [can't happen: if option is OFF, it's not "in use"]
2013 * false false false --no-b for example
2014 */
2015 if (! esl_opt_IsDefault(go, "--d1")) esl_fatal(errmsg);
2016 if (! esl_opt_IsOn (go, "--d1")) esl_fatal(errmsg);
2017 if ( esl_opt_IsUsed (go, "--d1")) esl_fatal(errmsg);
2018 if (! esl_opt_IsDefault(go, "--d2")) esl_fatal(errmsg);
2019 if ( esl_opt_IsOn (go, "--d2")) esl_fatal(errmsg);
2020 if ( esl_opt_IsUsed (go, "--d2")) esl_fatal(errmsg);
2021 if ( esl_opt_IsDefault(go, "-a")) esl_fatal(errmsg);
2022 if (! esl_opt_IsOn (go, "-a")) esl_fatal(errmsg);
2023 if (! esl_opt_IsUsed (go, "-a")) esl_fatal(errmsg);
2024 if ( esl_opt_IsDefault(go, "-b")) esl_fatal(errmsg);
2025 if (! esl_opt_IsOn (go, "-b")) esl_fatal(errmsg);
2026 if (! esl_opt_IsUsed (go, "-b")) esl_fatal(errmsg);
2027 if ( esl_opt_IsDefault(go, "--no-b")) esl_fatal(errmsg);
2028 if ( esl_opt_IsOn (go, "--no-b")) esl_fatal(errmsg);
2029 if ( esl_opt_IsUsed (go, "--no-b")) esl_fatal(errmsg);
2030
2031 for (i = 0; i < go->nopts; i++)
2032 { /* Test that no option is in an impossible default/on/used state according to logic table above */
2033 if ( esl_opt_IsDefault(go, go->opt[i].name) && esl_opt_IsOn(go, go->opt[i].name) && esl_opt_IsUsed(go, go->opt[i].name)) esl_fatal(errmsg);
2034 if ( esl_opt_IsDefault(go, go->opt[i].name) && ! esl_opt_IsOn(go, go->opt[i].name) && esl_opt_IsUsed(go, go->opt[i].name)) esl_fatal(errmsg);
2035 if (! esl_opt_IsDefault(go, go->opt[i].name) && esl_opt_IsOn(go, go->opt[i].name) && ! esl_opt_IsUsed(go, go->opt[i].name)) esl_fatal(errmsg);
2036 if (! esl_opt_IsDefault(go, go->opt[i].name) && ! esl_opt_IsOn(go, go->opt[i].name) && esl_opt_IsUsed(go, go->opt[i].name)) esl_fatal(errmsg);
2037 }
2038
2039 /* Now the two remaining argv[] elements are the command line args
2040 */
2041 if (esl_opt_ArgNumber(go) != 2) esl_fatal("getopts failed with wrong arg number");
2042
2043 if (strcmp("arg1", esl_opt_GetArg(go, 1)) != 0) esl_fatal("getopts failed on argument 1");
2044 if (strcmp("2005", esl_opt_GetArg(go, 2)) != 0) esl_fatal("getopts failed on argument 2");
2045
2046 esl_getopts_Destroy(go);
2047 remove(file1);
2048 remove(file2);
2049 exit(0);
2050 }
2051
2052 #endif /*eslGETOPTS_TESTDRIVE*/
2053 /*-------------- end of test driver -------------------------*/
2054
2055 /*****************************************************************
2056 * 7. Examples.
2057 *****************************************************************/
2058
2059 /* The starting example of "standard" getopts behavior, without
2060 * any of the bells and whistles.
2061 * Compile:
2062 gcc -g -Wall -o getopts_example -I. -DeslGETOPTS_EXAMPLE esl_getopts.c easel.c
2063 */
2064 #ifdef eslGETOPTS_EXAMPLE
2065 /*::cexcerpt::getopts_example::begin::*/
2066 #include <stdio.h>
2067 #include "easel.h"
2068 #include "esl_getopts.h"
2069
2070 static ESL_OPTIONS options[] = {
2071 /* name type def env range toggles reqs incomp help docgroup*/
2072 { "-h", eslARG_NONE, FALSE, NULL, NULL, NULL, NULL, NULL, "show help and usage", 0},
2073 { "-a", eslARG_NONE, FALSE, NULL, NULL, NULL, NULL, NULL, "a boolean switch", 0},
2074 { "-b", eslARG_NONE,"default", NULL, NULL, NULL, NULL, NULL, "another boolean switch", 0},
2075 { "-n", eslARG_INT, "0", NULL, NULL, NULL, NULL, NULL, "an integer argument", 0},
2076 { "-s", eslARG_STRING, "hi!", NULL, NULL, NULL, NULL, NULL, "a string argument", 0},
2077 { "-x", eslARG_REAL, "1.0", NULL, NULL, NULL, NULL, NULL, "a real-valued argument", 0},
2078 { "--file", eslARG_STRING, NULL, NULL, NULL, NULL, NULL, NULL, "long option, filename arg", 0},
2079 { "--char", eslARG_CHAR, "", NULL, NULL, NULL, NULL, NULL, "long option, char arg", 0},
2080 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2081 };
2082 static char usage[] = "Usage: ./example [-options] <arg>";
2083
2084 int
main(int argc,char ** argv)2085 main(int argc, char **argv)
2086 {
2087 ESL_GETOPTS *go;
2088 char *arg;
2089
2090 if ((go = esl_getopts_Create(options)) == NULL) esl_fatal("Bad options structure\n");
2091 if (esl_opt_ProcessCmdline(go, argc, argv) != eslOK) esl_fatal("Failed to parse command line: %s\n", go->errbuf);
2092 if (esl_opt_VerifyConfig(go) != eslOK) esl_fatal("Failed to parse command line: %s\n", go->errbuf);
2093
2094 if (esl_opt_GetBoolean(go, "-h") == TRUE) {
2095 printf("%s\n where options are:", usage);
2096 esl_opt_DisplayHelp(stdout, go, 0, 2, 80); /* 0=all docgroups; 2=indentation; 80=width */
2097 return 0;
2098 }
2099
2100 if (esl_opt_ArgNumber(go) != 1) esl_fatal("Incorrect number of command line arguments.\n%s\n", usage);
2101 arg = esl_opt_GetArg(go, 1);
2102
2103 printf("Option -a: %s\n", esl_opt_GetBoolean(go, "-a") ? "on" : "off");
2104 printf("Option -b: %s\n", esl_opt_GetBoolean(go, "-b") ? "on" : "off");
2105 printf("Option -n: %d\n", esl_opt_GetInteger(go, "-n"));
2106 printf("Option -s: %s\n", esl_opt_GetString( go, "-s"));
2107 printf("Option -x: %f\n", esl_opt_GetReal( go, "-x"));
2108 if (esl_opt_IsUsed(go, "--file")) printf("Option --file: %s\n", esl_opt_GetString(go, "--file"));
2109 else printf("Option --file: (not set)\n");
2110 printf("Option --char: %c\n", esl_opt_GetChar(go, "--char"));
2111 printf("Cmdline arg: %s\n", arg);
2112
2113 esl_getopts_Destroy(go);
2114 return 0;
2115 }
2116 /*::cexcerpt::getopts_example::end::*/
2117 #endif /*eslGETOPTS_EXAMPLE*/
2118
2119 /* Using <esl_getopts_CreateDefaultApp()> implements a standard series
2120 * of events, including how the -h (help) option is handled.
2121 * Compile:
2122 gcc -g -Wall -o getopts_example2 -I. -DeslGETOPTS_EXAMPLE2 esl_getopts.c easel.c
2123 */
2124 #ifdef eslGETOPTS_EXAMPLE2
2125 /*::cexcerpt::getopts_example2::begin::*/
2126 #include <stdio.h>
2127 #include "easel.h"
2128 #include "esl_getopts.h"
2129
2130 static ESL_OPTIONS options[] = {
2131 /* name type default env range toggles reqs incomp help docgroup*/
2132 { "-h", eslARG_NONE, FALSE, NULL, NULL, NULL, NULL, NULL, "show help and usage", 0},
2133 { "-a", eslARG_NONE, FALSE, NULL, NULL, NULL, NULL, NULL, "a boolean switch", 0},
2134 { "-n", eslARG_INT, "42",NULL, NULL, NULL, NULL, NULL, "an integer", 0},
2135 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2136 };
2137 static char banner[] = "example of using simplest getopts creation";
2138 static char usage[] = "[-options] <arg1> <arg2>";
2139
2140 int
main(int argc,char ** argv)2141 main(int argc, char **argv)
2142 {
2143 ESL_GETOPTS *go = esl_getopts_CreateDefaultApp(options, 2, argc, argv, banner, usage);
2144 char *arg1 = esl_opt_GetArg(go, 1);
2145 char *arg2 = esl_opt_GetArg(go, 2);
2146 int a = esl_opt_GetBoolean(go, "-a");
2147 int n = esl_opt_GetInteger(go, "-n");
2148
2149 printf("arg 1: %s\n", arg1);
2150 printf("arg 2: %s\n", arg2);
2151 printf("option a: %s\n", (a ? "true" : "false"));
2152 printf("option n: %d\n", n);
2153
2154 esl_getopts_Destroy(go);
2155 return 0;
2156 }
2157 /*::cexcerpt::getopts_example2::end::*/
2158 #endif /*eslGETOPTS_EXAMPLE2*/
2159 /*-------------- end of examples ---------------------*/
2160
2161
2162
2163
2164