Fixing copyright issues and code contributors
[alexxy/gromacs.git] / src / gmxlib / selection / params.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2009, The GROMACS development team,
6  * check out http://www.gromacs.org for more information.
7  * Copyright (c) 2012,2013, 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.
11  *
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.
16  *
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.
21  *
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.
26  *
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.
34  *
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.
37  */
38 /*! \internal \file
39  * \brief
40  * Implementation of functions in selparam.h.
41  */
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45
46 #include <smalloc.h>
47 #include <string2.h>
48 #include <vec.h>
49
50 #include <position.h>
51 #include <selmethod.h>
52 #include <selparam.h>
53
54 #include "parsetree.h"
55 #include "position.h"
56 #include "selelem.h"
57
58 /*!
59  * \param[in] name   Name of the parameter to search.
60  * \param[in] nparam Number of parameters in the \p param array.
61  * \param[in] param  Parameter array to search.
62  * \returns   Pointer to the parameter in the \p param
63  *   or NULL if no parameter with name \p name was found.
64  *
65  * The comparison is case-sensitive.
66  */
67 gmx_ana_selparam_t *
68 gmx_ana_selparam_find(const char *name, int nparam, gmx_ana_selparam_t *param)
69 {
70     int                i;
71
72     if (nparam == 0)
73     {
74         return NULL;
75     }
76     /* Find the first non-null parameter */
77     i = 0;
78     while (i < nparam && param[i].name == NULL)
79     {
80         ++i;
81     }
82     /* Process the special case of a NULL parameter */
83     if (name == NULL)
84     {
85         return (i == 0) ? NULL : &param[i-1];
86     }
87     for ( ; i < nparam; ++i)
88     {
89         if (!strcmp(param[i].name, name))
90         {
91             return &param[i];
92         }
93         /* Check for 'no' prefix on gmx_boolean parameters */
94         if (param[i].val.type == NO_VALUE
95             && strlen(name) > 2 && name[0] == 'n' && name[1] == 'o'
96             && !strcmp(param[i].name, name+2))
97         {
98             return &param[i];
99         }
100     }
101     return NULL;
102 }
103
104 /*! \brief
105  * Does a type conversion on a \c t_selexpr_value.
106  *
107  * \param[in,out] value    Value to convert.
108  * \param[in]     type     Type to convert to.
109  * \param[in]     scanner  Scanner data structure.
110  * \returns       0 on success, a non-zero value on error.
111  */
112 static int
113 convert_value(t_selexpr_value *value, e_selvalue_t type, void *scanner)
114 {
115     if (value->type == type || type == NO_VALUE)
116     {
117         return 0;
118     }
119     if (value->bExpr)
120     {
121         /* Conversion from atom selection to position using default
122          * reference positions. */
123         if (value->type == GROUP_VALUE && type == POS_VALUE)
124         {
125             value->u.expr =
126                 _gmx_sel_init_position(value->u.expr, NULL, scanner);
127             if (value->u.expr == NULL)
128             {
129                 return -1;
130             }
131             value->type = type;
132             return 0;
133         }
134         return -1;
135     }
136     else
137     {
138         /* Integers to floating point are easy */
139         if (value->type == INT_VALUE && type == REAL_VALUE)
140         {
141             real r1 = (real)value->u.i.i1;
142             real r2 = (real)value->u.i.i2;
143             value->u.r.r1 = r1;
144             value->u.r.r2 = r2;
145             value->type = type;
146             return 0;
147         }
148         /* Reals that are integer-valued can also be converted */
149         if (value->type == REAL_VALUE && type == INT_VALUE
150             && gmx_within_tol(value->u.r.r1, (int)value->u.r.r1, GMX_REAL_EPS)
151             && gmx_within_tol(value->u.r.r2, (int)value->u.r.r2, GMX_REAL_EPS))
152         {
153             int i1 = (int)value->u.r.r1;
154             int i2 = (int)value->u.r.r2;
155             value->u.i.i1 = i1;
156             value->u.i.i2 = i2;
157             value->type = type;
158             return 0;
159         }
160     }
161     return -1;
162 }
163
164 /*! \brief
165  * Does a type conversion on a list of values.
166  *
167  * \param[in,out] values   Values to convert.
168  * \param[in]     type     Type to convert to.
169  * \param[in]     scanner  Scanner data structure.
170  * \returns       0 on success, a non-zero value on error.
171  */
172 static int
173 convert_values(t_selexpr_value *values, e_selvalue_t type, void *scanner)
174 {
175     t_selexpr_value *value;
176     int              rc, rc1;
177
178     rc = 0;
179     value = values;
180     while (value)
181     {
182         rc1 = convert_value(value, type, scanner);
183         if (rc1 != 0 && rc == 0)
184         {
185             rc = rc1;
186         }
187         value = value->next;
188     }
189     /* FIXME: More informative error messages */
190     return rc;
191 }
192
193 /*! \brief
194  * Adds a child element for a parameter, keeping the parameter order.
195  *
196  * \param[in,out] root  Root element to which the child is added.
197  * \param[in]     child Child to add.
198  * \param[in]     param Parameter for which this child is a value.
199  *
200  * Puts \p child in the child list of \p root such that the list remains
201  * in the same order as the corresponding parameters.
202  */
203 static void
204 place_child(t_selelem *root, t_selelem *child, gmx_ana_selparam_t *param)
205 {
206     gmx_ana_selparam_t *ps;
207     int                 n;
208
209     ps = root->u.expr.method->param;
210     n  = param - ps;
211     /* Put the child element in the correct place */
212     if (!root->child || n < root->child->u.param - ps)
213     {
214         child->next = root->child;
215         root->child = child;
216     }
217     else
218     {
219         t_selelem *prev;
220
221         prev = root->child;
222         while (prev->next && prev->next->u.param - ps >= n)
223         {
224             prev = prev->next;
225         }
226         child->next = prev->next;
227         prev->next  = child;
228     }
229 }
230
231 /*! \brief
232  * Comparison function for sorting integer ranges.
233  * 
234  * \param[in] a Pointer to the first range.
235  * \param[in] b Pointer to the second range.
236  * \returns   -1, 0, or 1 depending on the relative order of \p a and \p b.
237  *
238  * The ranges are primarily sorted based on their starting point, and
239  * secondarily based on length (longer ranges come first).
240  */
241 static int
242 cmp_int_range(const void *a, const void *b)
243 {
244     if (((int *)a)[0] < ((int *)b)[0])
245     {
246         return -1;
247     }
248     if (((int *)a)[0] > ((int *)b)[0])
249     {
250         return 1;
251     }
252     if (((int *)a)[1] > ((int *)b)[1])
253     {
254         return -1;
255     }
256     return 0;
257 }
258
259 /*! \brief
260  * Comparison function for sorting real ranges.
261  *
262  * \param[in] a Pointer to the first range.
263  * \param[in] b Pointer to the second range.
264  * \returns   -1, 0, or 1 depending on the relative order of \p a and \p b.
265  *
266  * The ranges are primarily sorted based on their starting point, and
267  * secondarily based on length (longer ranges come first).
268  */
269 static int
270 cmp_real_range(const void *a, const void *b)
271 {
272     if (((real *)a)[0] < ((real *)b)[0])
273     {
274         return -1;
275     }
276     if (((real *)a)[0] > ((real *)b)[0])
277     {
278         return 1;
279     }
280     if (((real *)a)[1] > ((real *)b)[1])
281     {
282         return -1;
283     }
284     return 0;
285 }
286
287 /*! \brief
288  * Parses the values for a parameter that takes integer or real ranges.
289  * 
290  * \param[in] nval   Number of values in \p values.
291  * \param[in] values Pointer to the list of values.
292  * \param     param  Parameter to parse.
293  * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
294  */
295 static gmx_bool
296 parse_values_range(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param)
297 {
298     t_selexpr_value    *value;
299     int                *idata;
300     real               *rdata;
301     int                 i, j, n;
302
303     param->flags &= ~SPAR_DYNAMIC;
304     if (param->val.type != INT_VALUE && param->val.type != REAL_VALUE)
305     {
306         gmx_bug("internal error");
307         return FALSE;
308     }
309     idata = NULL;
310     rdata = NULL;
311     if (param->val.type == INT_VALUE)
312     {
313         snew(idata, nval*2);
314     }
315     else
316     {
317         snew(rdata, nval*2);
318     }
319     value = values;
320     i = 0;
321     while (value)
322     {
323         if (value->bExpr)
324         {
325             _gmx_selparser_error("expressions not supported within range parameters");
326             return FALSE;
327         }
328         if (value->type != param->val.type)
329         {
330             gmx_bug("internal error");
331             return FALSE;
332         }
333         if (param->val.type == INT_VALUE)
334         {
335             /* Make sure the input range is in increasing order */
336             if (value->u.i.i1 > value->u.i.i2)
337             {
338                 int tmp       = value->u.i.i1;
339                 value->u.i.i1 = value->u.i.i2;
340                 value->u.i.i2 = tmp;
341             }
342             /* Check if the new range overlaps or extends the previous one */
343             if (i > 0 && value->u.i.i1 <= idata[i-1]+1 && value->u.i.i2 >= idata[i-2]-1)
344             {
345                 idata[i-2] = min(idata[i-2], value->u.i.i1);
346                 idata[i-1] = max(idata[i-1], value->u.i.i2);
347             }
348             else
349             {
350                 idata[i++] = value->u.i.i1;
351                 idata[i++] = value->u.i.i2;
352             }
353         }
354         else
355         {
356             /* Make sure the input range is in increasing order */
357             if (value->u.r.r1 > value->u.r.r2)
358             {
359                 real tmp      = value->u.r.r1;
360                 value->u.r.r1 = value->u.r.r2;
361                 value->u.r.r2 = tmp;
362             }
363             /* Check if the new range overlaps or extends the previous one */
364             if (i > 0 && value->u.r.r1 <= rdata[i-1] && value->u.r.r2 >= rdata[i-2])
365             {
366                 rdata[i-2] = min(rdata[i-2], value->u.r.r1);
367                 rdata[i-1] = max(rdata[i-1], value->u.r.r2);
368             }
369             else
370             {
371                 rdata[i++] = value->u.r.r1;
372                 rdata[i++] = value->u.r.r2;
373             }
374         }
375         value = value->next;
376     }
377     n = i/2;
378     /* Sort the ranges and merge consequent ones */
379     if (param->val.type == INT_VALUE)
380     {
381         qsort(idata, n, 2*sizeof(int), &cmp_int_range);
382         for (i = j = 2; i < 2*n; i += 2)
383         {
384             if (idata[j-1]+1 >= idata[i])
385             {
386                 if (idata[i+1] > idata[j-1])
387                 {
388                     idata[j-1] = idata[i+1];
389                 }
390             }
391             else
392             {
393                 idata[j]   = idata[i];
394                 idata[j+1] = idata[i+1];
395                 j += 2;
396             }
397         }
398     }
399     else
400     {
401         qsort(rdata, n, 2*sizeof(real), &cmp_real_range);
402         for (i = j = 2; i < 2*n; i += 2)
403         {
404             if (rdata[j-1]+1 >= rdata[i])
405             {
406                 if (rdata[i+1] > rdata[j-1])
407                 {
408                     rdata[j-1] = rdata[i+1];
409                 }
410             }
411             else
412             {
413                 rdata[j]   = rdata[i];
414                 rdata[j+1] = rdata[i+1];
415                 j += 2;
416             }
417         }
418     }
419     n = j/2;
420     /* Store the values */
421     if (param->flags & SPAR_VARNUM)
422     {
423         param->val.nr  = n;
424         if (param->val.type == INT_VALUE)
425         {
426             srenew(idata, j);
427             _gmx_selvalue_setstore_alloc(&param->val, idata, j);
428         }
429         else
430         {
431             srenew(rdata, j);
432             _gmx_selvalue_setstore_alloc(&param->val, rdata, j);
433         }
434     }
435     else
436     {
437         if (n != param->val.nr)
438         {
439             _gmx_selparser_error("the value of parameter '%s' should consist of exactly one range",
440                                  param->name);       
441             sfree(idata);
442             sfree(rdata);
443             return FALSE;
444         }
445         if (param->val.type == INT_VALUE)
446         {
447             memcpy(param->val.u.i, idata, 2*n*sizeof(int));
448             sfree(idata);
449         }
450         else
451         {
452             memcpy(param->val.u.r, rdata, 2*n*sizeof(real));
453             sfree(rdata);
454         }
455     }
456     if (param->nvalptr)
457     {
458         *param->nvalptr = param->val.nr;
459     }
460     param->nvalptr = NULL;
461
462     return TRUE;
463 }
464
465 /*! \brief
466  * Parses the values for a parameter that takes a variable number of values.
467  * 
468  * \param[in] nval   Number of values in \p values.
469  * \param[in] values Pointer to the list of values.
470  * \param     param  Parameter to parse.
471  * \param     root   Selection element to which child expressions are added.
472  * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
473  *
474  * For integer ranges, the sequence of numbers from the first to second value
475  * is stored, each as a separate value.
476  */
477 static gmx_bool
478 parse_values_varnum(int nval, t_selexpr_value *values,
479                     gmx_ana_selparam_t *param, t_selelem *root)
480 {
481     t_selexpr_value    *value;
482     int                 i, j;
483
484     param->flags &= ~SPAR_DYNAMIC;
485     /* Update nval if there are integer ranges. */
486     if (param->val.type == INT_VALUE)
487     {
488         value = values;
489         while (value)
490         {
491             if (value->type == INT_VALUE && !value->bExpr)
492             {
493                 nval += abs(value->u.i.i2 - value->u.i.i1);
494             }
495             value = value->next;
496         }
497     }
498
499     /* Check that the value type is actually implemented */
500     if (param->val.type != INT_VALUE && param->val.type != REAL_VALUE
501         && param->val.type != STR_VALUE && param->val.type != POS_VALUE)
502     {
503         gmx_bug("internal error");
504         return FALSE;
505     }
506
507     /* Reserve appropriate amount of memory */
508     if (param->val.type == POS_VALUE)
509     {
510         gmx_ana_pos_reserve(param->val.u.p, nval, 0);
511         gmx_ana_pos_set_nr(param->val.u.p, nval);
512         gmx_ana_indexmap_init(&param->val.u.p->m, NULL, NULL, INDEX_UNKNOWN);
513     }
514     else
515     {
516         _gmx_selvalue_reserve(&param->val, nval);
517     }
518
519     value = values;
520     i     = 0;
521     while (value)
522     {
523         if (value->bExpr)
524         {
525             _gmx_selparser_error("expressions not supported within value lists");
526             return FALSE;
527         }
528         if (value->type != param->val.type)
529         {
530             gmx_bug("internal error");
531             return FALSE;
532         }
533         switch (param->val.type)
534         {
535             case INT_VALUE:
536                 if (value->u.i.i1 <= value->u.i.i2)
537                 {
538                     for (j = value->u.i.i1; j <= value->u.i.i2; ++j)
539                     {
540                         param->val.u.i[i++] = j;
541                     }
542                 }
543                 else
544                 {
545                     for (j = value->u.i.i1; j >= value->u.i.i2; --j)
546                     {
547                         param->val.u.i[i++] = j;
548                     }
549                 }
550                 break;
551             case REAL_VALUE:
552                 if (value->u.r.r1 != value->u.r.r2)
553                 {
554                     _gmx_selparser_error("real ranges not supported for parameter '%s'", param->name);
555                     return FALSE;
556                 }
557                 param->val.u.r[i++] = value->u.r.r1;
558                 break;
559             case STR_VALUE:  param->val.u.s[i++] = strdup(value->u.s); break;
560             case POS_VALUE:  copy_rvec(value->u.x, param->val.u.p->x[i++]); break;
561             default: /* Should not be reached */
562                 gmx_bug("internal error");
563                 return FALSE;
564         }
565         value = value->next;
566     }
567     param->val.nr = i;
568     if (param->nvalptr)
569     {
570         *param->nvalptr = param->val.nr;
571     }
572     param->nvalptr = NULL;
573     /* Create a dummy child element to store the string values.
574      * This element is responsible for freeing the values, but carries no
575      * other function. */
576     if (param->val.type == STR_VALUE)
577     {
578         t_selelem *child;
579
580         child = _gmx_selelem_create(SEL_CONST);
581         _gmx_selelem_set_vtype(child, STR_VALUE);
582         child->name = param->name;
583         child->flags &= ~SEL_ALLOCVAL;
584         child->flags |= SEL_FLAGSSET | SEL_VARNUMVAL | SEL_ALLOCDATA;
585         child->v.nr = param->val.nr;
586         _gmx_selvalue_setstore(&child->v, param->val.u.s);
587         /* Because the child is not group-valued, the u union is not used
588          * for anything, so we can abuse it by storing the parameter value
589          * as place_child() expects, but this is really ugly... */
590         child->u.param = param;
591         place_child(root, child, param);
592     }
593
594     return TRUE;
595 }
596
597 /*! \brief
598  * Adds a new subexpression reference to a selection element.
599  *
600  * \param[in,out] root  Root element to which the subexpression is added.
601  * \param[in]     param Parameter for which this expression is a value.
602  * \param[in]     expr  Expression to add.
603  * \returns       The created child element.
604  *
605  * Creates a new \ref SEL_SUBEXPRREF element and adds it into the child
606  * list of \p root.
607  * If \p expr is already a \ref SEL_SUBEXPRREF, it is used as it is.
608  * \ref SEL_ALLOCVAL is cleared for the returned element.
609  */
610 static t_selelem *
611 add_child(t_selelem *root, gmx_ana_selparam_t *param, t_selelem *expr)
612 {
613     t_selelem          *child;
614     int                 rc;
615
616     if (root->type != SEL_EXPRESSION && root->type != SEL_MODIFIER)
617     {
618         gmx_bug("unsupported root element for selection parameter parser");
619         return NULL;
620     }
621     /* Create a subexpression reference element if necessary */
622     if (expr->type == SEL_SUBEXPRREF)
623     {
624         child = expr;
625     }
626     else
627     {
628         child = _gmx_selelem_create(SEL_SUBEXPRREF);
629         if (!child)
630         {
631             return NULL;
632         }
633         _gmx_selelem_set_vtype(child, expr->v.type);
634         child->child  = expr;
635     }
636     /* Setup the child element */
637     child->flags &= ~SEL_ALLOCVAL;
638     child->u.param = param;
639     if (child->v.type != param->val.type)
640     {
641         _gmx_selparser_error("invalid expression value for parameter '%s'",
642                              param->name);
643         goto on_error;
644     }
645     rc = _gmx_selelem_update_flags(child);
646     if (rc != 0)
647     {
648         goto on_error;
649     }
650     if ((child->flags & SEL_DYNAMIC) && !(param->flags & SPAR_DYNAMIC))
651     {
652         _gmx_selparser_error("parameter '%s' does not support dynamic values",
653                              param->name);
654         goto on_error;
655     }
656     if (!(child->flags & SEL_DYNAMIC))
657     {
658         param->flags &= ~SPAR_DYNAMIC;
659     }
660     /* Put the child element in the correct place */
661     place_child(root, child, param);
662     return child;
663
664 on_error:
665     if (child != expr)
666     {
667         _gmx_selelem_free(child);
668     }
669     return NULL;
670 }
671
672 /*! \brief
673  * Parses an expression value for a parameter that takes a variable number of values.
674  * 
675  * \param[in] nval   Number of values in \p values.
676  * \param[in] values Pointer to the list of values.
677  * \param     param  Parameter to parse.
678  * \param     root   Selection element to which child expressions are added.
679  * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
680  */
681 static gmx_bool
682 parse_values_varnum_expr(int nval, t_selexpr_value *values,
683                          gmx_ana_selparam_t *param, t_selelem *root)
684 {
685     t_selexpr_value    *value;
686     t_selelem          *child;
687     t_selelem          *expr;
688
689     if (nval != 1 || !values->bExpr)
690     {
691         gmx_bug("internal error");
692         return FALSE;
693     }
694
695     value = values;
696     child = add_child(root, param, value->u.expr);
697     value->u.expr = NULL;
698     if (!child)
699     {
700         return FALSE;
701     }
702
703     /* Process single-valued expressions */
704     /* TODO: We should also handle SEL_SINGLEVAL expressions here */
705     if (child->v.type == POS_VALUE || child->v.type == GROUP_VALUE)
706     {
707         /* Set the value storage */
708         _gmx_selvalue_setstore(&child->v, param->val.u.ptr);
709         param->val.nr = 1;
710         if (param->nvalptr)
711         {
712             *param->nvalptr = param->val.nr;
713         }
714         param->nvalptr = NULL;
715         return TRUE;
716     }
717
718     if (!(child->flags & SEL_VARNUMVAL))
719     {
720         _gmx_selparser_error("invalid expression value for parameter '%s'",
721                              param->name);
722         return FALSE;
723     }
724
725     child->flags   |= SEL_ALLOCVAL;
726     param->val.nr   = -1;
727     *param->nvalptr = param->val.nr;
728     /* Rest of the initialization is done during compilation in
729      * init_method(). */
730
731     return TRUE;
732 }
733
734 /*! \brief
735  * Initializes the storage of an expression value.
736  *
737  * \param[in,out] sel   Selection element that evaluates the value.
738  * \param[in]     param Parameter to receive the value.
739  * \param[in]     i     The value of \p sel evaluates the value \p i for
740  *   \p param.
741  *
742  * Initializes the data pointer of \p sel such that the result is stored
743  * as the value \p i of \p param.
744  * This function is used internally by parse_values_std().
745  */
746 static gmx_bool
747 set_expr_value_store(t_selelem *sel, gmx_ana_selparam_t *param, int i)
748 {
749     if (sel->v.type != GROUP_VALUE && !(sel->flags & SEL_SINGLEVAL))
750     {
751         _gmx_selparser_error("invalid expression value for parameter '%s'",
752                              param->name);
753         return FALSE;
754     }
755     switch (sel->v.type)
756     {
757         case INT_VALUE:   sel->v.u.i = &param->val.u.i[i]; break;
758         case REAL_VALUE:  sel->v.u.r = &param->val.u.r[i]; break;
759         case STR_VALUE:   sel->v.u.s = &param->val.u.s[i]; break;
760         case POS_VALUE:   sel->v.u.p = &param->val.u.p[i]; break;
761         case GROUP_VALUE: sel->v.u.g = &param->val.u.g[i]; break;
762         default: /* Error */
763             gmx_bug("internal error");
764             return FALSE;
765     }
766     sel->v.nr = 1;
767     sel->v.nalloc = -1;
768     return TRUE;
769 }
770
771 /*! \brief
772  * Parses the values for a parameter that takes a constant number of values.
773  * 
774  * \param[in] nval   Number of values in \p values.
775  * \param[in] values Pointer to the list of values.
776  * \param     param  Parameter to parse.
777  * \param     root   Selection element to which child expressions are added.
778  * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
779  *
780  * For integer ranges, the sequence of numbers from the first to second value
781  * is stored, each as a separate value.
782  */
783 static gmx_bool
784 parse_values_std(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param,
785                  t_selelem *root)
786 {
787     t_selexpr_value   *value;
788     t_selelem         *child;
789     int                i, j;
790     gmx_bool               bDynamic;
791
792     /* Handle atom-valued parameters */
793     if (param->flags & SPAR_ATOMVAL)
794     {
795         if (nval > 1)
796         {
797             _gmx_selparser_error("extra values for parameter '%s'", param->name);
798             return FALSE;
799         }
800         value = values;
801         if (value->bExpr)
802         {
803             child = add_child(root, param, value->u.expr);
804             value->u.expr = NULL;
805             if (!child)
806             {
807                 return FALSE;
808             }
809             child->flags |= SEL_ALLOCVAL;
810             if (child->v.type != GROUP_VALUE && (child->flags & SEL_ATOMVAL))
811             {
812                 /* Rest of the initialization is done during compilation in
813                  * init_method(). */
814                 /* TODO: Positions are not correctly handled */
815                 param->val.nr = -1;
816                 if (param->nvalptr)
817                 {
818                     *param->nvalptr = -1;
819                 }
820                 return TRUE;
821             }
822             param->flags  &= ~SPAR_ATOMVAL;
823             param->val.nr  = 1;
824             if (param->nvalptr)
825             {
826                 *param->nvalptr = 1;
827             }
828             param->nvalptr = NULL;
829             if (param->val.type == INT_VALUE || param->val.type == REAL_VALUE
830                 || param->val.type == STR_VALUE)
831             {
832                 _gmx_selvalue_reserve(&param->val, 1);
833             }
834             return set_expr_value_store(child, param, 0);
835         }
836         /* If we reach here, proceed with normal parameter handling */
837         param->val.nr = 1;
838         if (param->val.type == INT_VALUE || param->val.type == REAL_VALUE
839             || param->val.type == STR_VALUE)
840         {
841             _gmx_selvalue_reserve(&param->val, 1);
842         }
843         param->flags &= ~SPAR_ATOMVAL;
844         param->flags &= ~SPAR_DYNAMIC;
845     }
846
847     value = values;
848     i = 0;
849     bDynamic = FALSE;
850     while (value && i < param->val.nr)
851     {
852         if (value->type != param->val.type)
853         {
854             _gmx_selparser_error("incorrect value for parameter '%s' skipped", param->name);
855             value = value->next;
856             continue;
857         }
858         if (value->bExpr)
859         {
860             child = add_child(root, param, value->u.expr);
861             /* Clear the expression from the value once it is stored */
862             value->u.expr = NULL;
863             /* Check that the expression is valid */
864             if (!child)
865             {
866                 return FALSE;
867             }
868             if (!set_expr_value_store(child, param, i))
869             {
870                 return FALSE;
871             }
872             if (child->flags & SEL_DYNAMIC)
873             {
874                 bDynamic = TRUE;
875             }
876         }
877         else
878         {
879             /* Value is not an expression */
880             switch (value->type)
881             {
882                 case INT_VALUE:
883                     if (value->u.i.i1 <= value->u.i.i2)
884                     {
885                         for (j = value->u.i.i1; j <= value->u.i.i2 && i < param->val.nr; ++j)
886                         {
887                             param->val.u.i[i++] = j;
888                         }
889                         if (j != value->u.i.i2 + 1)
890                         {
891                             _gmx_selparser_error("extra values for parameter '%s' skipped", param->name);
892                         }
893                     }
894                     else
895                     {
896                         for (j = value->u.i.i1; j >= value->u.i.i2 && i < param->val.nr; --j)
897                         {
898                             param->val.u.i[i++] = j;
899                         }
900                         if (j != value->u.i.i2 - 1)
901                         {
902                             _gmx_selparser_error("extra values for parameter '%s' skipped", param->name);
903                         }
904                     }
905                     --i;
906                     break;
907                 case REAL_VALUE:
908                     if (value->u.r.r1 != value->u.r.r2)
909                     {
910                         _gmx_selparser_error("real ranges not supported for parameter '%s'", param->name);
911                         return FALSE;
912                     }
913                     param->val.u.r[i] = value->u.r.r1;
914                     break;
915                 case STR_VALUE:
916                     param->val.u.s[i] = strdup(value->u.s);
917                     break;
918                 case POS_VALUE:
919                     gmx_ana_pos_init_const(&param->val.u.p[i], value->u.x);
920                     break;
921                 case NO_VALUE:
922                 case GROUP_VALUE:
923                     gmx_bug("internal error");
924                     return FALSE;
925             }
926         }
927         ++i;
928         value = value->next;
929     }
930     if (value)
931     {
932         _gmx_selparser_error("extra values for parameter '%s'", param->name);
933         return FALSE;
934     }
935     if (i < param->val.nr)
936     {
937         _gmx_selparser_error("not enough values for parameter '%s'", param->name);
938         return FALSE;
939     }
940     if (!bDynamic)
941     {
942         param->flags &= ~SPAR_DYNAMIC;
943     }
944     if (param->nvalptr)
945     {
946         *param->nvalptr = param->val.nr;
947     }
948     param->nvalptr = NULL;
949
950     return TRUE;
951 }
952
953 /*! \brief
954  * Parses the values for a gmx_boolean parameter.
955  *
956  * \param[in] name   Name by which the parameter was given.
957  * \param[in] nval   Number of values in \p values.
958  * \param[in] values Pointer to the list of values.
959  * \param     param  Parameter to parse.
960  * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
961  */
962 static gmx_bool
963 parse_values_gmx_bool(const char *name, int nval, t_selexpr_value *values, gmx_ana_selparam_t *param)
964 {
965     gmx_bool bSetNo;
966     int  len;
967
968     if (param->val.type != NO_VALUE)
969     {
970         gmx_bug("internal error");
971         return FALSE;
972     }
973     if (nval > 1 || (values && values->type != INT_VALUE))
974     {
975         _gmx_selparser_error("gmx_boolean parameter '%s' takes only a yes/no/on/off/0/1 value", param->name);
976         return FALSE;
977     }
978
979     bSetNo = FALSE;
980     /* Check if the parameter name is given with a 'no' prefix */
981     len = strlen(name);
982     if (len > 2 && name[0] == 'n' && name[1] == 'o'
983         && strncmp(name+2, param->name, len-2) == 0)
984     {
985         bSetNo = TRUE;
986     }
987     if (bSetNo && nval > 0)
988     {
989         _gmx_selparser_error("gmx_boolean parameter 'no%s' should not have a value", param->name);
990         return FALSE;
991     }
992     if (values && values->u.i.i1 == 0)
993     {
994         bSetNo = TRUE;
995     }
996
997     *param->val.u.b = bSetNo ? FALSE : TRUE;
998     return TRUE;
999 }
1000
1001 /*! \brief
1002  * Parses the values for an enumeration parameter.
1003  *
1004  * \param[in] nval   Number of values in \p values.
1005  * \param[in] values Pointer to the list of values.
1006  * \param     param  Parameter to parse.
1007  * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
1008  */
1009 static gmx_bool
1010 parse_values_enum(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param)
1011 {
1012     int  i, len, match;
1013
1014     if (nval != 1)
1015     {
1016         _gmx_selparser_error("a single value is required for parameter '%s'", param->name);
1017         return FALSE;
1018     }
1019     if (values->type != STR_VALUE || param->val.type != STR_VALUE)
1020     {
1021         gmx_bug("internal error");
1022         return FALSE;
1023     }
1024     if (values->bExpr)
1025     {
1026         _gmx_selparser_error("expression value for enumerated parameter '%s' not supported", param->name);
1027         return FALSE;
1028     }
1029
1030     len = strlen(values->u.s);
1031     i = 1;
1032     match = 0;
1033     while (param->val.u.s[i] != NULL)
1034     {
1035         if (strncmp(values->u.s, param->val.u.s[i], len) == 0)
1036         {
1037             /* Check if there is a duplicate match */
1038             if (match > 0)
1039             {
1040                 _gmx_selparser_error("ambiguous value for parameter '%s'", param->name);
1041                 return FALSE;
1042             }
1043             match = i;
1044         }
1045         ++i;
1046     }
1047     if (match == 0)
1048     {
1049         _gmx_selparser_error("invalid value for parameter '%s'", param->name);
1050         return FALSE;
1051     }
1052     param->val.u.s[0] = param->val.u.s[match];
1053     return TRUE;
1054 }
1055
1056 /*! \brief
1057  * Replaces constant expressions with their values.
1058  *
1059  * \param[in,out] values First element in the value list to process.
1060  */
1061 static void
1062 convert_const_values(t_selexpr_value *values)
1063 {
1064     t_selexpr_value *val;
1065
1066     val = values;
1067     while (val)
1068     {
1069         if (val->bExpr && val->u.expr->v.type != GROUP_VALUE &&
1070             val->u.expr->type == SEL_CONST)
1071         {
1072             t_selelem *expr = val->u.expr;
1073             val->bExpr = FALSE;
1074             switch (expr->v.type)
1075             {
1076                 case INT_VALUE:
1077                     val->u.i.i1 = val->u.i.i2 = expr->v.u.i[0];
1078                     break;
1079                 case REAL_VALUE:
1080                     val->u.r.r1 = val->u.r.r2 = expr->v.u.r[0];
1081                     break;
1082                 case STR_VALUE:
1083                     val->u.s = expr->v.u.s[0];
1084                     break;
1085                 case POS_VALUE:
1086                     copy_rvec(expr->v.u.p->x[0], val->u.x);
1087                     break;
1088                 default:
1089                     gmx_bug("internal error");
1090                     break;
1091             }
1092             _gmx_selelem_free(expr);
1093         }
1094         val = val->next;
1095     }
1096 }
1097
1098 /*!
1099  * \param     pparams List of parameters from the selection parser.
1100  * \param[in] nparam  Number of parameters in \p params.
1101  * \param     params  Array of parameters to parse.
1102  * \param     root    Selection element to which child expressions are added.
1103  * \param[in] scanner Scanner data structure.
1104  * \returns   TRUE if the parameters were parsed successfully, FALSE otherwise.
1105  *
1106  * Initializes the \p params array based on the parameters in \p pparams.
1107  * See the documentation of \c gmx_ana_selparam_t for different options
1108  * available for parsing.
1109  *
1110  * The list \p pparams and any associated values are freed after the parameters
1111  * have been processed, no matter is there was an error or not.
1112  */
1113 gmx_bool
1114 _gmx_sel_parse_params(t_selexpr_param *pparams, int nparam, gmx_ana_selparam_t *params,
1115                       t_selelem *root, void *scanner)
1116 {
1117     t_selexpr_param    *pparam;
1118     gmx_ana_selparam_t *oparam;
1119     gmx_bool                bOk, rc;
1120     int                 i;
1121
1122     /* Check that the value pointers of SPAR_VARNUM parameters are NULL and
1123      * that they are not NULL for other parameters */
1124     bOk = TRUE;
1125     for (i = 0; i < nparam; ++i)
1126     {
1127         if (params[i].val.type != POS_VALUE && (params[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
1128         {
1129             if (params[i].val.u.ptr != NULL)
1130             {
1131                 _gmx_selparser_error("warning: value pointer of parameter '%s' is not NULL\n"
1132                                      "         although it should be for SPAR_VARNUM and SPAR_ATOMVAL parameters\n",
1133                                      params[i].name);
1134             }
1135             if ((params[i].flags & SPAR_VARNUM)
1136                 && (params[i].flags & SPAR_DYNAMIC) && !params[i].nvalptr)
1137             {
1138                 _gmx_selparser_error("error: nvalptr of parameter '%s' is NULL\n"
1139                                      "       but both SPAR_VARNUM and SPAR_DYNAMIC are specified\n",
1140                                      params[i].name);
1141                 bOk = FALSE;
1142             }
1143         }
1144         else
1145         {
1146             if (params[i].val.u.ptr == NULL)
1147             {
1148                 _gmx_selparser_error("error: value pointer of parameter '%s' is NULL\n",
1149                                      params[i].name);
1150                 bOk = FALSE;
1151             }
1152         }
1153     }
1154     if (!bOk)
1155     {
1156         _gmx_selexpr_free_params(pparams);
1157         return FALSE;
1158     }
1159     /* Parse the parameters */
1160     pparam = pparams;
1161     i      = 0;
1162     while (pparam)
1163     {
1164         /* Find the parameter and make some checks */
1165         if (pparam->name != NULL)
1166         {
1167             i = -1;
1168             oparam = gmx_ana_selparam_find(pparam->name, nparam, params);
1169         }
1170         else if (i >= 0)
1171         {
1172             oparam = &params[i];
1173             if (oparam->name != NULL)
1174             {
1175                 oparam = NULL;
1176                 _gmx_selparser_error("too many NULL parameters provided");
1177                 bOk = FALSE;
1178                 goto next_param;
1179             }
1180             ++i;
1181         }
1182         else
1183         {
1184             _gmx_selparser_error("all NULL parameters should appear in the beginning of the list");
1185             bOk = FALSE;
1186             pparam = pparam->next;
1187             continue;
1188         }
1189         if (!oparam)
1190         {
1191             _gmx_selparser_error("unknown parameter '%s' skipped", pparam->name);
1192             bOk = FALSE;
1193             goto next_param;
1194         }
1195         if (oparam->flags & SPAR_SET)
1196         {
1197             _gmx_selparser_error("parameter '%s' set multiple times, extra values skipped", pparam->name);
1198             bOk = FALSE;
1199             goto next_param;
1200         }
1201         oparam->flags |= SPAR_SET;
1202         /* Process the values for the parameter */
1203         convert_const_values(pparam->value);
1204         if (convert_values(pparam->value, oparam->val.type, scanner) != 0)
1205         {
1206             _gmx_selparser_error("invalid value for parameter '%s'", pparam->name);
1207             bOk = FALSE;
1208             goto next_param;
1209         }
1210         if (oparam->val.type == NO_VALUE)
1211         {
1212             rc = parse_values_gmx_bool(pparam->name, pparam->nval, pparam->value, oparam);
1213         }
1214         else if (oparam->flags & SPAR_RANGES)
1215         {
1216             rc = parse_values_range(pparam->nval, pparam->value, oparam);
1217         }
1218         else if (oparam->flags & SPAR_VARNUM)
1219         {
1220             if (pparam->nval == 1 && pparam->value->bExpr)
1221             {
1222                 rc = parse_values_varnum_expr(pparam->nval, pparam->value, oparam, root);
1223             }
1224             else
1225             {
1226                 rc = parse_values_varnum(pparam->nval, pparam->value, oparam, root);
1227             }
1228         }
1229         else if (oparam->flags & SPAR_ENUMVAL)
1230         {
1231             rc = parse_values_enum(pparam->nval, pparam->value, oparam);
1232         }
1233         else
1234         {
1235             rc = parse_values_std(pparam->nval, pparam->value, oparam, root);
1236         }
1237         if (!rc)
1238         {
1239             bOk = FALSE;
1240         }
1241         /* Advance to the next parameter */
1242 next_param:
1243         pparam = pparam->next;
1244     }
1245     /* Check that all required parameters are present */
1246     for (i = 0; i < nparam; ++i)
1247     {
1248         if (!(params[i].flags & SPAR_OPTIONAL) && !(params[i].flags & SPAR_SET))
1249         {
1250             _gmx_selparser_error("required parameter '%s' not specified", params[i].name);
1251             bOk = FALSE;
1252         }
1253     }
1254     
1255     _gmx_selexpr_free_params(pparams);
1256     return bOk;
1257 }