3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * GROningen Mixture of Alchemy and Childrens' Stories
35 /* This file is completely threadsafe - keep it that way! */
36 #include "gromacs/commandline/pargs.h"
47 #include "gromacs/legacyheaders/gmx_fatal.h"
48 #include "gromacs/legacyheaders/smalloc.h"
49 #include "gromacs/legacyheaders/string2.h"
51 #include "gromacs/utility/gmxassert.h"
53 /* The source code in this file should be thread-safe.
54 Please keep it that way. */
56 static void usage(const char *type, const char *arg)
58 GMX_ASSERT(arg != NULL, "NULL command-line argument should not occur");
59 gmx_fatal(FARGS, "Expected %s argument for option %s\n", type, arg);
62 /* Scan an int for argument argv[*i] from argument at argv[*i + 1].
63 * eg: -p 32. argv[*i] is only used for error reporting.
64 * If there is no value, or the conversion is not successful, the
65 * routine exits with an error, otherwise it returns the value found.
66 * *i is incremented once.
68 static int iscan(int argc, char *argv[], int *i)
70 const char *const arg = argv[*i];
73 usage("an integer", arg);
75 const char *const value = argv[++(*i)];
77 int var = std::strtol(value, &endptr, 10);
78 if (*value == '\0' || *endptr != '\0')
80 usage("an integer", arg);
85 /* Same as above, but for large integer values */
86 static gmx_large_int_t istepscan(int argc, char *argv[], int *i)
88 const char *const arg = argv[*i];
91 usage("an integer", arg);
93 const char *const value = argv[++(*i)];
95 gmx_large_int_t var = str_to_large_int_t(value, &endptr);
96 if (*value == '\0' || *endptr != '\0')
98 usage("an integer", arg);
103 /* Routine similar to the above, but working on doubles. */
104 static double dscan(int argc, char *argv[], int *i)
106 const char *const arg = argv[*i];
109 usage("a real", arg);
111 const char *const value = argv[++(*i)];
113 double var = std::strtod(value, &endptr);
114 if (*value == '\0' || *endptr != '\0')
116 usage("a real", arg);
121 /* Routine similar to the above, but working on strings. The pointer
122 * returned is a pointer to the argv field.
124 static char *sscan(int argc, char *argv[], int *i)
128 if ( (argv[(*i)+1][0] == '-') && (argc > (*i)+2) &&
129 (argv[(*i)+2][0] != '-') )
131 fprintf(stderr, "Possible missing string argument for option %s\n\n",
137 usage("a string", argv[*i]);
143 gmx_bool is_hidden(t_pargs *pa)
145 return ((strstr(pa->desc, "HIDDEN") != NULL) ||
146 (strstr(pa->desc, "[hidden]") != NULL));
149 int nenum(const char *const enumc[])
154 /* we *can* compare pointers directly here! */
155 while (enumc[i] && enumc[0] != enumc[i])
163 void get_pargs(int *argc, char *argv[], int nparg, t_pargs pa[], gmx_bool bKeepArgs)
170 snew(bKeep, *argc+1);
174 for (i = 1; (i < *argc); i++)
177 for (j = 0; (j < nparg); j++)
179 if (pa[j].type == etBOOL)
181 sprintf(buf, "-no%s", pa[j].option+1);
182 if (strcmp(pa[j].option, argv[i]) == 0)
188 else if (strcmp(buf, argv[i]) == 0)
195 else if (strcmp(pa[j].option, argv[i]) == 0)
199 fprintf(stderr, "Setting option %s more than once!\n",
207 *pa[j].u.i = iscan(*argc, argv, &i);
209 case etGMX_LARGE_INT:
210 *pa[j].u.is = istepscan(*argc, argv, &i);
214 *pa[j].u.r = dscan(*argc, argv, &i);
217 *(pa[j].u.c) = sscan(*argc, argv, &i);
221 ptr = sscan(*argc, argv, &i);
222 for (k = 1; (pa[j].u.c[k] != NULL); k++)
224 /* only check ptr against beginning of
226 if (gmx_strncasecmp(ptr, pa[j].u.c[k], strlen(ptr)) == 0)
228 if ( ( match == -1 ) ||
229 ( strlen(pa[j].u.c[k]) <
230 strlen(pa[j].u.c[match]) ) )
238 pa[j].u.c[0] = pa[j].u.c[match];
242 gmx_fatal(FARGS, "Invalid argument %s for option %s",
247 (*pa[j].u.rv)[0] = dscan(*argc, argv, &i);
248 if ( (i+1 == *argc) ||
249 ( (argv[i+1][0] == '-') &&
250 !isdigit(argv[i+1][1]) ) )
259 (*pa[j].u.rv)[1] = dscan(*argc, argv, &i);
260 if ( (i+1 == *argc) ||
261 ( (argv[i+1][0] == '-') &&
262 !isdigit(argv[i+1][1]) ) )
265 "%s: vector must have 1 or 3 real parameters",
269 (*pa[j].u.rv)[2] = dscan(*argc, argv, &i);
273 gmx_fatal(FARGS, "Invalid type %d in pargs", pa[j].type);
275 /* i may be incremented, so set it to not keep */
282 /* Remove used entries */
283 for (i = j = 0; (i <= *argc); i++)
295 int opt2parg_int(const char *option, int nparg, t_pargs pa[])
299 for (i = 0; (i < nparg); i++)
301 if (strcmp(pa[i].option, option) == 0)
307 gmx_fatal(FARGS, "No integer option %s in pargs", option);
312 gmx_bool opt2parg_gmx_bool(const char *option, int nparg, t_pargs pa[])
316 for (i = 0; (i < nparg); i++)
318 if (strcmp(pa[i].option, option) == 0)
324 gmx_fatal(FARGS, "No boolean option %s in pargs", option);
329 real opt2parg_real(const char *option, int nparg, t_pargs pa[])
333 for (i = 0; (i < nparg); i++)
335 if (strcmp(pa[i].option, option) == 0)
341 gmx_fatal(FARGS, "No real option %s in pargs", option);
346 const char *opt2parg_str(const char *option, int nparg, t_pargs pa[])
350 for (i = 0; (i < nparg); i++)
352 if (strcmp(pa[i].option, option) == 0)
358 gmx_fatal(FARGS, "No string option %s in pargs", option);
363 gmx_bool opt2parg_bSet(const char *option, int nparg, t_pargs pa[])
367 for (i = 0; (i < nparg); i++)
369 if (strcmp(pa[i].option, option) == 0)
375 gmx_fatal(FARGS, "No such option %s in pargs", option);
377 return FALSE; /* Too make some compilers happy */
380 const char *opt2parg_enum(const char *option, int nparg, t_pargs pa[])
384 for (i = 0; (i < nparg); i++)
386 if (strcmp(pa[i].option, option) == 0)
392 gmx_fatal(FARGS, "No such option %s in pargs", option);