Merge branch release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / gmxlib / readinp.c
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.
14
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.
19  *
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.
26  *
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.
29  *
30  * For more info, check our website at http://www.gromacs.org
31  *
32  * And Hey:
33  * GROningen Mixture of Alchemy and Childrens' Stories
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
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"
52
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);
55
56
57 t_inpfile *read_inpfile(const char *fn, int *ninp,
58                         warninp_t wi)
59 {
60     FILE      *in;
61     char       buf[STRLEN], lbuf[STRLEN], rbuf[STRLEN], warn_buf[STRLEN];
62     char      *ptr, *cptr;
63     t_inpfile *inp = NULL;
64     int        nin, lc, i, j, k;
65     /* setting cppopts from command-line options would be cooler */
66     gmx_bool   allow_override = FALSE;
67
68
69     if (debug)
70     {
71         fprintf(debug, "Reading MDP file %s\n", fn);
72     }
73
74     in = ffopen(fn, "r");
75
76     nin = lc  = 0;
77     do
78     {
79         ptr = fgets2(buf, STRLEN-1, in);
80         lc++;
81         set_warning_line(wi, fn, lc);
82         if (ptr)
83         {
84             /* Strip comment */
85             if ((cptr = strchr(buf, COMMENTSIGN)) != NULL)
86             {
87                 *cptr = '\0';
88             }
89             /* Strip spaces */
90             trim(buf);
91
92             for (j = 0; (buf[j] != '=') && (buf[j] != '\0'); j++)
93             {
94                 ;
95             }
96             if (buf[j] == '\0')
97             {
98                 if (j > 0)
99                 {
100                     if (debug)
101                     {
102                         fprintf(debug, "No = on line %d in file %s, ignored\n", lc, fn);
103                     }
104                 }
105             }
106             else
107             {
108                 for (i = 0; (i < j); i++)
109                 {
110                     lbuf[i] = buf[i];
111                 }
112                 lbuf[i] = '\0';
113                 trim(lbuf);
114                 if (lbuf[0] == '\0')
115                 {
116                     if (debug)
117                     {
118                         fprintf(debug, "Empty left hand side on line %d in file %s, ignored\n", lc, fn);
119                     }
120                 }
121                 else
122                 {
123                     for (i = j+1, k = 0; (buf[i] != '\0'); i++, k++)
124                     {
125                         rbuf[k] = buf[i];
126                     }
127                     rbuf[k] = '\0';
128                     trim(rbuf);
129                     if (rbuf[0] == '\0')
130                     {
131                         if (debug)
132                         {
133                             fprintf(debug, "Empty right hand side on line %d in file %s, ignored\n", lc, fn);
134                         }
135                     }
136                     else
137                     {
138                         /* Now finally something sensible */
139                         int found_index;
140
141                         /* first check whether we hit the 'multiple_entries' option */
142                         if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptName], lbuf) == 0)
143                         {
144                             /* we now check whether to allow overrides from here or not */
145                             if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptNo], rbuf) == 0)
146                             {
147                                 allow_override = FALSE;
148                             }
149                             else if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptLast], rbuf) == 0)
150                             {
151                                 allow_override = TRUE;
152                             }
153                             else
154                             {
155                                 sprintf(warn_buf,
156                                         "Parameter \"%s\" should either be %s or %s\n",
157                                         lbuf,
158                                         eMultentOpt_names[eMultentOptNo],
159                                         eMultentOpt_names[eMultentOptLast]);
160                                 warning_error(wi, warn_buf);
161                             }
162                         }
163                         else
164                         {
165                             /* it is a regular option; check for duplicates */
166                             found_index = search_einp(nin, inp, lbuf);
167
168                             if (found_index == -1)
169                             {
170                                 /* add a new item */
171                                 srenew(inp, ++nin);
172                                 inp[nin-1].inp_count  = 1;
173                                 inp[nin-1].count      = 0;
174                                 inp[nin-1].bObsolete  = FALSE;
175                                 inp[nin-1].bSet       = FALSE;
176                                 inp[nin-1].name       = strdup(lbuf);
177                                 inp[nin-1].value      = strdup(rbuf);
178                             }
179                             else
180                             {
181                                 if (!allow_override)
182                                 {
183                                     sprintf(warn_buf,
184                                             "Parameter \"%s\" doubly defined (and multiple assignments not allowed)\n",
185                                             lbuf);
186                                     warning_error(wi, warn_buf);
187                                 }
188                                 else
189                                 {
190                                     /* override */
191                                     sfree(inp[found_index].value);
192                                     inp[found_index].value = strdup(rbuf);
193                                     sprintf(warn_buf,
194                                             "Overriding existing parameter \"%s\" with value \"%s\"\n",
195                                             lbuf, rbuf);
196                                     warning_note(wi, warn_buf);
197                                 }
198                             }
199                         }
200                     }
201                 }
202             }
203         }
204     }
205     while (ptr);
206
207     ffclose(in);
208
209     if (debug)
210     {
211         fprintf(debug, "Done reading MDP file, there were %d entries in there\n",
212                 nin);
213     }
214
215     *ninp = nin;
216
217     return inp;
218 }
219
220
221
222
223 static int inp_comp(const void *a, const void *b)
224 {
225     return ((t_inpfile *)a)->count - ((t_inpfile *)b)->count;
226 }
227
228 static void sort_inp(int ninp, t_inpfile inp[])
229 {
230     int i, mm;
231
232     mm = -1;
233     for (i = 0; (i < ninp); i++)
234     {
235         mm = max(mm, inp[i].count);
236     }
237     for (i = 0; (i < ninp); i++)
238     {
239         if (inp[i].count == 0)
240         {
241             inp[i].count = mm++;
242         }
243     }
244     qsort(inp, ninp, (size_t)sizeof(inp[0]), inp_comp);
245 }
246
247 void write_inpfile(const char *fn, int ninp, t_inpfile inp[], gmx_bool bHaltOnUnknown,
248                    warninp_t wi)
249 {
250     FILE *out;
251     int   i;
252     char  warn_buf[STRLEN];
253
254     sort_inp(ninp, inp);
255     out = gmx_fio_fopen(fn, "w");
256     nice_header(out, fn);
257     for (i = 0; (i < ninp); i++)
258     {
259         if (inp[i].bSet)
260         {
261             if (inp[i].name[0] == ';' || (strlen(inp[i].name) > 2 && inp[i].name[1] == ';'))
262             {
263                 fprintf(out, "%-24s\n", inp[i].name);
264             }
265             else
266             {
267                 fprintf(out, "%-24s = %s\n", inp[i].name, inp[i].value ? inp[i].value : "");
268             }
269         }
270         else if (!inp[i].bObsolete)
271         {
272             sprintf(warn_buf, "Unknown left-hand '%s' in parameter file\n",
273                     inp[i].name);
274             if (bHaltOnUnknown)
275             {
276                 warning_error(wi, warn_buf);
277             }
278             else
279             {
280                 warning(wi, warn_buf);
281             }
282         }
283     }
284     gmx_fio_fclose(out);
285
286     check_warning_error(wi, FARGS);
287 }
288
289 void replace_inp_entry(int ninp, t_inpfile *inp, const char *old_entry, const char *new_entry)
290 {
291     int  i;
292
293     for (i = 0; (i < ninp); i++)
294     {
295         if (gmx_strcasecmp_min(old_entry, inp[i].name) == 0)
296         {
297             if (new_entry)
298             {
299                 fprintf(stderr, "Replacing old mdp entry '%s' by '%s'\n",
300                         inp[i].name, new_entry);
301                 sfree(inp[i].name);
302                 inp[i].name = strdup(new_entry);
303             }
304             else
305             {
306                 fprintf(stderr, "Ignoring obsolete mdp entry '%s'\n",
307                         inp[i].name);
308                 inp[i].bObsolete = TRUE;
309             }
310         }
311     }
312 }
313
314 static int search_einp(int ninp, const t_inpfile *inp, const char *name)
315 {
316     int i;
317
318     if (inp == NULL)
319     {
320         return -1;
321     }
322     for (i = 0; i < ninp; i++)
323     {
324         if (gmx_strcasecmp_min(name, inp[i].name) == 0)
325         {
326             return i;
327         }
328     }
329     return -1;
330 }
331
332 static int get_einp(int *ninp, t_inpfile **inp, const char *name)
333 {
334     int    i;
335     int    notfound = FALSE;
336     char   warn_buf[STRLEN];
337
338 /*  if (inp==NULL)
339     return -1;
340    for(i=0; (i<(*ninp)); i++)
341     if (gmx_strcasecmp_min(name,(*inp)[i].name) == 0)
342       break;
343    if (i == (*ninp)) {*/
344     i = search_einp(*ninp, *inp, name);
345     if (i == -1)
346     {
347         notfound = TRUE;
348         i        = (*ninp)++;
349         srenew(*inp, (*ninp));
350         (*inp)[i].name = strdup(name);
351         (*inp)[i].bSet = TRUE;
352     }
353     (*inp)[i].count = (*inp)[0].inp_count++;
354     (*inp)[i].bSet  = TRUE;
355     if (debug)
356     {
357         fprintf(debug, "Inp %d = %s\n", (*inp)[i].count, (*inp)[i].name);
358     }
359
360     /*if (i == (*ninp)-1)*/
361     if (notfound)
362     {
363         return -1;
364     }
365     else
366     {
367         return i;
368     }
369 }
370
371 int get_eint(int *ninp, t_inpfile **inp, const char *name, int def,
372              warninp_t wi)
373 {
374     char buf[32], *ptr, warn_buf[STRLEN];
375     int  ii;
376     int  ret;
377
378     ii = get_einp(ninp, inp, name);
379
380     if (ii == -1)
381     {
382         sprintf(buf, "%d", def);
383         (*inp)[(*ninp)-1].value = strdup(buf);
384
385         return def;
386     }
387     else
388     {
389         ret = strtol((*inp)[ii].value, &ptr, 10);
390         if (ptr == (*inp)[ii].value)
391         {
392             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);
393             warning_error(wi, warn_buf);
394         }
395
396         return ret;
397     }
398 }
399
400 gmx_large_int_t get_egmx_large_int(int *ninp, t_inpfile **inp,
401                                    const char *name, gmx_large_int_t def,
402                                    warninp_t wi)
403 {
404     char            buf[32], *ptr, warn_buf[STRLEN];
405     int             ii;
406     gmx_large_int_t ret;
407
408     ii = get_einp(ninp, inp, name);
409
410     if (ii == -1)
411     {
412         sprintf(buf, gmx_large_int_pfmt, def);
413         (*inp)[(*ninp)-1].value = strdup(buf);
414
415         return def;
416     }
417     else
418     {
419         ret = str_to_large_int_t((*inp)[ii].value, &ptr);
420         if (ptr == (*inp)[ii].value)
421         {
422             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);
423             warning_error(wi, warn_buf);
424         }
425
426         return ret;
427     }
428 }
429
430 double get_ereal(int *ninp, t_inpfile **inp, const char *name, double def,
431                  warninp_t wi)
432 {
433     char   buf[32], *ptr, warn_buf[STRLEN];
434     int    ii;
435     double ret;
436
437     ii = get_einp(ninp, inp, name);
438
439     if (ii == -1)
440     {
441         sprintf(buf, "%g", def);
442         (*inp)[(*ninp)-1].value = strdup(buf);
443
444         return def;
445     }
446     else
447     {
448         ret = strtod((*inp)[ii].value, &ptr);
449         if (ptr == (*inp)[ii].value)
450         {
451             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);
452             warning_error(wi, warn_buf);
453         }
454
455         return ret;
456     }
457 }
458
459 const char *get_estr(int *ninp, t_inpfile **inp, const char *name, const char *def)
460 {
461     char buf[32];
462     int  ii;
463
464     ii = get_einp(ninp, inp, name);
465
466     if (ii == -1)
467     {
468         if (def)
469         {
470             sprintf(buf, "%s", def);
471             (*inp)[(*ninp)-1].value = strdup(buf);
472         }
473         else
474         {
475             (*inp)[(*ninp)-1].value = NULL;
476         }
477
478         return def;
479     }
480     else
481     {
482         return (*inp)[ii].value;
483     }
484 }
485
486 int get_eeenum(int *ninp, t_inpfile **inp, const char *name, const char **defs,
487                warninp_t wi)
488 {
489     int  ii, i, j;
490     int  n = 0;
491     char buf[STRLEN];
492
493     ii = get_einp(ninp, inp, name);
494
495     if (ii == -1)
496     {
497         (*inp)[(*ninp)-1].value = strdup(defs[0]);
498
499         return 0;
500     }
501
502     for (i = 0; (defs[i] != NULL); i++)
503     {
504         if (gmx_strcasecmp_min(defs[i], (*inp)[ii].value) == 0)
505         {
506             break;
507         }
508     }
509
510     if (defs[i] == NULL)
511     {
512         n += sprintf(buf, "Invalid enum '%s' for variable %s, using '%s'\n",
513                      (*inp)[ii].value, name, defs[0]);
514         n += sprintf(buf+n, "Next time use one of:");
515         j  = 0;
516         while (defs[j])
517         {
518             n += sprintf(buf+n, " '%s'", defs[j]);
519             j++;
520         }
521         if (wi != NULL)
522         {
523             warning_error(wi, buf);
524         }
525         else
526         {
527             fprintf(stderr, "%s\n", buf);
528         }
529
530         (*inp)[ii].value = strdup(defs[0]);
531
532         return 0;
533     }
534
535     return i;
536 }
537
538 int get_eenum(int *ninp, t_inpfile **inp, const char *name, const char **defs)
539 {
540     int dum = 0;
541
542     return get_eeenum(ninp, inp, name, defs, NULL);
543 }