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
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,
62 char buf[STRLEN],lbuf[STRLEN],rbuf[STRLEN],warn_buf[STRLEN];
66 /* setting cppopts from command-line options would be cooler */
67 gmx_bool allow_override=FALSE;
71 fprintf(debug,"Reading MDP file %s\n",fn);
77 ptr = fgets2(buf,STRLEN-1,in);
79 set_warning_line(wi,fn,lc);
82 if ((cptr=strchr(buf,COMMENTSIGN)) != NULL)
87 for(j=0; (buf[j] != '=') && (buf[j] != '\0'); j++)
92 fprintf(debug,"No = on line %d in file %s, ignored\n",lc,fn);
100 if (lbuf[0] == '\0') {
102 fprintf(debug,"Empty left hand side on line %d in file %s, ignored\n",lc,fn);
105 for(i=j+1,k=0; (buf[i] != '\0'); i++,k++)
109 if (rbuf[0] == '\0') {
111 fprintf(debug,"Empty right hand side on line %d in file %s, ignored\n",lc,fn);
114 /* Now finally something sensible */
117 /* first check whether we hit the 'multiple_entries' option */
118 if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptName], lbuf)==0)
120 /* we now check whether to allow overrides from here or not */
121 if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptNo], rbuf)==0)
123 allow_override=FALSE;
125 else if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptLast], rbuf)==0)
132 "Parameter \"%s\" should either be %s or %s\n",
134 eMultentOpt_names[eMultentOptNo],
135 eMultentOpt_names[eMultentOptLast]);
136 warning_error(wi,warn_buf);
141 /* it is a regular option; check for duplicates */
142 found_index=search_einp(nin, inp, lbuf);
144 if (found_index == -1)
148 inp[nin-1].inp_count = 1;
149 inp[nin-1].count = 0;
150 inp[nin-1].bObsolete = FALSE;
151 inp[nin-1].bSet = FALSE;
152 inp[nin-1].name = strdup(lbuf);
153 inp[nin-1].value = strdup(rbuf);
160 "Parameter \"%s\" doubly defined (and multiple assignments not allowed)\n",
162 warning_error(wi,warn_buf);
167 sfree(inp[found_index].value);
168 inp[found_index].value = strdup(rbuf);
170 "Overriding existing parameter \"%s\" with value \"%s\"\n",
172 warning_note(wi,warn_buf);
185 fprintf(debug,"Done reading MDP file, there were %d entries in there\n",
197 static int inp_comp(const void *a,const void *b)
199 return ((t_inpfile *)a)->count - ((t_inpfile *)b)->count;
202 static void sort_inp(int ninp,t_inpfile inp[])
207 for(i=0; (i<ninp); i++)
208 mm=max(mm,inp[i].count);
209 for(i=0; (i<ninp); i++) {
210 if (inp[i].count == 0)
213 qsort(inp,ninp,(size_t)sizeof(inp[0]),inp_comp);
216 void write_inpfile(const char *fn,int ninp,t_inpfile inp[],gmx_bool bHaltOnUnknown,
221 char warn_buf[STRLEN];
224 out=gmx_fio_fopen(fn,"w");
226 for(i=0; (i<ninp); i++) {
228 if(inp[i].name[0]==';' || (strlen(inp[i].name)>2 && inp[i].name[1]==';'))
229 fprintf(out,"%-24s\n",inp[i].name);
231 fprintf(out,"%-24s = %s\n",inp[i].name,inp[i].value ? inp[i].value : "");
232 } else if (!inp[i].bObsolete) {
233 sprintf(warn_buf,"Unknown left-hand '%s' in parameter file\n",
235 if (bHaltOnUnknown) {
236 warning_error(wi,warn_buf);
238 warning(wi,warn_buf);
244 check_warning_error(wi,FARGS);
247 void replace_inp_entry(int ninp,t_inpfile *inp,const char *old_entry,const char *new_entry)
251 for(i=0; (i<ninp); i++) {
252 if (gmx_strcasecmp_min(old_entry,inp[i].name) == 0) {
254 fprintf(stderr,"Replacing old mdp entry '%s' by '%s'\n",
255 inp[i].name,new_entry);
257 inp[i].name = strdup(new_entry);
259 fprintf(stderr,"Ignoring obsolete mdp entry '%s'\n",
261 inp[i].bObsolete = TRUE;
267 static int search_einp(int ninp, const t_inpfile *inp, const char *name)
273 for(i=0; i<ninp; i++)
274 if (gmx_strcasecmp_min(name,inp[i].name) == 0)
279 static int get_einp(int *ninp,t_inpfile **inp,const char *name)
283 char warn_buf[STRLEN];
287 for(i=0; (i<(*ninp)); i++)
288 if (gmx_strcasecmp_min(name,(*inp)[i].name) == 0)
290 if (i == (*ninp)) {*/
291 i=search_einp(*ninp, *inp, name);
296 srenew(*inp,(*ninp));
297 (*inp)[i].name=strdup(name);
300 (*inp)[i].count = (*inp)[0].inp_count++;
301 (*inp)[i].bSet = TRUE;
303 fprintf(debug,"Inp %d = %s\n",(*inp)[i].count,(*inp)[i].name);
305 /*if (i == (*ninp)-1)*/
312 int get_eint(int *ninp,t_inpfile **inp,const char *name,int def,
315 char buf[32],*ptr,warn_buf[STRLEN];
319 ii=get_einp(ninp,inp,name);
322 sprintf(buf,"%d",def);
323 (*inp)[(*ninp)-1].value=strdup(buf);
328 ret = strtol((*inp)[ii].value,&ptr,10);
329 if (ptr == (*inp)[ii].value) {
330 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);
331 warning_error(wi,warn_buf);
338 gmx_large_int_t get_egmx_large_int(int *ninp,t_inpfile **inp,
339 const char *name,gmx_large_int_t def,
342 char buf[32],*ptr,warn_buf[STRLEN];
346 ii=get_einp(ninp,inp,name);
349 sprintf(buf,gmx_large_int_pfmt,def);
350 (*inp)[(*ninp)-1].value=strdup(buf);
355 ret = str_to_large_int_t((*inp)[ii].value,&ptr);
356 if (ptr == (*inp)[ii].value) {
357 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);
358 warning_error(wi,warn_buf);
365 double get_ereal(int *ninp,t_inpfile **inp,const char *name,double def,
368 char buf[32],*ptr,warn_buf[STRLEN];
372 ii=get_einp(ninp,inp,name);
375 sprintf(buf,"%g",def);
376 (*inp)[(*ninp)-1].value=strdup(buf);
381 ret = strtod((*inp)[ii].value,&ptr);
382 if (ptr == (*inp)[ii].value) {
383 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);
384 warning_error(wi,warn_buf);
391 const char *get_estr(int *ninp,t_inpfile **inp,const char *name,const char *def)
396 ii=get_einp(ninp,inp,name);
400 sprintf(buf,"%s",def);
401 (*inp)[(*ninp)-1].value=strdup(buf);
404 (*inp)[(*ninp)-1].value=NULL;
409 return (*inp)[ii].value;
412 int get_eeenum(int *ninp,t_inpfile **inp,const char *name,const char **defs,
419 ii=get_einp(ninp,inp,name);
422 (*inp)[(*ninp)-1].value=strdup(defs[0]);
427 for(i=0; (defs[i] != NULL); i++)
428 if (gmx_strcasecmp_min(defs[i],(*inp)[ii].value) == 0)
431 if (defs[i] == NULL) {
432 n += sprintf(buf,"Invalid enum '%s' for variable %s, using '%s'\n",
433 (*inp)[ii].value,name,defs[0]);
434 n += sprintf(buf+n,"Next time use one of:");
437 n += sprintf(buf+n," '%s'",defs[j]);
441 warning_error(wi,buf);
443 fprintf(stderr,"%s\n",buf);
446 (*inp)[ii].value = strdup(defs[0]);
454 int get_eenum(int *ninp,t_inpfile **inp,const char *name,const char **defs)
458 return get_eeenum(ninp,inp,name,defs,NULL);