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
);