Merge "Append all ICC Performance flags only to Release Flags" into release-4-5-patches
[gromacs.git] / src / gmxlib / readinp.c
blob618d56de4526b2c282b9dbfb32f1f8c7c6c81b86
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.2.0
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
32 * And Hey:
33 * GROningen Mixture of Alchemy and Childrens' Stories
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include "typedefs.h"
42 #include "string2.h"
43 #include "futil.h"
44 #include "smalloc.h"
45 #include "readinp.h"
46 #include "macros.h"
47 #include "statutil.h"
48 #include "gmxfio.h"
49 #include "names.h"
50 #include "warninp.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,
58 char **cppopts,
59 warninp_t wi)
61 FILE *in;
62 char buf[STRLEN],lbuf[STRLEN],rbuf[STRLEN],warn_buf[STRLEN];
63 char *ptr,*cptr;
64 t_inpfile *inp=NULL;
65 int nin,lc,i,j,k;
66 /* setting cppopts from command-line options would be cooler */
67 gmx_bool allow_override=FALSE;
70 if (debug)
71 fprintf(debug,"Reading MDP file %s\n",fn);
73 in = ffopen(fn, "r");
75 nin = lc = 0;
76 do {
77 ptr = fgets2(buf,STRLEN-1,in);
78 lc++;
79 set_warning_line(wi,fn,lc);
80 if (ptr) {
81 /* Strip comment */
82 if ((cptr=strchr(buf,COMMENTSIGN)) != NULL)
83 *cptr='\0';
84 /* Strip spaces */
85 trim(buf);
87 for(j=0; (buf[j] != '=') && (buf[j] != '\0'); j++)
89 if (buf[j] == '\0') {
90 if (j > 0) {
91 if (debug)
92 fprintf(debug,"No = on line %d in file %s, ignored\n",lc,fn);
95 else {
96 for(i=0; (i<j); i++)
97 lbuf[i]=buf[i];
98 lbuf[i]='\0';
99 trim(lbuf);
100 if (lbuf[0] == '\0') {
101 if (debug)
102 fprintf(debug,"Empty left hand side on line %d in file %s, ignored\n",lc,fn);
104 else {
105 for(i=j+1,k=0; (buf[i] != '\0'); i++,k++)
106 rbuf[k]=buf[i];
107 rbuf[k]='\0';
108 trim(rbuf);
109 if (rbuf[0] == '\0') {
110 if (debug)
111 fprintf(debug,"Empty right hand side on line %d in file %s, ignored\n",lc,fn);
113 else {
114 /* Now finally something sensible */
115 int found_index;
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)
127 allow_override=TRUE;
129 else
131 sprintf(warn_buf,
132 "Parameter \"%s\" should either be %s or %s\n",
133 lbuf,
134 eMultentOpt_names[eMultentOptNo],
135 eMultentOpt_names[eMultentOptLast]);
136 warning_error(wi,warn_buf);
139 else
141 /* it is a regular option; check for duplicates */
142 found_index=search_einp(nin, inp, lbuf);
144 if (found_index == -1)
146 /* add a new item */
147 srenew(inp,++nin);
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);
155 else
157 if (!allow_override)
159 sprintf(warn_buf,
160 "Parameter \"%s\" doubly defined (and multiple assignments not allowed)\n",
161 lbuf);
162 warning_error(wi,warn_buf);
164 else
166 /* override */
167 sfree(inp[found_index].value);
168 inp[found_index].value = strdup(rbuf);
169 sprintf(warn_buf,
170 "Overriding existing parameter \"%s\" with value \"%s\"\n",
171 lbuf,rbuf);
172 warning_note(wi,warn_buf);
180 } while (ptr);
182 fclose(in);
184 if (debug) {
185 fprintf(debug,"Done reading MDP file, there were %d entries in there\n",
186 nin);
189 *ninp = nin;
191 return inp;
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[])
204 int i,mm;
206 mm=-1;
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)
211 inp[i].count = mm++;
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,
217 warninp_t wi)
219 FILE *out;
220 int i;
221 char warn_buf[STRLEN];
223 sort_inp(ninp,inp);
224 out=gmx_fio_fopen(fn,"w");
225 nice_header(out,fn);
226 for(i=0; (i<ninp); i++) {
227 if (inp[i].bSet) {
228 if(inp[i].name[0]==';' || (strlen(inp[i].name)>2 && inp[i].name[1]==';'))
229 fprintf(out,"%-24s\n",inp[i].name);
230 else
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",
234 inp[i].name);
235 if (bHaltOnUnknown) {
236 warning_error(wi,warn_buf);
237 } else {
238 warning(wi,warn_buf);
242 gmx_fio_fclose(out);
244 check_warning_error(wi,FARGS);
247 void replace_inp_entry(int ninp,t_inpfile *inp,const char *old_entry,const char *new_entry)
249 int i;
251 for(i=0; (i<ninp); i++) {
252 if (gmx_strcasecmp_min(old_entry,inp[i].name) == 0) {
253 if (new_entry) {
254 fprintf(stderr,"Replacing old mdp entry '%s' by '%s'\n",
255 inp[i].name,new_entry);
256 sfree(inp[i].name);
257 inp[i].name = strdup(new_entry);
258 } else {
259 fprintf(stderr,"Ignoring obsolete mdp entry '%s'\n",
260 inp[i].name);
261 inp[i].bObsolete = TRUE;
267 static int search_einp(int ninp, const t_inpfile *inp, const char *name)
269 int i;
271 if (inp==NULL)
272 return -1;
273 for(i=0; i<ninp; i++)
274 if (gmx_strcasecmp_min(name,inp[i].name) == 0)
275 return i;
276 return -1;
279 static int get_einp(int *ninp,t_inpfile **inp,const char *name)
281 int i;
282 int notfound=FALSE;
283 char warn_buf[STRLEN];
285 /* if (inp==NULL)
286 return -1;
287 for(i=0; (i<(*ninp)); i++)
288 if (gmx_strcasecmp_min(name,(*inp)[i].name) == 0)
289 break;
290 if (i == (*ninp)) {*/
291 i=search_einp(*ninp, *inp, name);
292 if (i == -1)
294 notfound=TRUE;
295 i=(*ninp)++;
296 srenew(*inp,(*ninp));
297 (*inp)[i].name=strdup(name);
298 (*inp)[i].bSet=TRUE;
300 (*inp)[i].count = (*inp)[0].inp_count++;
301 (*inp)[i].bSet = TRUE;
302 if (debug)
303 fprintf(debug,"Inp %d = %s\n",(*inp)[i].count,(*inp)[i].name);
305 /*if (i == (*ninp)-1)*/
306 if (notfound)
307 return -1;
308 else
309 return i;
312 int get_eint(int *ninp,t_inpfile **inp,const char *name,int def,
313 warninp_t wi)
315 char buf[32],*ptr,warn_buf[STRLEN];
316 int ii;
317 int ret;
319 ii=get_einp(ninp,inp,name);
321 if (ii == -1) {
322 sprintf(buf,"%d",def);
323 (*inp)[(*ninp)-1].value=strdup(buf);
325 return def;
327 else {
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);
334 return ret;
338 gmx_large_int_t get_egmx_large_int(int *ninp,t_inpfile **inp,
339 const char *name,gmx_large_int_t def,
340 warninp_t wi)
342 char buf[32],*ptr,warn_buf[STRLEN];
343 int ii;
344 gmx_large_int_t ret;
346 ii=get_einp(ninp,inp,name);
348 if (ii == -1) {
349 sprintf(buf,gmx_large_int_pfmt,def);
350 (*inp)[(*ninp)-1].value=strdup(buf);
352 return def;
354 else {
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);
361 return ret;
365 double get_ereal(int *ninp,t_inpfile **inp,const char *name,double def,
366 warninp_t wi)
368 char buf[32],*ptr,warn_buf[STRLEN];
369 int ii;
370 double ret;
372 ii=get_einp(ninp,inp,name);
374 if (ii == -1) {
375 sprintf(buf,"%g",def);
376 (*inp)[(*ninp)-1].value=strdup(buf);
378 return def;
380 else {
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);
387 return ret;
391 const char *get_estr(int *ninp,t_inpfile **inp,const char *name,const char *def)
393 char buf[32];
394 int ii;
396 ii=get_einp(ninp,inp,name);
398 if (ii == -1) {
399 if (def) {
400 sprintf(buf,"%s",def);
401 (*inp)[(*ninp)-1].value=strdup(buf);
403 else
404 (*inp)[(*ninp)-1].value=NULL;
406 return def;
408 else
409 return (*inp)[ii].value;
412 int get_eeenum(int *ninp,t_inpfile **inp,const char *name,const char **defs,
413 warninp_t wi)
415 int ii,i,j;
416 int n=0;
417 char buf[STRLEN];
419 ii=get_einp(ninp,inp,name);
421 if (ii == -1) {
422 (*inp)[(*ninp)-1].value=strdup(defs[0]);
424 return 0;
427 for(i=0; (defs[i] != NULL); i++)
428 if (gmx_strcasecmp_min(defs[i],(*inp)[ii].value) == 0)
429 break;
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:");
435 j=0;
436 while (defs[j]) {
437 n += sprintf(buf+n," '%s'",defs[j]);
438 j++;
440 if (wi != NULL) {
441 warning_error(wi,buf);
442 } else {
443 fprintf(stderr,"%s\n",buf);
446 (*inp)[ii].value = strdup(defs[0]);
448 return 0;
451 return i;
454 int get_eenum(int *ninp,t_inpfile **inp,const char *name,const char **defs)
456 int dum=0;
458 return get_eeenum(ninp,inp,name,defs,NULL);