Re-organize BlueGene toolchain files
[gromacs.git] / src / gmxlib / readinp.c
blob874de494aba529b6215c5482cbadbb5b221404ec
1 /*
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.
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include "typedefs.h"
45 #include "string2.h"
46 #include "futil.h"
47 #include "smalloc.h"
48 #include "readinp.h"
49 #include "macros.h"
50 #include "statutil.h"
51 #include "gmxfio.h"
52 #include "names.h"
53 #include "warninp.h"
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,
61 char **cppopts,
62 warninp_t wi)
64 FILE *in;
65 char buf[STRLEN],lbuf[STRLEN],rbuf[STRLEN],warn_buf[STRLEN];
66 char *ptr,*cptr;
67 t_inpfile *inp=NULL;
68 int nin,lc,i,j,k;
69 /* setting cppopts from command-line options would be cooler */
70 gmx_bool allow_override=FALSE;
73 if (debug)
74 fprintf(debug,"Reading MDP file %s\n",fn);
76 in = ffopen(fn, "r");
78 nin = lc = 0;
79 do {
80 ptr = fgets2(buf,STRLEN-1,in);
81 lc++;
82 set_warning_line(wi,fn,lc);
83 if (ptr) {
84 /* Strip comment */
85 if ((cptr=strchr(buf,COMMENTSIGN)) != NULL)
86 *cptr='\0';
87 /* Strip spaces */
88 trim(buf);
90 for(j=0; (buf[j] != '=') && (buf[j] != '\0'); j++)
92 if (buf[j] == '\0') {
93 if (j > 0) {
94 if (debug)
95 fprintf(debug,"No = on line %d in file %s, ignored\n",lc,fn);
98 else {
99 for(i=0; (i<j); i++)
100 lbuf[i]=buf[i];
101 lbuf[i]='\0';
102 trim(lbuf);
103 if (lbuf[0] == '\0') {
104 if (debug)
105 fprintf(debug,"Empty left hand side on line %d in file %s, ignored\n",lc,fn);
107 else {
108 for(i=j+1,k=0; (buf[i] != '\0'); i++,k++)
109 rbuf[k]=buf[i];
110 rbuf[k]='\0';
111 trim(rbuf);
112 if (rbuf[0] == '\0') {
113 if (debug)
114 fprintf(debug,"Empty right hand side on line %d in file %s, ignored\n",lc,fn);
116 else {
117 /* Now finally something sensible */
118 int found_index;
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)
130 allow_override=TRUE;
132 else
134 sprintf(warn_buf,
135 "Parameter \"%s\" should either be %s or %s\n",
136 lbuf,
137 eMultentOpt_names[eMultentOptNo],
138 eMultentOpt_names[eMultentOptLast]);
139 warning_error(wi,warn_buf);
142 else
144 /* it is a regular option; check for duplicates */
145 found_index=search_einp(nin, inp, lbuf);
147 if (found_index == -1)
149 /* add a new item */
150 srenew(inp,++nin);
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);
158 else
160 if (!allow_override)
162 sprintf(warn_buf,
163 "Parameter \"%s\" doubly defined (and multiple assignments not allowed)\n",
164 lbuf);
165 warning_error(wi,warn_buf);
167 else
169 /* override */
170 sfree(inp[found_index].value);
171 inp[found_index].value = strdup(rbuf);
172 sprintf(warn_buf,
173 "Overriding existing parameter \"%s\" with value \"%s\"\n",
174 lbuf,rbuf);
175 warning_note(wi,warn_buf);
183 } while (ptr);
185 ffclose(in);
187 if (debug) {
188 fprintf(debug,"Done reading MDP file, there were %d entries in there\n",
189 nin);
192 *ninp = nin;
194 return inp;
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[])
207 int i,mm;
209 mm=-1;
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)
214 inp[i].count = mm++;
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,
220 warninp_t wi)
222 FILE *out;
223 int i;
224 char warn_buf[STRLEN];
226 sort_inp(ninp,inp);
227 out=gmx_fio_fopen(fn,"w");
228 nice_header(out,fn);
229 for(i=0; (i<ninp); i++) {
230 if (inp[i].bSet) {
231 if(inp[i].name[0]==';' || (strlen(inp[i].name)>2 && inp[i].name[1]==';'))
232 fprintf(out,"%-24s\n",inp[i].name);
233 else
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",
237 inp[i].name);
238 if (bHaltOnUnknown) {
239 warning_error(wi,warn_buf);
240 } else {
241 warning(wi,warn_buf);
245 gmx_fio_fclose(out);
247 check_warning_error(wi,FARGS);
250 void replace_inp_entry(int ninp,t_inpfile *inp,const char *old_entry,const char *new_entry)
252 int i;
254 for(i=0; (i<ninp); i++) {
255 if (gmx_strcasecmp_min(old_entry,inp[i].name) == 0) {
256 if (new_entry) {
257 fprintf(stderr,"Replacing old mdp entry '%s' by '%s'\n",
258 inp[i].name,new_entry);
259 sfree(inp[i].name);
260 inp[i].name = strdup(new_entry);
261 } else {
262 fprintf(stderr,"Ignoring obsolete mdp entry '%s'\n",
263 inp[i].name);
264 inp[i].bObsolete = TRUE;
270 static int search_einp(int ninp, const t_inpfile *inp, const char *name)
272 int i;
274 if (inp==NULL)
275 return -1;
276 for(i=0; i<ninp; i++)
277 if (gmx_strcasecmp_min(name,inp[i].name) == 0)
278 return i;
279 return -1;
282 static int get_einp(int *ninp,t_inpfile **inp,const char *name)
284 int i;
285 int notfound=FALSE;
286 char warn_buf[STRLEN];
288 /* if (inp==NULL)
289 return -1;
290 for(i=0; (i<(*ninp)); i++)
291 if (gmx_strcasecmp_min(name,(*inp)[i].name) == 0)
292 break;
293 if (i == (*ninp)) {*/
294 i=search_einp(*ninp, *inp, name);
295 if (i == -1)
297 notfound=TRUE;
298 i=(*ninp)++;
299 srenew(*inp,(*ninp));
300 (*inp)[i].name=strdup(name);
301 (*inp)[i].bSet=TRUE;
303 (*inp)[i].count = (*inp)[0].inp_count++;
304 (*inp)[i].bSet = TRUE;
305 if (debug)
306 fprintf(debug,"Inp %d = %s\n",(*inp)[i].count,(*inp)[i].name);
308 /*if (i == (*ninp)-1)*/
309 if (notfound)
310 return -1;
311 else
312 return i;
315 int get_eint(int *ninp,t_inpfile **inp,const char *name,int def,
316 warninp_t wi)
318 char buf[32],*ptr,warn_buf[STRLEN];
319 int ii;
320 int ret;
322 ii=get_einp(ninp,inp,name);
324 if (ii == -1) {
325 sprintf(buf,"%d",def);
326 (*inp)[(*ninp)-1].value=strdup(buf);
328 return def;
330 else {
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);
337 return ret;
341 gmx_large_int_t get_egmx_large_int(int *ninp,t_inpfile **inp,
342 const char *name,gmx_large_int_t def,
343 warninp_t wi)
345 char buf[32],*ptr,warn_buf[STRLEN];
346 int ii;
347 gmx_large_int_t ret;
349 ii=get_einp(ninp,inp,name);
351 if (ii == -1) {
352 sprintf(buf,gmx_large_int_pfmt,def);
353 (*inp)[(*ninp)-1].value=strdup(buf);
355 return def;
357 else {
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);
364 return ret;
368 double get_ereal(int *ninp,t_inpfile **inp,const char *name,double def,
369 warninp_t wi)
371 char buf[32],*ptr,warn_buf[STRLEN];
372 int ii;
373 double ret;
375 ii=get_einp(ninp,inp,name);
377 if (ii == -1) {
378 sprintf(buf,"%g",def);
379 (*inp)[(*ninp)-1].value=strdup(buf);
381 return def;
383 else {
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);
390 return ret;
394 const char *get_estr(int *ninp,t_inpfile **inp,const char *name,const char *def)
396 char buf[32];
397 int ii;
399 ii=get_einp(ninp,inp,name);
401 if (ii == -1) {
402 if (def) {
403 sprintf(buf,"%s",def);
404 (*inp)[(*ninp)-1].value=strdup(buf);
406 else
407 (*inp)[(*ninp)-1].value=NULL;
409 return def;
411 else
412 return (*inp)[ii].value;
415 int get_eeenum(int *ninp,t_inpfile **inp,const char *name,const char **defs,
416 warninp_t wi)
418 int ii,i,j;
419 int n=0;
420 char buf[STRLEN];
422 ii=get_einp(ninp,inp,name);
424 if (ii == -1) {
425 (*inp)[(*ninp)-1].value=strdup(defs[0]);
427 return 0;
430 for(i=0; (defs[i] != NULL); i++)
431 if (gmx_strcasecmp_min(defs[i],(*inp)[ii].value) == 0)
432 break;
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:");
438 j=0;
439 while (defs[j]) {
440 n += sprintf(buf+n," '%s'",defs[j]);
441 j++;
443 if (wi != NULL) {
444 warning_error(wi,buf);
445 } else {
446 fprintf(stderr,"%s\n",buf);
449 (*inp)[ii].value = strdup(defs[0]);
451 return 0;
454 return i;
457 int get_eenum(int *ninp,t_inpfile **inp,const char *name,const char **defs)
459 int dum=0;
461 return get_eeenum(ninp,inp,name,defs,NULL);