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
43 #include "gromacs/fileio/futil.h"
48 #include "gromacs/fileio/gmxfio.h"
51 #include "gmx_fatal.h"
53 /* find an entry; return index, or -1 if not found */
54 static int search_einp(int ninp, const t_inpfile *inp, const char *name);
57 t_inpfile *read_inpfile(const char *fn, int *ninp,
61 char buf[STRLEN], lbuf[STRLEN], rbuf[STRLEN], warn_buf[STRLEN];
63 t_inpfile *inp = NULL;
65 /* setting cppopts from command-line options would be cooler */
66 gmx_bool allow_override = FALSE;
71 fprintf(debug, "Reading MDP file %s\n", fn);
79 ptr = fgets2(buf, STRLEN-1, in);
81 set_warning_line(wi, fn, lc);
85 if ((cptr = strchr(buf, COMMENTSIGN)) != NULL)
92 for (j = 0; (buf[j] != '=') && (buf[j] != '\0'); j++)
102 fprintf(debug, "No = on line %d in file %s, ignored\n", lc, fn);
108 for (i = 0; (i < j); i++)
118 fprintf(debug, "Empty left hand side on line %d in file %s, ignored\n", lc, fn);
123 for (i = j+1, k = 0; (buf[i] != '\0'); i++, k++)
133 fprintf(debug, "Empty right hand side on line %d in file %s, ignored\n", lc, fn);
138 /* Now finally something sensible */
141 /* first check whether we hit the 'multiple_entries' option */
142 if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptName], lbuf) == 0)
144 /* we now check whether to allow overrides from here or not */
145 if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptNo], rbuf) == 0)
147 allow_override = FALSE;
149 else if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptLast], rbuf) == 0)
151 allow_override = TRUE;
156 "Parameter \"%s\" should either be %s or %s\n",
158 eMultentOpt_names[eMultentOptNo],
159 eMultentOpt_names[eMultentOptLast]);
160 warning_error(wi, warn_buf);
165 /* it is a regular option; check for duplicates */
166 found_index = search_einp(nin, inp, lbuf);
168 if (found_index == -1)
172 inp[nin-1].inp_count = 1;
173 inp[nin-1].count = 0;
174 inp[nin-1].bObsolete = FALSE;
175 inp[nin-1].bSet = FALSE;
176 inp[nin-1].name = strdup(lbuf);
177 inp[nin-1].value = strdup(rbuf);
184 "Parameter \"%s\" doubly defined (and multiple assignments not allowed)\n",
186 warning_error(wi, warn_buf);
191 sfree(inp[found_index].value);
192 inp[found_index].value = strdup(rbuf);
194 "Overriding existing parameter \"%s\" with value \"%s\"\n",
196 warning_note(wi, warn_buf);
211 fprintf(debug, "Done reading MDP file, there were %d entries in there\n",
223 static int inp_comp(const void *a, const void *b)
225 return ((t_inpfile *)a)->count - ((t_inpfile *)b)->count;
228 static void sort_inp(int ninp, t_inpfile inp[])
233 for (i = 0; (i < ninp); i++)
235 mm = max(mm, inp[i].count);
237 for (i = 0; (i < ninp); i++)
239 if (inp[i].count == 0)
244 qsort(inp, ninp, (size_t)sizeof(inp[0]), inp_comp);
247 void write_inpfile(const char *fn, int ninp, t_inpfile inp[], gmx_bool bHaltOnUnknown,
252 char warn_buf[STRLEN];
255 out = gmx_fio_fopen(fn, "w");
256 nice_header(out, fn);
257 for (i = 0; (i < ninp); i++)
261 if (inp[i].name[0] == ';' || (strlen(inp[i].name) > 2 && inp[i].name[1] == ';'))
263 fprintf(out, "%-24s\n", inp[i].name);
267 fprintf(out, "%-24s = %s\n", inp[i].name, inp[i].value ? inp[i].value : "");
270 else if (!inp[i].bObsolete)
272 sprintf(warn_buf, "Unknown left-hand '%s' in parameter file\n",
276 warning_error(wi, warn_buf);
280 warning(wi, warn_buf);
286 check_warning_error(wi, FARGS);
289 void replace_inp_entry(int ninp, t_inpfile *inp, const char *old_entry, const char *new_entry)
293 for (i = 0; (i < ninp); i++)
295 if (gmx_strcasecmp_min(old_entry, inp[i].name) == 0)
299 fprintf(stderr, "Replacing old mdp entry '%s' by '%s'\n",
300 inp[i].name, new_entry);
302 inp[i].name = strdup(new_entry);
306 fprintf(stderr, "Ignoring obsolete mdp entry '%s'\n",
308 inp[i].bObsolete = TRUE;
314 static int search_einp(int ninp, const t_inpfile *inp, const char *name)
322 for (i = 0; i < ninp; i++)
324 if (gmx_strcasecmp_min(name, inp[i].name) == 0)
332 static int get_einp(int *ninp, t_inpfile **inp, const char *name)
335 int notfound = FALSE;
336 char warn_buf[STRLEN];
340 for(i=0; (i<(*ninp)); i++)
341 if (gmx_strcasecmp_min(name,(*inp)[i].name) == 0)
343 if (i == (*ninp)) {*/
344 i = search_einp(*ninp, *inp, name);
349 srenew(*inp, (*ninp));
350 (*inp)[i].name = strdup(name);
351 (*inp)[i].bSet = TRUE;
353 (*inp)[i].count = (*inp)[0].inp_count++;
354 (*inp)[i].bSet = TRUE;
357 fprintf(debug, "Inp %d = %s\n", (*inp)[i].count, (*inp)[i].name);
360 /*if (i == (*ninp)-1)*/
371 int get_eint(int *ninp, t_inpfile **inp, const char *name, int def,
374 char buf[32], *ptr, warn_buf[STRLEN];
378 ii = get_einp(ninp, inp, name);
382 sprintf(buf, "%d", def);
383 (*inp)[(*ninp)-1].value = strdup(buf);
389 ret = strtol((*inp)[ii].value, &ptr, 10);
390 if (ptr == (*inp)[ii].value)
392 sprintf(warn_buf, "Right hand side '%s' for parameter '%s' in parameter file is not an integer value\n", (*inp)[ii].value, (*inp)[ii].name);
393 warning_error(wi, warn_buf);
400 gmx_large_int_t get_egmx_large_int(int *ninp, t_inpfile **inp,
401 const char *name, gmx_large_int_t def,
404 char buf[32], *ptr, warn_buf[STRLEN];
408 ii = get_einp(ninp, inp, name);
412 sprintf(buf, gmx_large_int_pfmt, def);
413 (*inp)[(*ninp)-1].value = strdup(buf);
419 ret = str_to_large_int_t((*inp)[ii].value, &ptr);
420 if (ptr == (*inp)[ii].value)
422 sprintf(warn_buf, "Right hand side '%s' for parameter '%s' in parameter file is not an integer value\n", (*inp)[ii].value, (*inp)[ii].name);
423 warning_error(wi, warn_buf);
430 double get_ereal(int *ninp, t_inpfile **inp, const char *name, double def,
433 char buf[32], *ptr, warn_buf[STRLEN];
437 ii = get_einp(ninp, inp, name);
441 sprintf(buf, "%g", def);
442 (*inp)[(*ninp)-1].value = strdup(buf);
448 ret = strtod((*inp)[ii].value, &ptr);
449 if (ptr == (*inp)[ii].value)
451 sprintf(warn_buf, "Right hand side '%s' for parameter '%s' in parameter file is not a real value\n", (*inp)[ii].value, (*inp)[ii].name);
452 warning_error(wi, warn_buf);
459 const char *get_estr(int *ninp, t_inpfile **inp, const char *name, const char *def)
464 ii = get_einp(ninp, inp, name);
470 sprintf(buf, "%s", def);
471 (*inp)[(*ninp)-1].value = strdup(buf);
475 (*inp)[(*ninp)-1].value = NULL;
482 return (*inp)[ii].value;
486 int get_eeenum(int *ninp, t_inpfile **inp, const char *name, const char **defs,
493 ii = get_einp(ninp, inp, name);
497 (*inp)[(*ninp)-1].value = strdup(defs[0]);
502 for (i = 0; (defs[i] != NULL); i++)
504 if (gmx_strcasecmp_min(defs[i], (*inp)[ii].value) == 0)
512 n += sprintf(buf, "Invalid enum '%s' for variable %s, using '%s'\n",
513 (*inp)[ii].value, name, defs[0]);
514 n += sprintf(buf+n, "Next time use one of:");
518 n += sprintf(buf+n, " '%s'", defs[j]);
523 warning_error(wi, buf);
527 fprintf(stderr, "%s\n", buf);
530 (*inp)[ii].value = strdup(defs[0]);
538 int get_eenum(int *ninp, t_inpfile **inp, const char *name, const char **defs)
542 return get_eeenum(ninp, inp, name, defs, NULL);