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"
53 #include <sys/schedctl.h>
54 #include <sys/sysmp.h>
57 #include "gromacs/legacyheaders/gmx_fatal.h"
58 #include "gromacs/legacyheaders/macros.h"
59 #include "gromacs/legacyheaders/network.h"
60 #include "gromacs/legacyheaders/smalloc.h"
61 #include "gromacs/legacyheaders/string2.h"
62 #include "gromacs/legacyheaders/thread_mpi/threads.h"
64 #include "gromacs/commandline/wman.h"
65 #include "gromacs/fileio/timecontrol.h"
66 #include "gromacs/utility/exceptions.h"
67 #include "gromacs/utility/gmxassert.h"
70 /* The source code in this file should be thread-safe.
71 Please keep it that way. */
73 static void usage(const char *type, const char *arg)
75 GMX_ASSERT(arg != NULL, "NULL command-line argument should not occur");
76 gmx_fatal(FARGS, "Expected %s argument for option %s\n", type, arg);
79 /* Scan an int for argument argv[*i] from argument at argv[*i + 1].
80 * eg: -p 32. argv[*i] is only used for error reporting.
81 * If there is no value, or the conversion is not successful, the
82 * routine exits with an error, otherwise it returns the value found.
83 * *i is incremented once.
85 static int iscan(int argc, char *argv[], int *i)
87 const char *const arg = argv[*i];
90 usage("an integer", arg);
92 const char *const value = argv[++(*i)];
94 int var = std::strtol(value, &endptr, 10);
95 if (*value == '\0' || *endptr != '\0')
97 usage("an integer", arg);
102 /* Same as above, but for large integer values */
103 static gmx_int64_t istepscan(int argc, char *argv[], int *i)
105 const char *const arg = argv[*i];
108 usage("an integer", arg);
110 const char *const value = argv[++(*i)];
112 gmx_int64_t var = str_to_int64_t(value, &endptr);
113 if (*value == '\0' || *endptr != '\0')
115 usage("an integer", arg);
120 /* Routine similar to the above, but working on doubles. */
121 static double dscan(int argc, char *argv[], int *i)
123 const char *const arg = argv[*i];
126 usage("a real", arg);
128 const char *const value = argv[++(*i)];
130 double var = std::strtod(value, &endptr);
131 if (*value == '\0' || *endptr != '\0')
133 usage("a real", arg);
138 /* Routine similar to the above, but working on strings. The pointer
139 * returned is a pointer to the argv field.
141 static char *sscan(int argc, char *argv[], int *i)
145 if ( (argv[(*i)+1][0] == '-') && (argc > (*i)+2) &&
146 (argv[(*i)+2][0] != '-') )
148 fprintf(stderr, "Possible missing string argument for option %s\n\n",
154 usage("a string", argv[*i]);
160 gmx_bool is_hidden(t_pargs *pa)
162 return ((strstr(pa->desc, "HIDDEN") != NULL) ||
163 (strstr(pa->desc, "[hidden]") != NULL));
166 int nenum(const char *const enumc[])
171 /* we *can* compare pointers directly here! */
172 while (enumc[i] && enumc[0] != enumc[i])
180 /* Read a number of arguments from the command line.
181 * For etINT, etREAL and etCHAR an extra argument is read (when present)
182 * for etBOOL the gmx_boolean option is changed to the negate value
183 * If !bKeepArgs, the command line arguments are removed from the command line
185 static void get_pargs(int *argc, char *argv[], int nparg, t_pargs pa[],
193 snew(bKeep, *argc+1);
197 for (i = 1; (i < *argc); i++)
200 for (j = 0; (j < nparg); j++)
202 if (pa[j].type == etBOOL)
204 sprintf(buf, "-no%s", pa[j].option+1);
205 if (strcmp(pa[j].option, argv[i]) == 0)
211 else if (strcmp(buf, argv[i]) == 0)
218 else if (strcmp(pa[j].option, argv[i]) == 0)
222 fprintf(stderr, "Setting option %s more than once!\n",
230 *pa[j].u.i = iscan(*argc, argv, &i);
232 case etGMX_LARGE_INT:
233 *pa[j].u.is = istepscan(*argc, argv, &i);
237 *pa[j].u.r = dscan(*argc, argv, &i);
240 *(pa[j].u.c) = sscan(*argc, argv, &i);
244 ptr = sscan(*argc, argv, &i);
245 for (k = 1; (pa[j].u.c[k] != NULL); k++)
247 /* only check ptr against beginning of
249 if (gmx_strncasecmp(ptr, pa[j].u.c[k], strlen(ptr)) == 0)
251 if ( ( match == -1 ) ||
252 ( strlen(pa[j].u.c[k]) <
253 strlen(pa[j].u.c[match]) ) )
261 pa[j].u.c[0] = pa[j].u.c[match];
265 gmx_fatal(FARGS, "Invalid argument %s for option %s",
270 (*pa[j].u.rv)[0] = dscan(*argc, argv, &i);
271 if ( (i+1 == *argc) ||
272 ( (argv[i+1][0] == '-') &&
273 !isdigit(argv[i+1][1]) ) )
282 (*pa[j].u.rv)[1] = dscan(*argc, argv, &i);
283 if ( (i+1 == *argc) ||
284 ( (argv[i+1][0] == '-') &&
285 !isdigit(argv[i+1][1]) ) )
288 "%s: vector must have 1 or 3 real parameters",
292 (*pa[j].u.rv)[2] = dscan(*argc, argv, &i);
296 gmx_fatal(FARGS, "Invalid type %d in pargs", pa[j].type);
298 /* i may be incremented, so set it to not keep */
305 /* Remove used entries */
306 for (i = j = 0; (i <= *argc); i++)
318 int opt2parg_int(const char *option, int nparg, t_pargs pa[])
322 for (i = 0; (i < nparg); i++)
324 if (strcmp(pa[i].option, option) == 0)
330 gmx_fatal(FARGS, "No integer option %s in pargs", option);
335 gmx_bool opt2parg_gmx_bool(const char *option, int nparg, t_pargs pa[])
339 for (i = 0; (i < nparg); i++)
341 if (strcmp(pa[i].option, option) == 0)
347 gmx_fatal(FARGS, "No boolean option %s in pargs", option);
352 real opt2parg_real(const char *option, int nparg, t_pargs pa[])
356 for (i = 0; (i < nparg); i++)
358 if (strcmp(pa[i].option, option) == 0)
364 gmx_fatal(FARGS, "No real option %s in pargs", option);
369 const char *opt2parg_str(const char *option, int nparg, t_pargs pa[])
373 for (i = 0; (i < nparg); i++)
375 if (strcmp(pa[i].option, option) == 0)
381 gmx_fatal(FARGS, "No string option %s in pargs", option);
386 gmx_bool opt2parg_bSet(const char *option, int nparg, t_pargs pa[])
390 for (i = 0; (i < nparg); i++)
392 if (strcmp(pa[i].option, option) == 0)
398 gmx_fatal(FARGS, "No such option %s in pargs", option);
400 return FALSE; /* Too make some compilers happy */
403 const char *opt2parg_enum(const char *option, int nparg, t_pargs pa[])
407 for (i = 0; (i < nparg); i++)
409 if (strcmp(pa[i].option, option) == 0)
415 gmx_fatal(FARGS, "No such option %s in pargs", option);
420 /********************************************************************
421 * parse_common_args()
424 static void set_default_time_unit(const char *time_list[], gmx_bool bCanTime)
427 const char *select = NULL;
431 select = getenv("GMXTIMEUNIT");
435 while (time_list[i] && strcmp(time_list[i], select) != 0)
441 if (!bCanTime || select == NULL ||
442 time_list[i] == NULL || strcmp(time_list[i], select) != 0)
444 /* Set it to the default: ps */
446 while (time_list[i] && strcmp(time_list[i], "ps") != 0)
452 time_list[0] = time_list[i];
455 static void set_default_xvg_format(const char *xvg_list[])
460 select = getenv("GMX_VIEW_XVG");
463 /* The default is the first option */
464 xvg_list[0] = xvg_list[1];
469 while (xvg_list[i] && strcmp(xvg_list[i], select) != 0)
473 if (xvg_list[i] != NULL)
475 xvg_list[0] = xvg_list[i];
479 xvg_list[0] = xvg_list[exvgNONE];
484 static int add_parg(int npargs, t_pargs *pa, t_pargs *pa_add)
486 memcpy(&(pa[npargs]), pa_add, sizeof(*pa_add));
491 static char *mk_desc(t_pargs *pa, const char *time_unit_str)
493 char *newdesc = NULL, *ndesc = NULL, *nptr = NULL;
494 const char*ptr = NULL;
497 /* First compute length for description */
498 len = strlen(pa->desc)+1;
499 if ((ptr = strstr(pa->desc, "HIDDEN")) != NULL)
503 if (pa->type == etENUM)
506 for (k = 1; (pa->u.c[k] != NULL); k++)
508 len += strlen(pa->u.c[k])+12;
513 /* add label for hidden options */
516 sprintf(newdesc, "[hidden] %s", ptr+6);
520 strcpy(newdesc, pa->desc);
523 /* change '%t' into time_unit */
524 #define TUNITLABEL "%t"
525 #define NTUNIT strlen(TUNITLABEL)
526 if (pa->type == etTIME)
528 while ( (nptr = strstr(newdesc, TUNITLABEL)) != NULL)
532 len += strlen(time_unit_str)-NTUNIT;
534 strcpy(ndesc, newdesc);
535 strcat(ndesc, time_unit_str);
545 /* Add extra comment for enumerateds */
546 if (pa->type == etENUM)
548 strcat(newdesc, ": ");
549 for (k = 1; (pa->u.c[k] != NULL); k++)
551 strcat(newdesc, "[TT]");
552 strcat(newdesc, pa->u.c[k]);
553 strcat(newdesc, "[tt]");
554 /* Print a comma everywhere but at the last one */
555 if (pa->u.c[k+1] != NULL)
557 if (pa->u.c[k+2] == NULL)
559 strcat(newdesc, " or ");
563 strcat(newdesc, ", ");
572 gmx_bool parse_common_args(int *argc, char *argv[], unsigned long Flags,
573 int nfile, t_filenm fnm[], int npargs, t_pargs *pa,
574 int ndesc, const char **desc,
575 int nbugs, const char **bugs,
578 const char *manstr[] = {
579 NULL, "no", "help", "html", "nroff", "completion", NULL
581 /* This array should match the order of the enum in oenv.h */
582 const char *xvg_format[] = { NULL, "xmgrace", "xmgr", "none", NULL };
583 /* This array should match the order of the enum in oenv.h */
584 const char *time_units[] = {
585 NULL, "fs", "ps", "ns", "us", "ms", "s",
588 int nicelevel = 0, debug_level = 0;
590 real tbegin = 0, tend = 0, tdelta = 0;
591 gmx_bool bView = FALSE;
593 t_pargs *all_pa = NULL;
598 "-npri", FALSE, etINT, {&npri},
599 "HIDDEN Set non blocking priority (try 128)"
603 "-nice", FALSE, etINT, {&nicelevel},
606 t_pargs deffnm_pa = {
607 "-deffnm", FALSE, etSTR, {&deffnm},
608 "Set the default filename for all file options"
611 "-b", FALSE, etTIME, {&tbegin},
612 "First frame (%t) to read from trajectory"
615 "-e", FALSE, etTIME, {&tend},
616 "Last frame (%t) to read from trajectory"
619 "-dt", FALSE, etTIME, {&tdelta},
620 "Only use frame when t MOD dt = first time (%t)"
623 "-w", FALSE, etBOOL, {&bView},
624 "View output [TT].xvg[tt], [TT].xpm[tt], [TT].eps[tt] and [TT].pdb[tt] files"
627 "-xvg", FALSE, etENUM, {xvg_format},
628 "xvg plot formatting"
631 "-tu", FALSE, etENUM, {time_units},
634 /* Maximum number of extra arguments */
638 { "-man", FALSE, etENUM, {manstr},
639 "HIDDENWrite manual and quit" },
640 { "-debug", FALSE, etINT, {&debug_level},
641 "HIDDENWrite file with debug information, 1: short, 2: also x and f" },
643 #define NPCA_PA asize(pca_pa)
644 gmx_bool bExit, bXvgr;
645 int i, j, k, npall, max_pa;
647 // Handle the flags argument, which is a bit field
648 // The FF macro returns whether or not the bit is set
649 #define FF(arg) ((Flags & arg) == arg)
651 /* Check for double arguments */
652 for (i = 1; (i < *argc); i++)
654 if (argv[i] && (strlen(argv[i]) > 1) && (!std::isdigit(argv[i][1])))
656 for (j = i+1; (j < *argc); j++)
658 if ( (argv[i][0] == '-') && (argv[j][0] == '-') &&
659 (strcmp(argv[i], argv[j]) == 0) )
661 if (FF(PCA_NOEXIT_ON_ARGS))
663 fprintf(stderr, "Double command line argument %s\n",
668 gmx_fatal(FARGS, "Double command line argument %s\n",
677 /* Check ALL the flags ... */
678 max_pa = NPCA_PA + EXTRA_PA + npargs+1;
679 snew(all_pa, max_pa);
681 for (i = npall = 0; (i < static_cast<int>(NPCA_PA)); i++)
683 npall = add_parg(npall, all_pa, &(pca_pa[i]));
687 const char *envstr = getenv("GMXNPRIALL");
690 npri = strtol(envstr, NULL, 10);
694 envstr = getenv("GMXNPRI");
697 npri = strtol(envstr, NULL, 10);
700 npall = add_parg(npall, all_pa, &npri_pa);
707 npall = add_parg(npall, all_pa, &nice_pa);
709 if (FF(PCA_CAN_SET_DEFFNM))
711 npall = add_parg(npall, all_pa, &deffnm_pa);
713 if (FF(PCA_CAN_BEGIN))
715 npall = add_parg(npall, all_pa, &begin_pa);
719 npall = add_parg(npall, all_pa, &end_pa);
723 npall = add_parg(npall, all_pa, &dt_pa);
725 if (FF(PCA_TIME_UNIT))
727 npall = add_parg(npall, all_pa, &time_pa);
729 if (FF(PCA_CAN_VIEW))
731 npall = add_parg(npall, all_pa, &view_pa);
735 for (i = 0; (i < nfile); i++)
737 bXvgr = bXvgr || (fnm[i].ftp == efXVG);
741 npall = add_parg(npall, all_pa, &xvg_pa);
744 /* Now append the program specific arguments */
745 for (i = 0; (i < npargs); i++)
747 npall = add_parg(npall, all_pa, &(pa[i]));
750 /* set etENUM options to default */
751 for (i = 0; (i < npall); i++)
753 if (all_pa[i].type == etENUM)
755 all_pa[i].u.c[0] = all_pa[i].u.c[1];
758 set_default_time_unit(time_units, FF(PCA_TIME_UNIT));
759 set_default_xvg_format(xvg_format);
761 /* Now parse all the command-line options */
762 get_pargs(argc, argv, npall, all_pa, FF(PCA_KEEP_ARGS));
764 /* set program name, command line, and default values for output options */
765 output_env_init(oenv, *argc, argv, (time_unit_t)nenum(time_units), bView,
766 (xvg_format_t)nenum(xvg_format), 0, debug_level);
768 if (FF(PCA_CAN_SET_DEFFNM) && (deffnm != NULL))
770 set_default_file_name(deffnm);
773 /* Parse the file args */
774 parse_file_args(argc, argv, nfile, fnm, FF(PCA_KEEP_ARGS), !FF(PCA_NOT_READ_NODE));
776 /* Open the debug file */
781 if (gmx_mpi_initialized())
783 sprintf(buf, "%s%d.debug", output_env_get_short_program_name(*oenv),
788 sprintf(buf, "%s.debug", output_env_get_short_program_name(*oenv));
791 init_debug(debug_level, buf);
792 fprintf(stderr, "Opening debug file %s (src code file %s, line %d)\n",
793 buf, __FILE__, __LINE__);
796 /* Now copy the results back... */
797 for (i = 0, k = npall-npargs; (i < npargs); i++, k++)
799 memcpy(&(pa[i]), &(all_pa[k]), (size_t)sizeof(pa[i]));
803 for (i = 0; (i < npall); i++)
805 all_pa[i].desc = mk_desc(&(all_pa[i]), output_env_get_time_unit(*oenv));
809 GMX_ASSERT(manstr[0] != NULL,
810 "Enum option default assignment should have changed this");
811 bExit = (strcmp(manstr[0], "no") != 0);
813 #if (defined __sgi && USE_SGI_FPE)
817 /* Set the nice level */
819 if (npri != 0 && !bExit)
821 schedctl(MPTS_RTPRI, 0, npri);
827 /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */
828 if (nicelevel != 0 && !bExit)
830 static gmx_bool nice_set = FALSE; /* only set it once */
831 static tMPI_Thread_mutex_t init_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
832 tMPI_Thread_mutex_lock(&init_mutex);
835 if (nice(nicelevel) == -1)
837 /* Do nothing, but use the return value to avoid warnings. */
841 tMPI_Thread_mutex_unlock(&init_mutex);
846 if (strcmp(manstr[0], "no") != 0 && !(FF(PCA_QUIET)))
850 if (!strcmp(manstr[0], "completion"))
852 /* one file each for csh, bash and zsh if we do completions */
853 write_man("completion-zsh", output_env_get_short_program_name(*oenv),
854 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs);
855 write_man("completion-bash", output_env_get_short_program_name(*oenv),
856 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs);
857 write_man("completion-csh", output_env_get_short_program_name(*oenv),
858 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs);
862 write_man(manstr[0], output_env_get_short_program_name(*oenv),
863 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs);
866 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
869 /* convert time options, must be done after printing! */
871 for (i = 0; i < npall; i++)
873 if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0))
875 *all_pa[i].u.r *= output_env_get_time_invfactor(*oenv);
879 /* Extract Time info from arguments */
880 if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b", npall, all_pa))
882 setTimeValue(TBEGIN, opt2parg_real("-b", npall, all_pa));
885 if (FF(PCA_CAN_END) && opt2parg_bSet("-e", npall, all_pa))
887 setTimeValue(TEND, opt2parg_real("-e", npall, all_pa));
890 if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt", npall, all_pa))
892 setTimeValue(TDELTA, opt2parg_real("-dt", npall, all_pa));
896 for (i = 0; i < npall; ++i)
898 sfree((void *)all_pa[i].desc);
902 if (!FF(PCA_NOEXIT_ON_ARGS))