void printFatalErrorHeader(FILE *fp, const char *title, const char *func, const char *file, int line) { // In case ProgramInfo is not initialized and there is an issue with the // initialization, fall back to "GROMACS". const char *programName = "GROMACS"; try { programName = getProgramContext().displayName(); } catch (const std::exception &) { } std::fprintf(fp, "\n-------------------------------------------------------\n"); std::fprintf(fp, "Program: %s, version %s\n", programName, gmx_version()); if (file != nullptr) { std::fprintf(fp, "Source file: %s (line %d)\n", Path::stripSourcePrefix(file), line); } if (func != nullptr) { std::fprintf(fp, "Function: %s\n", func); } if (gmx_node_num() > 1) { std::fprintf(fp, "MPI rank: %d (out of %d)\n", gmx_node_rank(), gmx_node_num()); } std::fprintf(fp, "\n"); std::fprintf(fp, "%s:\n", title); }
void gmx_abort(int errorno) { const char *programName = "GROMACS"; try { programName = gmx::getProgramContext().displayName(); } catch (const std::exception &) { } const int nnodes = gmx_node_num(); const int noderank = gmx_node_rank(); if (nnodes > 1) { std::fprintf(stderr, "Halting parallel program %s on rank %d out of %d\n", programName, noderank, nnodes); } else { std::fprintf(stderr, "Halting program %s\n", programName); } MPI_Abort(MPI_COMM_WORLD, errorno); std::exit(errorno); }
int processExceptionAtExit(const std::exception & /*ex*/) { int returnCode = 1; // If we have more than one rank (whether real MPI or thread-MPI), // we cannot currently know whether just one rank or all ranks // actually threw the error, so we need to exit here. // Returning would mean graceful cleanup, which is not possible if // some code is still executing on other ranks/threads. if (gmx_node_num() > 1) { gmx_exit_on_fatal_error(ExitType_Abort, returnCode); } return returnCode; }
int SimulationRunner::callMdrun(const CommandLine &callerRef) { /* Conforming to style guide by not passing a non-const reference to this function. Passing a non-const reference might make it easier to write code that incorrectly re-uses callerRef after the call to this function. */ CommandLine caller(callerRef); caller.addOption("-s", tprFileName_); caller.addOption("-g", logFileName_); caller.addOption("-e", edrFileName_); caller.addOption("-o", fullPrecisionTrajectoryFileName_); caller.addOption("-x", reducedPrecisionTrajectoryFileName_); caller.addOption("-deffnm", fixture_->fileManager_.getTemporaryFilePath("state")); if (nsteps_ > -2) { caller.addOption("-nsteps", nsteps_); } #ifdef GMX_MPI # ifdef GMX_GPU # ifdef GMX_THREAD_MPI int numGpusNeeded = g_numThreads; # else /* Must be real MPI */ int numGpusNeeded = gmx_node_num(); # endif std::string gpuIdString(numGpusNeeded, '0'); caller.addOption("-gpu_id", gpuIdString.c_str()); # endif #endif #ifdef GMX_THREAD_MPI caller.addOption("-nt", g_numThreads); #endif #ifdef GMX_OPENMP caller.addOption("-ntomp", g_numOpenMPThreads); #endif return gmx_mdrun(caller.argc(), caller.argv()); }
static void quit_gmx(const char *msg) { if (!fatal_errno) { if (log_file) fprintf(log_file,"%s\n",msg); fprintf(stderr,"%s\n",msg); /* we set it to no-zero because if this function is called, something has gone wrong */ fatal_errno=255; } else { if (fatal_errno != -1) errno=fatal_errno; perror(msg); } if (gmx_parallel_env) { int nnodes; int noderank; nnodes = gmx_node_num(); noderank = gmx_node_rank(); if (nnodes > 1) fprintf(stderr,"Error on node %d, will try to stop all the nodes\n", noderank); gmx_abort(noderank,nnodes,-1); } else { if (debug) fflush(debug); if (bDebug) { fprintf(stderr,"dump core (y/n):"); fflush(stderr); if (toupper(getc(stdin))!='N') (void) abort(); } } exit(fatal_errno); }
static void quit_gmx(const char *msg) { if (!fatal_errno) { if (log_file) fprintf(log_file,"%s\n",msg); fprintf(stderr,"%s\n",msg); } else { if (fatal_errno != -1) errno=fatal_errno; perror(msg); } if (gmx_parallel_env) { int nnodes; int noderank; nnodes = gmx_node_num(); noderank = gmx_node_rank(); if (nnodes > 1) fprintf(stderr,"Error on node %d, will try to stop all the nodes\n", noderank); gmx_abort(noderank,nnodes,-1); } else { if (debug) fflush(debug); if (bDebug) { fprintf(stderr,"dump core (y/n):"); fflush(stderr); if (toupper(getc(stdin))!='N') (void) abort(); } } exit(-1); }
void quit_gmx(int fatal_errno,char *msg) { if (!fatal_errno) { if (stdlog) fprintf(stdlog,"%s\n",msg); fprintf(stderr,"%s\n",msg); } else { if (fatal_errno != -1) errno=fatal_errno; perror(msg); } #ifdef USE_MPI if (gmx_parallel) { int nnodes; int nodeid; nnodes = gmx_node_num(); nodeid = gmx_node_id(); if (nnodes > 1) fprintf(stderr,"Error on node %d, will try to stop all the nodes\n",nodeid); gmx_abort(nodeid,nnodes,-1); } #else if (debug) fflush(debug); if (bDebug) { fprintf(stderr,"dump core (y/n):"); fflush(stderr); if (toupper(getc(stdin))!='N') (void) abort(); } #endif exit(-1); }
//! \cond internal void initTestUtils(const char *dataPath, const char *tempPath, bool usesMpi, bool usesHardwareDetection, int *argc, char ***argv) { #if !defined NDEBUG && \ !((defined __clang__ || (defined(__GNUC__) && !defined(__ICC) && __GNUC__ == 7)) \ && defined __OPTIMIZE__) gmx_feenableexcept(); #endif const CommandLineProgramContext &context = initForCommandLine(argc, argv); try { if (!usesMpi && gmx_node_num() > 1) { // We cannot continue, since some tests might be using // MPI_COMM_WORLD, which could deadlock if we would only // continue with the master rank here. if (gmx_node_rank() == 0) { fprintf(stderr, "NOTE: You are running %s on %d MPI ranks, " "but it is does not contain MPI-enabled tests. " "The test will now exit.\n", context.programName(), gmx_node_num()); } finalizeForCommandLine(); std::exit(1); } if (usesHardwareDetection) { callAddGlobalTestEnvironment(); } g_testContext = gmx::compat::make_unique<TestProgramContext>(context); setProgramContext(g_testContext.get()); // Use the default finder that does not respect GMXLIB, since the tests // generally can only get confused by a different set of data files. setLibraryFileFinder(nullptr); ::testing::InitGoogleMock(argc, *argv); if (dataPath != nullptr) { TestFileManager::setInputDataDirectory( Path::join(CMAKE_SOURCE_DIR, dataPath)); } if (tempPath != nullptr) { TestFileManager::setGlobalOutputTempDirectory(tempPath); } bool bHelp = false; std::string sourceRoot; Options options; // TODO: A single option that accepts multiple names would be nicer. // Also, we recognize -help, but GTest doesn't, which leads to a bit // unintuitive behavior. options.addOption(BooleanOption("h").store(&bHelp) .description("Print GROMACS-specific unit test options")); options.addOption(BooleanOption("help").store(&bHelp).hidden()); options.addOption(BooleanOption("?").store(&bHelp).hidden()); // TODO: Make this into a FileNameOption (or a DirectoryNameOption). options.addOption(StringOption("src-root").store(&sourceRoot) .description("Override source tree location (for data files)")); // The potential MPI test event listener must be initialized first, // because it should appear in the start of the event listener list, // before other event listeners that may generate test failures // (currently, such an event listener is used by the reference data // framework). if (usesMpi) { initMPIOutput(); } // TODO: Consider removing this option from test binaries that do not need it. initReferenceData(&options); initTestOptions(&options); try { CommandLineParser(&options).parse(argc, *argv); options.finish(); } catch (const UserInputError &) { printHelp(options); throw; } if (bHelp) { printHelp(options); } if (!sourceRoot.empty()) { g_testContext->overrideSourceRoot(sourceRoot); TestFileManager::setInputDataDirectory( Path::join(sourceRoot, dataPath)); } } catch (const std::exception &ex) { printFatalErrorMessage(stderr, ex); int retcode = processExceptionAtExitForCommandLine(ex); // TODO: It could be nice to destroy things in proper order such that // g_testContext would not contain hanging references at this point, // but in practice that should not matter. g_testContext.reset(); std::exit(retcode); } }
int SimulationRunner::callMdrun(const CommandLine &callerRef) { /* Conforming to style guide by not passing a non-const reference to this function. Passing a non-const reference might make it easier to write code that incorrectly re-uses callerRef after the call to this function. */ CommandLine caller(callerRef); caller.addOption("-s", tprFileName_); caller.addOption("-g", logFileName_); caller.addOption("-e", edrFileName_); caller.addOption("-o", fullPrecisionTrajectoryFileName_); caller.addOption("-x", reducedPrecisionTrajectoryFileName_); caller.addOption("-deffnm", fixture_->fileManager_.getTemporaryFilePath("state")); if (nsteps_ > -2) { caller.addOption("-nsteps", nsteps_); } #if GMX_MPI # if GMX_GPU != GMX_GPU_NONE # if GMX_THREAD_MPI int numGpusNeeded = g_numThreads; # else /* Must be real MPI */ int numGpusNeeded = gmx_node_num(); # endif std::string gpuIdString(numGpusNeeded, '0'); caller.addOption("-gpu_id", gpuIdString.c_str()); # endif #endif #if GMX_THREAD_MPI caller.addOption("-ntmpi", g_numThreads); #endif #if GMX_OPENMP caller.addOption("-ntomp", g_numOpenMPThreads); #endif #if GMX_GPU != GMX_GPU_NONE /* TODO Ideally, with real MPI, we could call * gmx_collect_hardware_mpi() here and find out how many nodes * mdrun will run on. For now, we assume that we're running on one * node regardless of the number of ranks, because that's true in * Jenkins and for most developers running the tests. */ int numberOfNodes = 1; #if GMX_THREAD_MPI /* Can't use gmx_node_num() because it is only valid after spawn of thread-MPI threads */ int numberOfRanks = g_numThreads; #elif GMX_LIB_MPI int numberOfRanks = gmx_node_num(); #else int numberOfRanks = 1; #endif if (numberOfRanks > numberOfNodes && !gmx_multiple_gpu_per_node_supported()) { if (gmx_node_rank() == 0) { fprintf(stderr, "GROMACS in this build configuration cannot run on more than one GPU per node,\n so with %d ranks and %d nodes, this test will disable GPU support", numberOfRanks, numberOfNodes); } caller.addOption("-nb", "cpu"); } #endif return gmx_mdrun(caller.argc(), caller.argv()); }
int CommandLineModuleManager::run(int argc, char *argv[]) { CommandLineModuleInterface *module; const bool bMaster = (gmx_node_rank() == 0); bool bQuiet = impl_->bQuiet_ || !bMaster; CommandLineCommonOptionsHolder optionsHolder; try { optionsHolder.initOptions(); module = impl_->processCommonOptions(&optionsHolder, &argc, &argv); } catch (const std::exception &) { bQuiet |= optionsHolder.shouldBeQuiet(); if (!bQuiet) { printBinaryInformation(stderr, impl_->programContext_, optionsHolder.binaryInfoSettings()); } throw; } bQuiet |= optionsHolder.shouldBeQuiet(); if (!bQuiet) { FILE *out = optionsHolder.startupInfoFile(); printBinaryInformation(out, impl_->programContext_, optionsHolder.binaryInfoSettings()); fprintf(out, "\n"); } if (module == NULL) { return 0; } CommandLineModuleSettings settings; module->init(&settings); optionsHolder.adjustFromSettings(settings); gmx_set_max_backup_count(optionsHolder.shouldBackup() ? -1 : 0); // Open the debug file. if (optionsHolder.debugLevel() > 0) { std::string filename(impl_->programContext_.programName()); if (gmx_node_num() > 1) { filename.append(formatString("%d", gmx_node_rank())); } filename.append(".debug"); fprintf(stderr, "Will write debug log file: %s\n", filename.c_str()); gmx_init_debug(optionsHolder.debugLevel(), filename.c_str()); } // Set the nice level unless disabled in the configuration. if (optionsHolder.niceLevel() != 0) { static bool bNiceSet = false; // Only set it once. if (!bNiceSet) { // TODO: Diagnostic if this fails and the user explicitly requested it. gmx_set_nice(optionsHolder.niceLevel()); bNiceSet = true; } } if (optionsHolder.enableFPExceptions()) { //TODO: currently it is always enabled for mdrun (verlet) and tests. gmx_feenableexcept(); } int rc = 0; if (!(module == impl_->helpModule_ && !bMaster)) { rc = module->run(argc, argv); } if (!bQuiet) { gmx_thanx(stderr); } return rc; }
void parse_common_args(int *argc,char *argv[],unsigned long Flags, int nfile,t_filenm fnm[],int npargs,t_pargs *pa, int ndesc,char **desc,int nbugs,char **bugs) { static bool bHelp=FALSE,bHidden=FALSE,bQuiet=FALSE; static char *manstr[] = { NULL, "no", "html", "tex", "nroff", "ascii", "completion", NULL }; static char *not_nicestr[] = { NULL, "0", "4", "10", "19", NULL }; static char *nicestr[] = { NULL, "19", "10", "4", "0", NULL }; static char *not_npristr[] = { NULL, "0", "128", "100", "200", "250", NULL }; static char *npristr[] = { NULL, "128", "250", "200", "100", "0", NULL }; static int nicelevel=0,mantp=0,npri=0; static bool bGUI=FALSE,bDebug=FALSE; static char *deffnm=NULL; FILE *fp; bool bPrint,bExit; int i,j,k,npall; char *ptr,*newdesc; char *envstr; t_pargs *all_pa=NULL; t_pargs motif_pa = { "-X", FALSE, etBOOL, {&bGUI}, "Use dialog box GUI to edit command line options" }; t_pargs npri_paX = { "-npri", FALSE, etENUM, {not_npristr}, "Set non blocking priority" }; t_pargs npri_pa = { "-npri", FALSE, etINT, {&npri}, "HIDDEN Set non blocking priority (try 128)" }; t_pargs nice_paX = { "-nice", FALSE, etENUM, {not_nicestr}, "Set the nicelevel" }; t_pargs nice_pa = { "-nice", FALSE, etINT, {&nicelevel}, "Set the nicelevel" }; t_pargs deffnm_pa = { "-deffnm", FALSE, etSTR, {&deffnm}, "Set the default filename for all file options" }; t_pargs begin_pa = { "-b", FALSE, etTIME, {&tbegin}, "First frame (%t) to read from trajectory" }; t_pargs end_pa = { "-e", FALSE, etTIME, {&tend}, "Last frame (%t) to read from trajectory" }; t_pargs dt_pa = { "-dt", FALSE, etTIME, {&tdelta}, "Only use frame when t MOD dt = first time (%t)" }; t_pargs view_pa = { "-w", FALSE, etBOOL, {&bView}, "View output xvg, xpm, eps and pdb files" }; t_pargs time_pa = { "-tu", FALSE, etENUM, {timestr}, "Time unit" }; t_pargs pca_pa[] = { { "-h", FALSE, etBOOL, {&bHelp}, "Print help info and quit" }, { "-hidden", FALSE, etBOOL, {&bHidden}, "HIDDENPrint hidden options" }, { "-quiet",FALSE, etBOOL, {&bQuiet}, "HIDDENDo not print help info" }, { "-man", FALSE, etENUM, {manstr}, "HIDDENWrite manual and quit" }, { "-debug",FALSE, etBOOL, {&bDebug}, "HIDDENWrite file with debug information" }, }; #define NPCA_PA asize(pca_pa) debug_gmx(); if (debug) { fprintf(debug,"PID=%d, argc = %d\n",gmx_node_id(),*argc); for(i=0; (i<*argc); i++) fprintf(debug,"PID=%d, argv[%d] = %s\n",gmx_node_id(),i,argv[i]); } /* Check for double arguments */ for (i=1; (i<*argc); i++) { if (argv[i] && (strlen(argv[i]) > 1) && (!isdigit(argv[i][1]))) { for (j=i+1; (j<*argc); j++) { if ( (argv[i][0]=='-') && (argv[j][0]=='-') && (strcmp(argv[i],argv[j])==0) ) { if (FF(PCA_NOEXIT_ON_ARGS)) fprintf(stderr,"Double command line argument %s\n",argv[i]); else fatal_error(0,"Double command line argument %s\n",argv[i]); } } } } debug_gmx(); /* Handle the flags argument, which is a bit field * The FF macro returns whether or not the bit is set */ uFlags = Flags; bPrint = !FF(PCA_SILENT); /* Check whether we should have GUI or not */ #ifdef HAVE_MOTIF bGUI = (getenv("GMXMOTIF") != NULL); for(i=1; (i<*argc); i++) { if (strcmp(argv[i],"-X") == 0) bGUI = TRUE; else if (strcmp(argv[i],"-noX") == 0) bGUI = FALSE; } if (bGUI) bQuiet = TRUE; #else bGUI = FALSE; #endif set_program_name(argv[0]); /* Check ALL the flags ... */ snew(all_pa,NPCA_PA+npargs); for(i=npall=0; (i<NPCA_PA); i++) npall = add_parg(npall,&(all_pa),&(pca_pa[i])); /* Motif options */ npall = add_parg(npall,&(all_pa),&motif_pa); #if (defined __sgi && !defined SPEC_CPU) envstr = getenv("GMXNPRIALL"); if (envstr) npri=atoi(envstr); if (FF(PCA_BE_NICE)) { envstr = getenv("GMXNPRI"); if (envstr) npri=atoi(envstr); } if (bGUI) { if (npri) npri_paX.u.c = npristr; npall = add_parg(npall,&(all_pa),&npri_paX); } else npall = add_parg(npall,&(all_pa),&npri_pa); #endif if (bGUI) { /* Automatic nice or scheduling options */ if (FF(PCA_BE_NICE)) nice_paX.u.c = nicestr; npall = add_parg(npall,&(all_pa),&nice_paX); } else { if (FF(PCA_BE_NICE)) nicelevel=19; npall = add_parg(npall,&(all_pa),&nice_pa); } if (FF(PCA_CAN_SET_DEFFNM)) npall = add_parg(npall,&(all_pa),&deffnm_pa); if (FF(PCA_CAN_BEGIN)) npall = add_parg(npall,&(all_pa),&begin_pa); if (FF(PCA_CAN_END)) npall = add_parg(npall,&(all_pa),&end_pa); if (FF(PCA_CAN_DT)) npall = add_parg(npall,&(all_pa),&dt_pa); #ifndef SPEC_CPU if (FF(PCA_TIME_UNIT)) { envstr = getenv("GMXTIMEUNIT"); if ( envstr == NULL ) envstr="ps"; set_default_time_unit(envstr); npall = add_parg(npall,&(all_pa),&time_pa); } else #endif set_default_time_unit("ps"); if (FF(PCA_CAN_VIEW)) npall = add_parg(npall,&(all_pa),&view_pa); /* Now append the program specific arguments */ for(i=0; (i<npargs); i++) npall = add_parg(npall,&(all_pa),&(pa[i])); /* set etENUM options to default */ for(i=0; (i<npall); i++) if (all_pa[i].type==etENUM) all_pa[i].u.c[0]=all_pa[i].u.c[1]; /* Now parse all the command-line options */ get_pargs(argc,argv,npall,all_pa,FF(PCA_KEEP_ARGS)); if (FF(PCA_CAN_SET_DEFFNM) && (deffnm!=NULL)) set_default_file_name(deffnm); /* Parse the file args */ parse_file_args(argc,argv,nfile,fnm,FF(PCA_KEEP_ARGS)); /* Open the debug file */ if (bDebug) { char buf[256]; if (gmx_node_num() > 1) sprintf(buf,"%s%d.log",ShortProgram(),gmx_node_id()); else sprintf(buf,"%s.log",ShortProgram()); init_debug(buf); fprintf(debug,"%s (this file) opened in file %s, line %d\n", buf,__FILE__,__LINE__); } /* Now we have parsed the command line arguments. If the user wants it * we can now plop up a GUI dialog box to edit options. */ if (bGUI) { #ifdef HAVE_MOTIF gmx_gui(argc,argv,nfile,fnm,npall,all_pa,ndesc,desc,nbugs,bugs); #else fatal_error(0,"GROMACS compiled without MOTIF support - can't use X interface"); #endif } /* Now copy the results back... */ for(i=0,k=npall-npargs; (i<npargs); i++,k++) memcpy(&(pa[i]),&(all_pa[k]),(size_t)sizeof(pa[i])); for(i=0; (i<npall); i++) all_pa[i].desc = mk_desc(&(all_pa[i]), time_unit() ); bExit = bHelp || (strcmp(manstr[0],"no") != 0); #if (defined __sgi && USE_SGI_FPE) doexceptions(); #endif /* Set the nice level */ #ifdef __sgi if (bGUI) if (npri) sscanf(npristr[0],"%d",&npri); else sscanf(not_npristr[0],"%d",&npri); if (npri != 0 && !bExit) { (void) schedctl(MPTS_RTPRI,0,npri); } else #endif #ifdef HAVE_UNISTD_H if (bGUI) { if (FF(PCA_BE_NICE)) sscanf(nicestr[0],"%d",&nicelevel); else sscanf(not_nicestr[0],"%d",&nicelevel); } if (nicelevel != 0 && !bExit) nice(nicelevel); #endif if (!(FF(PCA_QUIET) || bQuiet )) { if (bHelp) write_man(stderr,"help",program,ndesc,desc,nfile,fnm,npall,all_pa, nbugs,bugs,bHidden); else if (bPrint) { pr_fns(stderr,nfile,fnm); print_pargs(stderr,npall,all_pa); } } if (strcmp(manstr[0],"no") != 0) { if(!strcmp(manstr[0],"completion")) { /* one file each for csh, bash and zsh if we do completions */ fp=man_file(program,"completion-zsh"); write_man(fp,"completion-zsh",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); fclose(fp); fp=man_file(program,"completion-bash"); write_man(fp,"completion-bash",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); fclose(fp); fp=man_file(program,"completion-csh"); write_man(fp,"completion-csh",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); fclose(fp); } else { fp=man_file(program,manstr[0]); write_man(fp,manstr[0],program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); fclose(fp); } } /* convert time options, must be done after printing! */ init_time_factor(); for(i=0; i<npall; i++) { if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0)) { *all_pa[i].u.r /= timefactor; } } /* clear memory */ for(i=0; i<npall; i++) sfree(all_pa[i].desc); sfree(all_pa); if (!FF(PCA_NOEXIT_ON_ARGS)) { if (*argc > 1) { for(i=1; (i<*argc); i++) fprintf(stderr,"Unknown argument: %s\n",argv[i]); fatal_error(0,"Program %s halted",Program()); } } if (bExit) { #ifdef USE_MPI if (gmx_parallel) gmx_abort(gmx_node_id(),gmx_node_num(),0); #endif exit(0); } }
void parse_common_args(int *argc,char *argv[],unsigned long Flags, int nfile,t_filenm fnm[],int npargs,t_pargs *pa, int ndesc,char **desc,int nbugs,char **bugs) { static bool bHelp=FALSE,bHidden=FALSE,bQuiet=FALSE; static char *manstr[] = { NULL, "no", "html", "tex", "nroff", "ascii", "completion", "py", "xml", "wiki", NULL }; static int nicelevel=0,mantp=0,npri=0,debug_level=0; static char *deffnm=NULL; static real tbegin=0,tend=0,tdelta=0; t_pargs *all_pa=NULL; t_pargs npri_pa = { "-npri", FALSE, etINT, {&npri}, "HIDDEN Set non blocking priority (try 128)" }; t_pargs nice_pa = { "-nice", FALSE, etINT, {&nicelevel}, "Set the nicelevel" }; t_pargs deffnm_pa = { "-deffnm", FALSE, etSTR, {&deffnm}, "Set the default filename for all file options" }; t_pargs begin_pa = { "-b", FALSE, etTIME, {&tbegin}, "First frame (%t) to read from trajectory" }; t_pargs end_pa = { "-e", FALSE, etTIME, {&tend}, "Last frame (%t) to read from trajectory" }; t_pargs dt_pa = { "-dt", FALSE, etTIME, {&tdelta}, "Only use frame when t MOD dt = first time (%t)" }; t_pargs view_pa = { "-w", FALSE, etBOOL, {&bView}, "View output xvg, xpm, eps and pdb files" }; t_pargs code_pa = { "-xvgr", FALSE, etBOOL, {&bXvgrCodes}, "Add specific codes (legends etc.) in the output xvg files for the xmgrace program" }; t_pargs time_pa = { "-tu", FALSE, etENUM, {timestr}, "Time unit" }; /* Maximum number of extra arguments */ #define EXTRA_PA 16 t_pargs pca_pa[] = { { "-h", FALSE, etBOOL, {&bHelp}, "Print help info and quit" }, { "-hidden", FALSE, etBOOL, {&bHidden}, "HIDDENPrint hidden options" }, { "-quiet",FALSE, etBOOL, {&bQuiet}, "HIDDENDo not print help info" }, { "-man", FALSE, etENUM, {manstr}, "HIDDENWrite manual and quit" }, { "-debug",FALSE, etINT, {&debug_level}, "HIDDENWrite file with debug information, 1: short, 2: also x and f" }, }; #define NPCA_PA asize(pca_pa) FILE *fp; bool bPrint,bExit,bXvgr; int i,j,k,npall,max_pa,cmdlength; char *ptr,*newdesc; char *envstr; #define FF(arg) ((Flags & arg)==arg) cmdlength = strlen(argv[0]); /* Check for double arguments */ for (i=1; (i<*argc); i++) { cmdlength += strlen(argv[i]); if (argv[i] && (strlen(argv[i]) > 1) && (!isdigit(argv[i][1]))) { for (j=i+1; (j<*argc); j++) { if ( (argv[i][0]=='-') && (argv[j][0]=='-') && (strcmp(argv[i],argv[j])==0) ) { if (FF(PCA_NOEXIT_ON_ARGS)) fprintf(stderr,"Double command line argument %s\n",argv[i]); else gmx_fatal(FARGS,"Double command line argument %s\n",argv[i]); } } } } debug_gmx(); /* Fill the cmdline string */ snew(cmdline,cmdlength+*argc+1); for (i=0; (i<*argc); i++) { strcat(cmdline,argv[i]); strcat(cmdline," "); } /* Handle the flags argument, which is a bit field * The FF macro returns whether or not the bit is set */ bPrint = !FF(PCA_SILENT); set_program_name(argv[0]); /* Check ALL the flags ... */ max_pa = NPCA_PA + EXTRA_PA + npargs; snew(all_pa,max_pa); for(i=npall=0; (i<NPCA_PA); i++) npall = add_parg(npall,all_pa,&(pca_pa[i])); #ifdef __sgi envstr = getenv("GMXNPRIALL"); if (envstr) npri=atoi(envstr); if (FF(PCA_BE_NICE)) { envstr = getenv("GMXNPRI"); if (envstr) npri=atoi(envstr); } npall = add_parg(npall,all_pa,&npri_pa); #endif if (FF(PCA_BE_NICE)) nicelevel=19; npall = add_parg(npall,all_pa,&nice_pa); if (FF(PCA_CAN_SET_DEFFNM)) npall = add_parg(npall,all_pa,&deffnm_pa); if (FF(PCA_CAN_BEGIN)) npall = add_parg(npall,all_pa,&begin_pa); if (FF(PCA_CAN_END)) npall = add_parg(npall,all_pa,&end_pa); if (FF(PCA_CAN_DT)) npall = add_parg(npall,all_pa,&dt_pa); if (FF(PCA_TIME_UNIT)) { envstr = getenv("GMXTIMEUNIT"); if ( envstr == NULL ) envstr="ps"; set_default_time_unit(envstr); npall = add_parg(npall,all_pa,&time_pa); } else set_default_time_unit("ps"); if (FF(PCA_CAN_VIEW)) npall = add_parg(npall,all_pa,&view_pa); bXvgr = FALSE; for(i=0; (i<nfile); i++) bXvgr = bXvgr || (fnm[i].ftp == efXVG); if (bXvgr) npall = add_parg(npall,all_pa,&code_pa); /* Now append the program specific arguments */ for(i=0; (i<npargs); i++) npall = add_parg(npall,all_pa,&(pa[i])); /* set etENUM options to default */ for(i=0; (i<npall); i++) if (all_pa[i].type==etENUM) all_pa[i].u.c[0]=all_pa[i].u.c[1]; /* Now parse all the command-line options */ get_pargs(argc,argv,npall,all_pa,FF(PCA_KEEP_ARGS)); if (FF(PCA_CAN_SET_DEFFNM) && (deffnm!=NULL)) set_default_file_name(deffnm); /* Parse the file args */ parse_file_args(argc,argv,nfile,fnm,FF(PCA_KEEP_ARGS)); /* Open the debug file */ if (debug_level > 0) { char buf[256]; if (gmx_mpi_initialized()) sprintf(buf,"%s%d.log",ShortProgram(),gmx_node_rank()); else sprintf(buf,"%s.log",ShortProgram()); init_debug(debug_level,buf); fprintf(stderr,"Opening debug file %s (src code file %s, line %d)\n", buf,__FILE__,__LINE__); } /* Now copy the results back... */ for(i=0,k=npall-npargs; (i<npargs); i++,k++) memcpy(&(pa[i]),&(all_pa[k]),(size_t)sizeof(pa[i])); for(i=0; (i<npall); i++) all_pa[i].desc = mk_desc(&(all_pa[i]), time_unit() ); bExit = bHelp || (strcmp(manstr[0],"no") != 0); #if (defined __sgi && USE_SGI_FPE) doexceptions(); #endif /* Set the nice level */ #ifdef __sgi if (npri != 0 && !bExit) { schedctl(MPTS_RTPRI,0,npri); } #endif #ifdef HAVE_UNISTD_H #ifndef GMX_NO_NICE /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */ if (nicelevel != 0 && !bExit) i=nice(nicelevel); /* assign ret value to avoid warnings */ #endif #endif if (!(FF(PCA_QUIET) || bQuiet )) { if (bHelp) write_man(stderr,"help",program,ndesc,desc,nfile,fnm,npall,all_pa, nbugs,bugs,bHidden); else if (bPrint) { pr_fns(stderr,nfile,fnm); print_pargs(stderr,npall,all_pa,FALSE); } } if (strcmp(manstr[0],"no") != 0) { if(!strcmp(manstr[0],"completion")) { /* one file each for csh, bash and zsh if we do completions */ fp=man_file(program,"completion-zsh"); write_man(fp,"completion-zsh",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); fp=man_file(program,"completion-bash"); write_man(fp,"completion-bash",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); fp=man_file(program,"completion-csh"); write_man(fp,"completion-csh",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); } else { fp=man_file(program,manstr[0]); write_man(fp,manstr[0],program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); } } /* convert time options, must be done after printing! */ init_time_factor(); for(i=0; i<npall; i++) { if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0)) { *all_pa[i].u.r *= timeinvfac; } } /* Extract Time info from arguments */ if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b",npall,all_pa)) setTimeValue(TBEGIN,opt2parg_real("-b",npall,all_pa)); if (FF(PCA_CAN_END) && opt2parg_bSet("-e",npall,all_pa)) setTimeValue(TEND,opt2parg_real("-e",npall,all_pa)); if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt",npall,all_pa)) setTimeValue(TDELTA,opt2parg_real("-dt",npall,all_pa)); /* clear memory */ sfree(all_pa); if (!FF(PCA_NOEXIT_ON_ARGS)) { if (*argc > 1) { gmx_cmd(argv[1]); } } if (bExit) { if (gmx_parallel_env) gmx_abort(gmx_node_rank(),gmx_node_num(),0); else exit(0); } #undef FF }