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