2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
54 #include "gmx_fatal.h"
56 /* find an entry; return index, or -1 if not found */
57 static int search_einp(int ninp, const t_inpfile *inp, const char *name);
60 t_inpfile *read_inpfile(const char *fn,int *ninp,
65 char buf[STRLEN],lbuf[STRLEN],rbuf[STRLEN],warn_buf[STRLEN];
69 /* setting cppopts from command-line options would be cooler */
70 gmx_bool allow_override=FALSE;
74 fprintf(debug,"Reading MDP file %s\n",fn);
80 ptr = fgets2(buf,STRLEN-1,in);
82 set_warning_line(wi,fn,lc);
85 if ((cptr=strchr(buf,COMMENTSIGN)) != NULL)
90 for(j=0; (buf[j] != '=') && (buf[j] != '\0'); j++)
95 fprintf(debug,"No = on line %d in file %s, ignored\n",lc,fn);
103 if (lbuf[0] == '\0') {
105 fprintf(debug,"Empty left hand side on line %d in file %s, ignored\n",lc,fn);
108 for(i=j+1,k=0; (buf[i] != '\0'); i++,k++)
112 if (rbuf[0] == '\0') {
114 fprintf(debug,"Empty right hand side on line %d in file %s, ignored\n",lc,fn);
117 /* Now finally something sensible */
120 /* first check whether we hit the 'multiple_entries' option */
121 if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptName], lbuf)==0)
123 /* we now check whether to allow overrides from here or not */
124 if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptNo], rbuf)==0)
126 allow_override=FALSE;
128 else if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptLast], rbuf)==0)
135 "Parameter \"%s\" should either be %s or %s\n",
137 eMultentOpt_names[eMultentOptNo],
138 eMultentOpt_names[eMultentOptLast]);
139 warning_error(wi,warn_buf);
144 /* it is a regular option; check for duplicates */
145 found_index=search_einp(nin, inp, lbuf);
147 if (found_index == -1)
151 inp[nin-1].inp_count = 1;
152 inp[nin-1].count = 0;
153 inp[nin-1].bObsolete = FALSE;
154 inp[nin-1].bSet = FALSE;
155 inp[nin-1].name = strdup(lbuf);
156 inp[nin-1].value = strdup(rbuf);
163 "Parameter \"%s\" doubly defined (and multiple assignments not allowed)\n",
165 warning_error(wi,warn_buf);
170 sfree(inp[found_index].value);
171 inp[found_index].value = strdup(rbuf);
173 "Overriding existing parameter \"%s\" with value \"%s\"\n",
175 warning_note(wi,warn_buf);
188 fprintf(debug,"Done reading MDP file, there were %d entries in there\n",
200 static int inp_comp(const void *a,const void *b)
202 return ((t_inpfile *)a)->count - ((t_inpfile *)b)->count;
205 static void sort_inp(int ninp,t_inpfile inp[])
210 for(i=0; (i<ninp); i++)
211 mm=max(mm,inp[i].count);
212 for(i=0; (i<ninp); i++) {
213 if (inp[i].count == 0)
216 qsort(inp,ninp,(size_t)sizeof(inp[0]),inp_comp);
219 void write_inpfile(const char *fn,int ninp,t_inpfile inp[],gmx_bool bHaltOnUnknown,
224 char warn_buf[STRLEN];
227 out=gmx_fio_fopen(fn,"w");
229 for(i=0; (i<ninp); i++) {
231 if(inp[i].name[0]==';' || (strlen(inp[i].name)>2 && inp[i].name[1]==';'))
232 fprintf(out,"%-24s\n",inp[i].name);
234 fprintf(out,"%-24s = %s\n",inp[i].name,inp[i].value ? inp[i].value : "");
235 } else if (!inp[i].bObsolete) {
236 sprintf(warn_buf,"Unknown left-hand '%s' in parameter file\n",
238 if (bHaltOnUnknown) {
239 warning_error(wi,warn_buf);
241 warning(wi,warn_buf);
247 check_warning_error(wi,FARGS);
250 void replace_inp_entry(int ninp,t_inpfile *inp,const char *old_entry,const char *new_entry)
254 for(i=0; (i<ninp); i++) {
255 if (gmx_strcasecmp_min(old_entry,inp[i].name) == 0) {
257 fprintf(stderr,"Replacing old mdp entry '%s' by '%s'\n",
258 inp[i].name,new_entry);
260 inp[i].name = strdup(new_entry);
262 fprintf(stderr,"Ignoring obsolete mdp entry '%s'\n",
264 inp[i].bObsolete = TRUE;
270 static int search_einp(int ninp, const t_inpfile *inp, const char *name)
276 for(i=0; i<ninp; i++)
277 if (gmx_strcasecmp_min(name,inp[i].name) == 0)
282 static int get_einp(int *ninp,t_inpfile **inp,const char *name)
286 char warn_buf[STRLEN];
290 for(i=0; (i<(*ninp)); i++)
291 if (gmx_strcasecmp_min(name,(*inp)[i].name) == 0)
293 if (i == (*ninp)) {*/
294 i=search_einp(*ninp, *inp, name);
299 srenew(*inp,(*ninp));
300 (*inp)[i].name=strdup(name);
303 (*inp)[i].count = (*inp)[0].inp_count++;
304 (*inp)[i].bSet = TRUE;
306 fprintf(debug,"Inp %d = %s\n",(*inp)[i].count,(*inp)[i].name);
308 /*if (i == (*ninp)-1)*/
315 int get_eint(int *ninp,t_inpfile **inp,const char *name,int def,
318 char buf[32],*ptr,warn_buf[STRLEN];
322 ii=get_einp(ninp,inp,name);
325 sprintf(buf,"%d",def);
326 (*inp)[(*ninp)-1].value=strdup(buf);
331 ret = strtol((*inp)[ii].value,&ptr,10);
332 if (ptr == (*inp)[ii].value) {
333 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);
334 warning_error(wi,warn_buf);
341 gmx_large_int_t get_egmx_large_int(int *ninp,t_inpfile **inp,
342 const char *name,gmx_large_int_t def,
345 char buf[32],*ptr,warn_buf[STRLEN];
349 ii=get_einp(ninp,inp,name);
352 sprintf(buf,gmx_large_int_pfmt,def);
353 (*inp)[(*ninp)-1].value=strdup(buf);
358 ret = str_to_large_int_t((*inp)[ii].value,&ptr);
359 if (ptr == (*inp)[ii].value) {
360 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);
361 warning_error(wi,warn_buf);
368 double get_ereal(int *ninp,t_inpfile **inp,const char *name,double def,
371 char buf[32],*ptr,warn_buf[STRLEN];
375 ii=get_einp(ninp,inp,name);
378 sprintf(buf,"%g",def);
379 (*inp)[(*ninp)-1].value=strdup(buf);
384 ret = strtod((*inp)[ii].value,&ptr);
385 if (ptr == (*inp)[ii].value) {
386 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);
387 warning_error(wi,warn_buf);
394 const char *get_estr(int *ninp,t_inpfile **inp,const char *name,const char *def)
399 ii=get_einp(ninp,inp,name);
403 sprintf(buf,"%s",def);
404 (*inp)[(*ninp)-1].value=strdup(buf);
407 (*inp)[(*ninp)-1].value=NULL;
412 return (*inp)[ii].value;
415 int get_eeenum(int *ninp,t_inpfile **inp,const char *name,const char **defs,
422 ii=get_einp(ninp,inp,name);
425 (*inp)[(*ninp)-1].value=strdup(defs[0]);
430 for(i=0; (defs[i] != NULL); i++)
431 if (gmx_strcasecmp_min(defs[i],(*inp)[ii].value) == 0)
434 if (defs[i] == NULL) {
435 n += sprintf(buf,"Invalid enum '%s' for variable %s, using '%s'\n",
436 (*inp)[ii].value,name,defs[0]);
437 n += sprintf(buf+n,"Next time use one of:");
440 n += sprintf(buf+n," '%s'",defs[j]);
444 warning_error(wi,buf);
446 fprintf(stderr,"%s\n",buf);
449 (*inp)[ii].value = strdup(defs[0]);
457 int get_eenum(int *ninp,t_inpfile **inp,const char *name,const char **defs)
461 return get_eeenum(ninp,inp,name,defs,NULL);