Fix remaining copyright headers
[alexxy/gromacs.git] / src / gromacs / commandline / pargs.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 /* This file is completely threadsafe - keep it that way! */
38 #include "gromacs/commandline/pargs.h"
39
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43
44 #include <cctype>
45 #include <cstdio>
46 #include <cstdlib>
47 #include <cstring>
48
49 #ifdef HAVE_UNISTD_H
50 #include <unistd.h>
51 #endif
52
53 /* used for npri */
54 #ifdef __sgi
55 #include <sys/schedctl.h>
56 #include <sys/sysmp.h>
57 #endif
58
59 #include "gromacs/legacyheaders/gmx_fatal.h"
60 #include "gromacs/legacyheaders/macros.h"
61 #include "gromacs/legacyheaders/network.h"
62 #include "gromacs/legacyheaders/smalloc.h"
63 #include "gromacs/legacyheaders/string2.h"
64 #include "gromacs/legacyheaders/thread_mpi/threads.h"
65
66 #include "gromacs/commandline/cmdlinehelpcontext.h"
67 #include "gromacs/commandline/shellcompletions.h"
68 #include "gromacs/commandline/wman.h"
69 #include "gromacs/fileio/timecontrol.h"
70 #include "gromacs/utility/exceptions.h"
71 #include "gromacs/utility/gmxassert.h"
72
73
74 /* The source code in this file should be thread-safe.
75       Please keep it that way. */
76
77 static void usage(const char *type, const char *arg)
78 {
79     GMX_ASSERT(arg != NULL, "NULL command-line argument should not occur");
80     gmx_fatal(FARGS, "Expected %s argument for option %s\n", type, arg);
81 }
82
83 /* Scan an int for argument argv[*i] from argument at argv[*i + 1].
84  * eg: -p 32.  argv[*i] is only used for error reporting.
85  * If there is no value, or the conversion is not successful, the
86  * routine exits with an error, otherwise it returns the value found.
87  * *i is incremented once.
88  */
89 static int iscan(int argc, char *argv[], int *i)
90 {
91     const char *const arg = argv[*i];
92     if (argc <= (*i)+1)
93     {
94         usage("an integer", arg);
95     }
96     const char *const value = argv[++(*i)];
97     char             *endptr;
98     int               var = std::strtol(value, &endptr, 10);
99     if (*value == '\0' || *endptr != '\0')
100     {
101         usage("an integer", arg);
102     }
103     return var;
104 }
105
106 /* Same as above, but for large integer values */
107 static gmx_int64_t istepscan(int argc, char *argv[], int *i)
108 {
109     const char *const arg = argv[*i];
110     if (argc <= (*i)+1)
111     {
112         usage("an integer", arg);
113     }
114     const char *const value = argv[++(*i)];
115     char             *endptr;
116     gmx_int64_t       var = str_to_int64_t(value, &endptr);
117     if (*value == '\0' || *endptr != '\0')
118     {
119         usage("an integer", arg);
120     }
121     return var;
122 }
123
124 /* Routine similar to the above, but working on doubles. */
125 static double dscan(int argc, char *argv[], int *i)
126 {
127     const char *const arg = argv[*i];
128     if (argc <= (*i)+1)
129     {
130         usage("a real", arg);
131     }
132     const char *const value = argv[++(*i)];
133     char             *endptr;
134     double            var = std::strtod(value, &endptr);
135     if (*value == '\0' || *endptr != '\0')
136     {
137         usage("a real", arg);
138     }
139     return var;
140 }
141
142 /* Routine similar to the above, but working on strings. The pointer
143  * returned is a pointer to the argv field.
144  */
145 static char *sscan(int argc, char *argv[], int *i)
146 {
147     if (argc > (*i)+1)
148     {
149         if ( (argv[(*i)+1][0] == '-') && (argc > (*i)+2) &&
150              (argv[(*i)+2][0] != '-') )
151         {
152             fprintf(stderr, "Possible missing string argument for option %s\n\n",
153                     argv[*i]);
154         }
155     }
156     else
157     {
158         usage("a string", argv[*i]);
159     }
160
161     return argv[++(*i)];
162 }
163
164 gmx_bool is_hidden(t_pargs *pa)
165 {
166     return ((strstr(pa->desc, "HIDDEN") != NULL) ||
167             (strstr(pa->desc, "[hidden]") != NULL));
168 }
169
170 int nenum(const char *const enumc[])
171 {
172     int i;
173
174     i = 1;
175     /* we *can* compare pointers directly here! */
176     while (enumc[i] && enumc[0] != enumc[i])
177     {
178         i++;
179     }
180
181     return i;
182 }
183
184 /* Read a number of arguments from the command line.
185  * For etINT, etREAL and etCHAR an extra argument is read (when present)
186  * for etBOOL the gmx_boolean option is changed to the negate value
187  * If !bKeepArgs, the command line arguments are removed from the command line
188  */
189 static void get_pargs(int *argc, char *argv[], int nparg, t_pargs pa[],
190                       gmx_bool bKeepArgs)
191 {
192     int       i, j, k, match;
193     gmx_bool *bKeep;
194     char      buf[32];
195     char     *ptr;
196
197     snew(bKeep, *argc+1);
198     bKeep[0]     = TRUE;
199     bKeep[*argc] = TRUE;
200
201     for (i = 1; (i < *argc); i++)
202     {
203         bKeep[i] = TRUE;
204         for (j = 0; (j < nparg); j++)
205         {
206             if (pa[j].type == etBOOL)
207             {
208                 sprintf(buf, "-no%s", pa[j].option+1);
209                 if (strcmp(pa[j].option, argv[i]) == 0)
210                 {
211                     *pa[j].u.b = TRUE;
212                     pa[j].bSet = TRUE;
213                     bKeep[i]   = FALSE;
214                 }
215                 else if (strcmp(buf, argv[i]) == 0)
216                 {
217                     *pa[j].u.b = FALSE;
218                     pa[j].bSet = TRUE;
219                     bKeep[i]   = FALSE;
220                 }
221             }
222             else if (strcmp(pa[j].option, argv[i]) == 0)
223             {
224                 if (pa[j].bSet)
225                 {
226                     fprintf(stderr, "Setting option %s more than once!\n",
227                             pa[j].option);
228                 }
229                 pa[j].bSet = TRUE;
230                 bKeep[i]   = FALSE;
231                 switch (pa[j].type)
232                 {
233                     case etINT:
234                         *pa[j].u.i = iscan(*argc, argv, &i);
235                         break;
236                     case etINT64:
237                         *pa[j].u.is = istepscan(*argc, argv, &i);
238                         break;
239                     case etTIME:
240                     case etREAL:
241                         *pa[j].u.r = dscan(*argc, argv, &i);
242                         break;
243                     case etSTR:
244                         *(pa[j].u.c) = sscan(*argc, argv, &i);
245                         break;
246                     case etENUM:
247                         match = -1;
248                         ptr   = sscan(*argc, argv, &i);
249                         for (k = 1; (pa[j].u.c[k] != NULL); k++)
250                         {
251                             /* only check ptr against beginning of
252                                pa[j].u.c[k] */
253                             if (gmx_strncasecmp(ptr, pa[j].u.c[k], strlen(ptr)) == 0)
254                             {
255                                 if ( ( match == -1 ) ||
256                                      ( strlen(pa[j].u.c[k]) <
257                                        strlen(pa[j].u.c[match]) ) )
258                                 {
259                                     match = k;
260                                 }
261                             }
262                         }
263                         if (match != -1)
264                         {
265                             pa[j].u.c[0] = pa[j].u.c[match];
266                         }
267                         else
268                         {
269                             gmx_fatal(FARGS, "Invalid argument %s for option %s",
270                                       ptr, pa[j].option);
271                         }
272                         break;
273                     case etRVEC:
274                         (*pa[j].u.rv)[0] = dscan(*argc, argv, &i);
275                         if ( (i+1 == *argc) ||
276                              ( (argv[i+1][0] == '-') &&
277                                !isdigit(argv[i+1][1]) ) )
278                         {
279                             (*pa[j].u.rv)[1]     =
280                                 (*pa[j].u.rv)[2] =
281                                     (*pa[j].u.rv)[0];
282                         }
283                         else
284                         {
285                             bKeep[i]         = FALSE;
286                             (*pa[j].u.rv)[1] = dscan(*argc, argv, &i);
287                             if ( (i+1 == *argc) ||
288                                  ( (argv[i+1][0] == '-') &&
289                                    !isdigit(argv[i+1][1]) ) )
290                             {
291                                 gmx_fatal(FARGS,
292                                           "%s: vector must have 1 or 3 real parameters",
293                                           pa[j].option);
294                             }
295                             bKeep[i]         = FALSE;
296                             (*pa[j].u.rv)[2] = dscan(*argc, argv, &i);
297                         }
298                         break;
299                     default:
300                         gmx_fatal(FARGS, "Invalid type %d in pargs", pa[j].type);
301                 }
302                 /* i may be incremented, so set it to not keep */
303                 bKeep[i] = FALSE;
304             }
305         }
306     }
307     if (!bKeepArgs)
308     {
309         /* Remove used entries */
310         for (i = j = 0; (i <= *argc); i++)
311         {
312             if (bKeep[i])
313             {
314                 argv[j++] = argv[i];
315             }
316         }
317         (*argc) = j-1;
318     }
319     sfree(bKeep);
320 }
321
322 int opt2parg_int(const char *option, int nparg, t_pargs pa[])
323 {
324     int i;
325
326     for (i = 0; (i < nparg); i++)
327     {
328         if (strcmp(pa[i].option, option) == 0)
329         {
330             return *pa[i].u.i;
331         }
332     }
333
334     gmx_fatal(FARGS, "No integer option %s in pargs", option);
335
336     return 0;
337 }
338
339 gmx_bool opt2parg_gmx_bool(const char *option, int nparg, t_pargs pa[])
340 {
341     int i;
342
343     for (i = 0; (i < nparg); i++)
344     {
345         if (strcmp(pa[i].option, option) == 0)
346         {
347             return *pa[i].u.b;
348         }
349     }
350
351     gmx_fatal(FARGS, "No boolean option %s in pargs", option);
352
353     return FALSE;
354 }
355
356 real opt2parg_real(const char *option, int nparg, t_pargs pa[])
357 {
358     int i;
359
360     for (i = 0; (i < nparg); i++)
361     {
362         if (strcmp(pa[i].option, option) == 0)
363         {
364             return *pa[i].u.r;
365         }
366     }
367
368     gmx_fatal(FARGS, "No real option %s in pargs", option);
369
370     return 0.0;
371 }
372
373 const char *opt2parg_str(const char *option, int nparg, t_pargs pa[])
374 {
375     int i;
376
377     for (i = 0; (i < nparg); i++)
378     {
379         if (strcmp(pa[i].option, option) == 0)
380         {
381             return *(pa[i].u.c);
382         }
383     }
384
385     gmx_fatal(FARGS, "No string option %s in pargs", option);
386
387     return NULL;
388 }
389
390 gmx_bool opt2parg_bSet(const char *option, int nparg, t_pargs pa[])
391 {
392     int i;
393
394     for (i = 0; (i < nparg); i++)
395     {
396         if (strcmp(pa[i].option, option) == 0)
397         {
398             return pa[i].bSet;
399         }
400     }
401
402     gmx_fatal(FARGS, "No such option %s in pargs", option);
403
404     return FALSE; /* Too make some compilers happy */
405 }
406
407 const char *opt2parg_enum(const char *option, int nparg, t_pargs pa[])
408 {
409     int i;
410
411     for (i = 0; (i < nparg); i++)
412     {
413         if (strcmp(pa[i].option, option) == 0)
414         {
415             return pa[i].u.c[0];
416         }
417     }
418
419     gmx_fatal(FARGS, "No such option %s in pargs", option);
420
421     return NULL;
422 }
423
424 /********************************************************************
425  * parse_common_args()
426  */
427
428 static void set_default_time_unit(const char *time_list[], gmx_bool bCanTime)
429 {
430     int         i      = 0;
431     const char *select = NULL;
432
433     if (bCanTime)
434     {
435         select = getenv("GMXTIMEUNIT");
436         if (select != NULL)
437         {
438             i = 1;
439             while (time_list[i] && strcmp(time_list[i], select) != 0)
440             {
441                 i++;
442             }
443         }
444     }
445     if (!bCanTime || select == NULL ||
446         time_list[i] == NULL || strcmp(time_list[i], select) != 0)
447     {
448         /* Set it to the default: ps */
449         i = 1;
450         while (time_list[i] && strcmp(time_list[i], "ps") != 0)
451         {
452             i++;
453         }
454
455     }
456     time_list[0] = time_list[i];
457 }
458
459 static void set_default_xvg_format(const char *xvg_list[])
460 {
461     int         i;
462     const char *select;
463
464     select = getenv("GMX_VIEW_XVG");
465     if (select == NULL)
466     {
467         /* The default is the first option */
468         xvg_list[0] = xvg_list[1];
469     }
470     else
471     {
472         i = 1;
473         while (xvg_list[i] && strcmp(xvg_list[i], select) != 0)
474         {
475             i++;
476         }
477         if (xvg_list[i] != NULL)
478         {
479             xvg_list[0] = xvg_list[i];
480         }
481         else
482         {
483             xvg_list[0] = xvg_list[exvgNONE];
484         }
485     }
486 }
487
488 static int add_parg(int npargs, t_pargs *pa, t_pargs *pa_add)
489 {
490     memcpy(&(pa[npargs]), pa_add, sizeof(*pa_add));
491
492     return npargs+1;
493 }
494
495 static char *mk_desc(t_pargs *pa, const char *time_unit_str)
496 {
497     char      *newdesc = NULL, *ndesc = NULL, *nptr = NULL;
498     const char*ptr     = NULL;
499     int        len, k;
500
501     /* First compute length for description */
502     len = strlen(pa->desc)+1;
503     if ((ptr = strstr(pa->desc, "HIDDEN")) != NULL)
504     {
505         len += 4;
506     }
507     if (pa->type == etENUM)
508     {
509         len += 10;
510         for (k = 1; (pa->u.c[k] != NULL); k++)
511         {
512             len += strlen(pa->u.c[k])+12;
513         }
514     }
515     snew(newdesc, len);
516
517     /* add label for hidden options */
518     if (is_hidden(pa))
519     {
520         sprintf(newdesc, "[hidden] %s", ptr+6);
521     }
522     else
523     {
524         strcpy(newdesc, pa->desc);
525     }
526
527     /* change '%t' into time_unit */
528 #define TUNITLABEL "%t"
529 #define NTUNIT strlen(TUNITLABEL)
530     if (pa->type == etTIME)
531     {
532         while ( (nptr = strstr(newdesc, TUNITLABEL)) != NULL)
533         {
534             nptr[0] = '\0';
535             nptr   += NTUNIT;
536             len    += strlen(time_unit_str)-NTUNIT;
537             snew(ndesc, len);
538             strcpy(ndesc, newdesc);
539             strcat(ndesc, time_unit_str);
540             strcat(ndesc, nptr);
541             sfree(newdesc);
542             newdesc = ndesc;
543             ndesc   = NULL;
544         }
545     }
546 #undef TUNITLABEL
547 #undef NTUNIT
548
549     /* Add extra comment for enumerateds */
550     if (pa->type == etENUM)
551     {
552         strcat(newdesc, ": ");
553         for (k = 1; (pa->u.c[k] != NULL); k++)
554         {
555             strcat(newdesc, "[TT]");
556             strcat(newdesc, pa->u.c[k]);
557             strcat(newdesc, "[tt]");
558             /* Print a comma everywhere but at the last one */
559             if (pa->u.c[k+1] != NULL)
560             {
561                 if (pa->u.c[k+2] == NULL)
562                 {
563                     strcat(newdesc, " or ");
564                 }
565                 else
566                 {
567                     strcat(newdesc, ", ");
568                 }
569             }
570         }
571     }
572     return newdesc;
573 }
574
575
576 gmx_bool parse_common_args(int *argc, char *argv[], unsigned long Flags,
577                            int nfile, t_filenm fnm[], int npargs, t_pargs *pa,
578                            int ndesc, const char **desc,
579                            int nbugs, const char **bugs,
580                            output_env_t *oenv)
581 {
582     const char *manstr[] = {
583         NULL, "no", "completion", NULL
584     };
585     /* This array should match the order of the enum in oenv.h */
586     const char *xvg_format[] = { NULL, "xmgrace", "xmgr", "none", NULL };
587     /* This array should match the order of the enum in oenv.h */
588     const char *time_units[] = {
589         NULL, "fs", "ps", "ns", "us", "ms", "s",
590         NULL
591     };
592     int         nicelevel = 0, debug_level = 0;
593     char       *deffnm    = NULL;
594     real        tbegin    = 0, tend = 0, tdelta = 0;
595     gmx_bool    bView     = FALSE;
596
597     t_pargs    *all_pa = NULL;
598
599 #ifdef __sgi
600     int     npri      = 0;
601     t_pargs npri_pa   = {
602         "-npri", FALSE, etINT,   {&npri},
603         "HIDDEN Set non blocking priority (try 128)"
604     };
605 #endif
606     t_pargs nice_pa   = {
607         "-nice", FALSE, etINT,   {&nicelevel},
608         "Set the nicelevel"
609     };
610     t_pargs deffnm_pa = {
611         "-deffnm", FALSE, etSTR, {&deffnm},
612         "Set the default filename for all file options"
613     };
614     t_pargs begin_pa  = {
615         "-b",    FALSE, etTIME,  {&tbegin},
616         "First frame (%t) to read from trajectory"
617     };
618     t_pargs end_pa    = {
619         "-e",    FALSE, etTIME,  {&tend},
620         "Last frame (%t) to read from trajectory"
621     };
622     t_pargs dt_pa     = {
623         "-dt",   FALSE, etTIME,  {&tdelta},
624         "Only use frame when t MOD dt = first time (%t)"
625     };
626     t_pargs view_pa   = {
627         "-w",    FALSE, etBOOL,  {&bView},
628         "View output [TT].xvg[tt], [TT].xpm[tt], [TT].eps[tt] and [TT].pdb[tt] files"
629     };
630     t_pargs xvg_pa    = {
631         "-xvg",  FALSE, etENUM,  {xvg_format},
632         "xvg plot formatting"
633     };
634     t_pargs time_pa   = {
635         "-tu",   FALSE, etENUM,  {time_units},
636         "Time unit"
637     };
638     /* Maximum number of extra arguments */
639 #define EXTRA_PA 16
640
641     t_pargs  pca_pa[] = {
642         { "-man",  FALSE, etENUM,  {manstr},
643           "HIDDENWrite manual and quit" },
644         { "-debug", FALSE, etINT, {&debug_level},
645           "HIDDENWrite file with debug information, 1: short, 2: also x and f" },
646     };
647 #define NPCA_PA asize(pca_pa)
648     gmx_bool bXvgr;
649     int      i, j, k, npall, max_pa;
650
651     // Handle the flags argument, which is a bit field
652     // The FF macro returns whether or not the bit is set
653 #define FF(arg) ((Flags & arg) == arg)
654
655     /* Check for double arguments */
656     for (i = 1; (i < *argc); i++)
657     {
658         if (argv[i] && (strlen(argv[i]) > 1) && (!std::isdigit(argv[i][1])))
659         {
660             for (j = i+1; (j < *argc); j++)
661             {
662                 if ( (argv[i][0] == '-') && (argv[j][0] == '-') &&
663                      (strcmp(argv[i], argv[j]) == 0) )
664                 {
665                     if (FF(PCA_NOEXIT_ON_ARGS))
666                     {
667                         fprintf(stderr, "Double command line argument %s\n",
668                                 argv[i]);
669                     }
670                     else
671                     {
672                         gmx_fatal(FARGS, "Double command line argument %s\n",
673                                   argv[i]);
674                     }
675                 }
676             }
677         }
678     }
679     debug_gmx();
680
681     /* Check ALL the flags ... */
682     max_pa = NPCA_PA + EXTRA_PA + npargs+1;
683     snew(all_pa, max_pa);
684
685     for (i = npall = 0; (i < static_cast<int>(NPCA_PA)); i++)
686     {
687         npall = add_parg(npall, all_pa, &(pca_pa[i]));
688     }
689
690 #ifdef __sgi
691     const char *envstr = getenv("GMXNPRIALL");
692     if (envstr)
693     {
694         npri = strtol(envstr, NULL, 10);
695     }
696     if (FF(PCA_BE_NICE))
697     {
698         envstr = getenv("GMXNPRI");
699         if (envstr)
700         {
701             npri = strtol(envstr, NULL, 10);
702         }
703     }
704     npall = add_parg(npall, all_pa, &npri_pa);
705 #endif
706
707     if (FF(PCA_BE_NICE))
708     {
709         nicelevel = 19;
710     }
711     npall = add_parg(npall, all_pa, &nice_pa);
712
713     if (FF(PCA_CAN_SET_DEFFNM))
714     {
715         npall = add_parg(npall, all_pa, &deffnm_pa);
716     }
717     if (FF(PCA_CAN_BEGIN))
718     {
719         npall = add_parg(npall, all_pa, &begin_pa);
720     }
721     if (FF(PCA_CAN_END))
722     {
723         npall = add_parg(npall, all_pa, &end_pa);
724     }
725     if (FF(PCA_CAN_DT))
726     {
727         npall = add_parg(npall, all_pa, &dt_pa);
728     }
729     if (FF(PCA_TIME_UNIT))
730     {
731         npall = add_parg(npall, all_pa, &time_pa);
732     }
733     if (FF(PCA_CAN_VIEW))
734     {
735         npall = add_parg(npall, all_pa, &view_pa);
736     }
737
738     bXvgr = FALSE;
739     for (i = 0; (i < nfile); i++)
740     {
741         bXvgr = bXvgr ||  (fnm[i].ftp == efXVG);
742     }
743     if (bXvgr)
744     {
745         npall = add_parg(npall, all_pa, &xvg_pa);
746     }
747
748     /* Now append the program specific arguments */
749     for (i = 0; (i < npargs); i++)
750     {
751         npall = add_parg(npall, all_pa, &(pa[i]));
752     }
753
754     /* set etENUM options to default */
755     for (i = 0; (i < npall); i++)
756     {
757         if (all_pa[i].type == etENUM)
758         {
759             all_pa[i].u.c[0] = all_pa[i].u.c[1];
760         }
761     }
762     set_default_time_unit(time_units, FF(PCA_TIME_UNIT));
763     set_default_xvg_format(xvg_format);
764
765     /* Now parse all the command-line options */
766     get_pargs(argc, argv, npall, all_pa, FF(PCA_KEEP_ARGS));
767
768     /* set program name, command line, and default values for output options */
769     output_env_init(oenv, *argc, argv, (time_unit_t)nenum(time_units), bView,
770                     (xvg_format_t)nenum(xvg_format), 0, debug_level);
771
772     /* Parse the file args */
773     parse_file_args(argc, argv, nfile, fnm, deffnm,
774                     FF(PCA_KEEP_ARGS), !FF(PCA_NOT_READ_NODE));
775
776     /* Open the debug file */
777     if (debug_level > 0)
778     {
779         char buf[256];
780
781         if (gmx_mpi_initialized())
782         {
783             sprintf(buf, "%s%d.debug", output_env_get_short_program_name(*oenv),
784                     gmx_node_rank());
785         }
786         else
787         {
788             sprintf(buf, "%s.debug", output_env_get_short_program_name(*oenv));
789         }
790
791         init_debug(debug_level, buf);
792         fprintf(stderr, "Opening debug file %s (src code file %s, line %d)\n",
793                 buf, __FILE__, __LINE__);
794     }
795
796     /* Now copy the results back... */
797     for (i = 0, k = npall-npargs; (i < npargs); i++, k++)
798     {
799         memcpy(&(pa[i]), &(all_pa[k]), (size_t)sizeof(pa[i]));
800     }
801
802
803     for (i = 0; (i < npall); i++)
804     {
805         all_pa[i].desc = mk_desc(&(all_pa[i]), output_env_get_time_unit(*oenv));
806     }
807
808 #if (defined __sgi && USE_SGI_FPE)
809     doexceptions();
810 #endif
811
812     bool bExit = false;
813     try
814     {
815         const gmx::CommandLineHelpContext *context =
816             gmx::GlobalCommandLineHelpContext::get();
817         bExit = (context != NULL || strcmp(manstr[0], "no") != 0);
818         if (!(FF(PCA_QUIET)))
819         {
820             if (context != NULL)
821             {
822                 write_man(*context, ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs);
823             }
824             else if (!strcmp(manstr[0], "completion"))
825             {
826                 const char *program = output_env_get_short_program_name(*oenv);
827                 /* one file each for csh, bash and zsh if we do completions */
828                 write_completions("completion-zsh", program, nfile, fnm, npall, all_pa);
829                 write_completions("completion-bash", program, nfile, fnm, npall, all_pa);
830                 write_completions("completion-csh", program, nfile, fnm, npall, all_pa);
831             }
832         }
833     }
834     GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
835
836     /* Set the nice level */
837 #ifdef __sgi
838     if (npri != 0 && !bExit)
839     {
840         schedctl(MPTS_RTPRI, 0, npri);
841     }
842 #endif
843
844 #ifdef HAVE_UNISTD_H
845 #ifndef GMX_NO_NICE
846     /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */
847     if (nicelevel != 0 && !bExit)
848     {
849         static gmx_bool            nice_set   = FALSE; /* only set it once */
850         static tMPI_Thread_mutex_t init_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
851         tMPI_Thread_mutex_lock(&init_mutex);
852         if (!nice_set)
853         {
854             if (nice(nicelevel) == -1)
855             {
856                 /* Do nothing, but use the return value to avoid warnings. */
857             }
858             nice_set = TRUE;
859         }
860         tMPI_Thread_mutex_unlock(&init_mutex);
861     }
862 #endif
863 #endif
864
865     /* convert time options, must be done after printing! */
866
867     for (i = 0; i < npall; i++)
868     {
869         if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0))
870         {
871             *all_pa[i].u.r *= output_env_get_time_invfactor(*oenv);
872         }
873     }
874
875     /* Extract Time info from arguments */
876     if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b", npall, all_pa))
877     {
878         setTimeValue(TBEGIN, opt2parg_real("-b", npall, all_pa));
879     }
880
881     if (FF(PCA_CAN_END) && opt2parg_bSet("-e", npall, all_pa))
882     {
883         setTimeValue(TEND, opt2parg_real("-e", npall, all_pa));
884     }
885
886     if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt", npall, all_pa))
887     {
888         setTimeValue(TDELTA, opt2parg_real("-dt", npall, all_pa));
889     }
890
891     /* clear memory */
892     for (i = 0; i < npall; ++i)
893     {
894         sfree((void *)all_pa[i].desc);
895     }
896     sfree(all_pa);
897
898     if (!FF(PCA_NOEXIT_ON_ARGS))
899     {
900         if (*argc > 1)
901         {
902             gmx_cmd(argv[1]);
903         }
904     }
905     return !bExit;
906 #undef FF
907 }