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