~ubuntu-branches/ubuntu/vivid/libdap/vivid

« back to all changes in this revision

Viewing changes to ConstraintEvaluator.cc

  • Committer: Package Import Robot
  • Author(s): Alastair McKinstry
  • Date: 2013-10-17 22:12:11 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20131017221211-re1r37k4d6wrtmeq
Tags: 3.12.0-1
* New upstream release.
  - No longer need curl-types-remove.patch 
* Add debian/watch file.
* Fix typo in hardening flags; Change  to =all,-pie ; 
  Use DEB_LDFLAGS_MAINT_APPEND. Closes: #697387.
* Enable parallel build. Closes: #723938.
* Depend on libcurl4-gnutls-dev | libcurl-dev. Closes: #722701.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
//
19
19
// You should have received a copy of the GNU Lesser General Public
20
20
// License along with this library; if not, write to the Free Software
21
 
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
21
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
22
//
23
23
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24
24
 
25
25
#include "config.h"
26
26
 
27
 
static char rcsid[] not_used =
28
 
    {"$Id: ConstraintEvaluator.cc 24370 2011-03-28 16:21:32Z jimg $"
29
 
    };
 
27
//#define DODS_DEBUG
30
28
 
 
29
#include "ServerFunctionsList.h"
31
30
#include "ConstraintEvaluator.h"
32
31
 
33
 
#include "ce_functions.h"
34
 
#include "parser.h"
35
32
#include "ce_parser.h"
36
33
#include "debug.h"
 
34
#include "parser.h"
 
35
#include "expr.h"
 
36
//#include "ce_expr.tab.hh"
37
37
 
38
38
struct yy_buffer_state;
39
 
yy_buffer_state *ce_expr_scan_string(const char *str);
40
 
int ce_exprparse(void *arg);
 
39
 
 
40
int ce_exprparse(libdap::ce_parser_arg *arg);
41
41
 
42
42
// Glue routines declared in expr.lex
43
43
void ce_expr_switch_to_buffer(void *new_buffer);
44
44
void ce_expr_delete_buffer(void * buffer);
45
45
void *ce_expr_string(const char *yy_str);
46
46
 
 
47
extern int ce_exprdebug;
 
48
 
47
49
namespace libdap {
48
50
 
49
51
ConstraintEvaluator::ConstraintEvaluator()
50
52
{
51
 
    register_functions(*this);
 
53
    // Functions are now held in BES modules. jhrg 1/30/13
 
54
 
 
55
    // modules load functions to this list; this class searches the list
 
56
    // instead of having it's own copy. This is very similar to the BES'
 
57
    // various List classes, but this one is part of libdap and not the
 
58
    // BES. The List class is a singleton, so each function module can
 
59
    // register it's functions to the list object.
 
60
    d_functions_list = ServerFunctionsList::TheList();
52
61
}
53
62
 
54
63
ConstraintEvaluator::~ConstraintEvaluator()
55
64
{
56
65
    // delete all the constants created by the parser for CE evaluation
57
66
    for (Constants_iter j = constants.begin(); j != constants.end(); j++) {
58
 
        BaseType *btp = *j ;
59
 
        delete btp ; btp = 0;
 
67
        BaseType *btp = *j;
 
68
        delete btp;
 
69
        btp = 0;
60
70
    }
61
71
 
62
72
    for (Clause_iter k = expr.begin(); k != expr.end(); k++) {
63
 
        Clause *cp = *k ;
64
 
        delete cp ; cp = 0;
 
73
        Clause *cp = *k;
 
74
        delete cp;
 
75
        cp = 0;
65
76
    }
66
77
}
67
78
 
68
79
/** Returns the first clause in a parsed constraint expression. */
69
 
ConstraintEvaluator::Clause_iter
70
 
ConstraintEvaluator::clause_begin()
 
80
ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_begin()
71
81
{
72
 
    return expr.begin() ;
 
82
    return expr.begin();
73
83
}
74
84
 
75
85
/** Returns a reference to the end of the list of clauses in a parsed
76
 
    constraint expression. It does not reference the last clause */
77
 
ConstraintEvaluator::Clause_iter
78
 
ConstraintEvaluator::clause_end()
 
86
 constraint expression. It does not reference the last clause */
 
87
ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_end()
79
88
{
80
 
    return expr.end() ;
 
89
    return expr.end();
81
90
}
82
91
 
83
92
/** Returns the value of the indicated clause of a constraint
84
 
    expression. */
85
 
bool
86
 
ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
 
93
 expression. */
 
94
bool ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
87
95
{
88
96
    if (expr.empty())
89
 
        throw InternalErr(__FILE__, __LINE__,
90
 
                          "There are no CE clauses for *this* DDS object.");
 
97
        throw InternalErr(__FILE__, __LINE__, "There are no CE clauses for *this* DDS object.");
91
98
 
92
99
    return (*iter)->value(dds);
93
100
}
94
101
 
95
102
/** @brief Add a clause to a constraint expression.
96
103
 
97
 
    This function adds an operator clause to the constraint
98
 
    expression.
 
104
 This function adds an operator clause to the constraint
 
105
 expression.
99
106
 
100
 
    @param op An integer indicating the operator in use.  These
101
 
    values are generated by \c bison.
102
 
    @param arg1 A pointer to the argument on the left side of the
103
 
    operator.
104
 
    @param arg2 A pointer to a list of the arguments on the right
105
 
    side of the operator.
106
 
*/
107
 
void
108
 
ConstraintEvaluator::append_clause(int op, rvalue *arg1, rvalue_list *arg2)
 
107
 @param op An integer indicating the operator in use.  These
 
108
 values are generated by \c bison.
 
109
 @param arg1 A pointer to the argument on the left side of the
 
110
 operator.
 
111
 @param arg2 A pointer to a list of the arguments on the right
 
112
 side of the operator.
 
113
 */
 
114
void ConstraintEvaluator::append_clause(int op, rvalue *arg1, rvalue_list *arg2)
109
115
{
110
116
    Clause *clause = new Clause(op, arg1, arg2);
111
117
 
114
120
 
115
121
/** @brief Add a clause to a constraint expression.
116
122
 
117
 
    This function adds a boolean function clause to the constraint
118
 
    expression.
 
123
 This function adds a boolean function clause to the constraint
 
124
 expression.
119
125
 
120
 
    @param func A pointer to a boolean function from the list of
121
 
    supported functions.
122
 
    @param args A list of arguments to that function.
123
 
*/
124
 
void
125
 
ConstraintEvaluator::append_clause(bool_func func, rvalue_list *args)
 
126
 @param func A pointer to a boolean function from the list of
 
127
 supported functions.
 
128
 @param args A list of arguments to that function.
 
129
 */
 
130
void ConstraintEvaluator::append_clause(bool_func func, rvalue_list *args)
126
131
{
127
132
    Clause *clause = new Clause(func, args);
128
133
 
131
136
 
132
137
/** @brief Add a clause to a constraint expression.
133
138
 
134
 
    This function adds a real-valued (BaseType) function clause to
135
 
    the constraint expression.
 
139
 This function adds a real-valued (BaseType) function clause to
 
140
 the constraint expression.
136
141
 
137
 
    @param func A pointer to a BaseType function from the list of
138
 
    supported functions.
139
 
    @param args A list of arguments to that function.
140
 
*/
141
 
void
142
 
ConstraintEvaluator::append_clause(btp_func func, rvalue_list *args)
 
142
 @param func A pointer to a BaseType function from the list of
 
143
 supported functions.
 
144
 @param args A list of arguments to that function.
 
145
 */
 
146
void ConstraintEvaluator::append_clause(btp_func func, rvalue_list *args)
143
147
{
144
148
    Clause *clause = new Clause(func, args);
145
149
 
147
151
}
148
152
 
149
153
/** The Constraint Evaluator maintains a list of BaseType pointers for all the
150
 
         constants that the constraint expression parser generates. These objects
151
 
         are deleted by the Constraint Evaluator destructor. Note that there are no
152
 
         list accessors; these constants are never accessed from the list. The list
153
 
         is simply a convenient way to make sure the constants are disposed of
154
 
         properly.
 
154
 constants that the constraint expression parser generates. These objects
 
155
 are deleted by the Constraint Evaluator destructor. Note that there are no
 
156
 list accessors; these constants are never accessed from the list. The list
 
157
 is simply a convenient way to make sure the constants are disposed of
 
158
 properly.
155
159
 */
156
 
void
157
 
ConstraintEvaluator::append_constant(BaseType *btp)
 
160
void ConstraintEvaluator::append_constant(BaseType *btp)
158
161
{
159
162
    constants.push_back(btp);
160
163
}
161
164
 
162
 
class func_name_is
163
 
{
 
165
// This code was removed when I switched from CE having it's own internal
 
166
// list of functions to using an external list.
 
167
#if 0
 
168
class func_name_is {
164
169
private:
165
170
    const string d_name;
166
171
 
167
172
public:
168
 
    func_name_is(const string &name): d_name(name)
169
 
    {}
 
173
    func_name_is(const string &name) :
 
174
            d_name(name)
 
175
    {
 
176
    }
170
177
    bool operator()(const ConstraintEvaluator::function f)
171
178
    {
172
179
        return f.name == d_name;
174
181
};
175
182
 
176
183
/** The Constraint Evaluator carries with it a list of external functions it
177
 
    can use while evaluate a constraint expression. If a constraint contains
178
 
    any of these functions, the entries in the list allow the parser to evaluate
179
 
    it. The functions are of three types: those that return boolean values,
180
 
    those that return real (also called BaseType) values, and those that
181
 
    are applied during evaluation of the projection for side effect
182
 
 
183
 
    @note The add_function() methods will replace a function of the same name,
184
 
    so it is possible to overwrite functions in specific handlers if the
185
 
    handler need special behavior to implement one of the standard functions.
186
 
 
187
 
    @see ce_functions for the standard functions
188
 
 
189
 
    These methods are used to manipulate this list of known
190
 
    external functions.
191
 
 
192
 
    @name External Function Accessors
193
 
*/
 
184
 can use while evaluate a constraint expression. If a constraint contains
 
185
 any of these functions, the entries in the list allow the parser to evaluate
 
186
 it. The functions are of three types: those that return boolean values,
 
187
 those that return real (also called BaseType) values, and those that
 
188
 are applied during evaluation of the projection for side effect
 
189
 
 
190
 @note The add_function() methods will replace a function of the same name,
 
191
 so it is possible to overwrite functions in specific handlers if the
 
192
 handler need special behavior to implement one of the standard functions.
 
193
 
 
194
 @see ce_functions for the standard functions
 
195
 
 
196
 These methods are used to manipulate this list of known
 
197
 external functions.
 
198
 
 
199
 @name External Function Accessors
 
200
 */
194
201
//@{
195
202
/** @brief Add a boolean function to the list. */
196
 
void
197
 
ConstraintEvaluator::add_function(const string &name, bool_func f)
 
203
void ConstraintEvaluator::add_function(const string &name, bool_func f)
198
204
{
199
205
    functions.remove_if(func_name_is(name));
200
206
    function func(name, f);
202
208
}
203
209
 
204
210
/** @brief Add a BaseType function to the list. */
205
 
void
206
 
ConstraintEvaluator::add_function(const string &name, btp_func f)
 
211
void ConstraintEvaluator::add_function(const string &name, btp_func f)
207
212
{
208
213
    functions.remove_if(func_name_is(name));
209
214
    function func(name, f);
211
216
}
212
217
 
213
218
/** @brief Add a projection function to the list. */
214
 
void
215
 
ConstraintEvaluator::add_function(const string &name, proj_func f)
 
219
void ConstraintEvaluator::add_function(const string &name, proj_func f)
216
220
{
217
221
    functions.remove_if(func_name_is(name));
218
222
    function func(name, f);
219
223
    functions.push_back(func);
220
224
}
 
225
#endif
221
226
 
222
227
/** @brief Find a Boolean function with a given name in the function list. */
223
 
bool
224
 
ConstraintEvaluator::find_function(const string &name, bool_func *f) const
 
228
bool ConstraintEvaluator::find_function(const string &name, bool_func *f) const
225
229
{
 
230
    return d_functions_list->find_function(name, f);
 
231
#if 0
226
232
    if (functions.empty())
227
233
        return false;
228
234
 
233
239
    }
234
240
 
235
241
    return false;
 
242
#endif
236
243
}
237
244
 
238
245
/** @brief Find a BaseType function with a given name in the function list. */
239
 
bool
240
 
ConstraintEvaluator::find_function(const string &name, btp_func *f) const
 
246
bool ConstraintEvaluator::find_function(const string &name, btp_func *f) const
241
247
{
 
248
    return d_functions_list->find_function(name, f);
 
249
#if 0
242
250
    if (functions.empty())
243
251
        return false;
244
252
 
249
257
    }
250
258
 
251
259
    return false;
 
260
#endif
252
261
}
253
262
 
254
263
/** @brief Find a projection function with a given name in the function list. */
255
 
bool
256
 
ConstraintEvaluator::find_function(const string &name, proj_func *f) const
 
264
bool ConstraintEvaluator::find_function(const string &name, proj_func *f) const
257
265
{
 
266
    return d_functions_list->find_function(name, f);
 
267
#if 0
258
268
    if (functions.empty())
259
269
        return false;
260
270
 
264
274
        }
265
275
 
266
276
    return false;
 
277
#endif
267
278
}
268
279
//@}
269
280
 
270
281
/** @brief Does the current constraint expression return a BaseType
271
 
    pointer?
272
 
    This method does not evaluate the clause, it provides information to the
273
 
    evaluator regarding _how_ to evaluate the clause.
274
 
    @return True if the clause is a function that returns a BaseType* and
275
 
    false otherwise */
276
 
bool
277
 
ConstraintEvaluator::functional_expression()
 
282
 pointer?
 
283
 This method does not evaluate the clause, it provides information to the
 
284
 evaluator regarding _how_ to evaluate the clause.
 
285
 @return True if the clause is a function that returns a BaseType* and
 
286
 false otherwise
 
287
 @deprecated
 
288
 */
 
289
bool ConstraintEvaluator::functional_expression()
278
290
{
279
291
    if (expr.empty())
280
292
        return false;
281
293
 
282
 
    Clause *cp = expr[0] ;
 
294
    Clause *cp = expr[0];
283
295
    return cp->value_clause();
284
296
}
285
297
 
286
 
/** @brief Evaluate a function-valued constraint expression. */
 
298
/** @brief Evaluate a function-valued constraint expression.
 
299
 * @deprecated
 
300
 * */
287
301
BaseType *
288
302
ConstraintEvaluator::eval_function(DDS &dds, const string &)
289
303
{
290
304
    if (expr.size() != 1)
291
 
        throw InternalErr(__FILE__, __LINE__,
292
 
                          "The length of the list of CE clauses is not 1.");
 
305
        throw InternalErr(__FILE__, __LINE__, "The length of the list of CE clauses is not 1.");
293
306
 
294
 
    Clause *cp = expr[0] ;
 
307
    Clause *cp = expr[0];
295
308
    BaseType *result;
296
309
    if (cp->value(dds, &result))
297
310
        return result;
299
312
        return NULL;
300
313
}
301
314
 
302
 
/** @brief Does the current constraint expression return a DDS pointer?
303
 
 
304
 
    This method does not evaluate the clauses, it provides information to the
305
 
    evaluator regarding _how_ to evaluate the clause.
306
 
 
307
 
    @note Added for libdap 3.11
308
 
 
309
 
    @return True if the clause is a function that returns a DDS* and
310
 
    false otherwise */
 
315
/** @brief Does the current constraint expression contain function clauses
 
316
 
 
317
 This method does not evaluate the clauses, it provides information to the
 
318
 evaluator regarding _how_ to evaluate the clause.
 
319
 
 
320
 @note Added for libdap 3.11
 
321
 
 
322
 @return True if the current constraint contains function clauses,
 
323
 otherwise returns False */
311
324
bool ConstraintEvaluator::function_clauses()
312
325
{
313
326
    if (expr.empty())
314
 
        return false;
 
327
        return false;
315
328
 
316
329
    for (unsigned int i = 0; i < expr.size(); ++i) {
317
 
        Clause *cp = expr[i];
318
 
        if (!cp->value_clause())
319
 
            return false;
 
330
        Clause *cp = expr[i];
 
331
        if (!cp->value_clause())
 
332
            return false;
320
333
    }
321
334
 
322
335
    return true;
323
336
}
324
337
 
325
338
/** @brief Evaluate a function-valued constraint expression that contains
326
 
    several function calls.
327
 
 
328
 
    This method can be called for any function-valued constraint expression.
329
 
    Unlike eval_function(), it will package the return value in a new DDS
330
 
    object. The server should free this object once it has been serialized
331
 
    and sent.
332
 
 
333
 
    @note While there is another type of function that can appear in a CE (a
334
 
    'projection function') those are evaluated by the ce parser - they are used
335
 
    to insert new variables into the DDS as a side effect of CE evaluation.
336
 
    That kind of function can never appear here; these are all functions that
337
 
    return BaseType pointers.
338
 
 
339
 
    @note Added for libdap 3.11 */
 
339
 several function calls.
 
340
 
 
341
 This method can be called for any function-valued constraint expression.
 
342
 Unlike eval_function(), it will package the return value in a new DDS
 
343
 object. The server should free this object once it has been serialized
 
344
 and sent.
 
345
 
 
346
 @note While there is another type of function that can appear in a CE (a
 
347
 'projection function') those are evaluated by the ce parser - they are used
 
348
 to insert new variables into the DDS as a side effect of CE evaluation.
 
349
 That kind of function can never appear here; these are all functions that
 
350
 return BaseType pointers.
 
351
 
 
352
 @note Added for libdap 3.11 */
340
353
DDS *
341
354
ConstraintEvaluator::eval_function_clauses(DDS &dds)
342
355
{
343
356
    if (expr.empty())
344
 
        throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
 
357
        throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
345
358
 
346
359
    DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
347
360
    for (unsigned int i = 0; i < expr.size(); ++i) {
348
 
        Clause *cp = expr[i];
349
 
        BaseType *result;
350
 
        if (cp->value(dds, &result)) {
351
 
            result->set_send_p(true);
352
 
            fdds->add_var(result);
353
 
        }
354
 
        else {
355
 
                delete fdds;
356
 
            throw Error("A function was called but failed to return a value.");
357
 
        }
 
361
        Clause *cp = expr[i];
 
362
        BaseType *result;
 
363
        if (cp->value(dds, &result)) {
 
364
            // This is correct: The function must allocate the memory for the result
 
365
            // variable. 11/30/12 jhrg
 
366
            fdds->add_var_nocopy(result);
 
367
        }
 
368
        else {
 
369
            delete fdds;
 
370
            throw Error("A function was called but failed to return a value.");
 
371
        }
358
372
    }
359
373
 
360
374
    return fdds;
361
375
}
362
376
 
363
377
/** @brief Evaluate a function-valued constraint expression that contains
364
 
    several function calls. Takes and returns a DataDDS.
365
 
 
366
 
    @see ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
367
 
    @note Added for libdap 3.11 */
 
378
 several function calls. Takes and returns a DataDDS.
 
379
 
 
380
 @todo Change this so that the new variables are inserted into the
 
381
 original DDS object - this will allow constraints that mix simple
 
382
 projections with function calls. The function is responsible for
 
383
 setting the new variable's read_p property and this 'evaluator'
 
384
 sets the send_p property. The original variables would have to be
 
385
 removed from the original DDS for this to work or the names of
 
386
 the new variables would have to not clash with the original variables'
 
387
 names.
 
388
 
 
389
 @see ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
 
390
 @note Added for libdap 3.11 */
368
391
DataDDS *
369
392
ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
370
393
{
371
394
    if (expr.empty())
372
 
        throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
 
395
        throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
373
396
 
374
 
    DataDDS *fdds = new DataDDS(dds.get_factory(),
375
 
                                "function_result_" + dds.get_dataset_name(),
376
 
                                dds.get_version(), dds.get_protocol());
 
397
    DataDDS *fdds = new DataDDS(dds.get_factory(), "function_result_" + dds.get_dataset_name(), dds.get_version(),
 
398
            dds.get_protocol());
377
399
 
378
400
    for (unsigned int i = 0; i < expr.size(); ++i) {
379
 
        Clause *cp = expr[i];
380
 
        BaseType *result;
381
 
        if (cp->value(dds, &result)) {
382
 
            result->set_send_p(true);
383
 
            fdds->add_var(result);
384
 
        }
385
 
        else {
386
 
                delete fdds;
387
 
            throw Error("A function was called but failed to return a value.");
388
 
        }
 
401
        Clause *cp = expr[i];
 
402
        BaseType *result;
 
403
        if (cp->value(dds, &result)) {
 
404
            fdds->add_var_nocopy(result);
 
405
        }
 
406
        else {
 
407
            delete fdds;
 
408
            throw Error("A function was called but failed to return a value.");
 
409
        }
389
410
    }
390
411
 
391
412
    return fdds;
392
413
}
393
414
 
394
415
/** @brief Does the current constraint expression return a boolean value? */
395
 
bool
396
 
ConstraintEvaluator::boolean_expression()
 
416
bool ConstraintEvaluator::boolean_expression()
397
417
{
398
418
    if (expr.empty())
399
419
        return false;
406
426
    return boolean;
407
427
}
408
428
 
409
 
 
410
429
/** @brief Evaluate a boolean-valued constraint expression.
411
 
    This is main method for the evaluator ans is called by the
412
 
    BaseType::serialize() methods.
 
430
 This is main method for the evaluator ans is called by the
 
431
 BaseType::serialize() methods.
413
432
 
414
 
    @param dds Use these variables when evaluating the expressions.
415
 
    @param dataset This string is passed to the read() methods.
416
 
    @return True if the expression is true, false otherwise. */
417
 
bool
418
 
ConstraintEvaluator::eval_selection(DDS &dds, const string &)
 
433
 @param dds Use these variables when evaluating the expressions.
 
434
 @param dataset This string is passed to the read() methods.
 
435
 @return True if the expression is true, false otherwise. */
 
436
bool ConstraintEvaluator::eval_selection(DDS &dds, const string &)
419
437
{
420
438
    if (expr.empty()) {
421
439
        DBG(cerr << "No selection recorded" << endl);
432
450
    for (Clause_iter i = expr.begin(); i != expr.end() && result; i++) {
433
451
        // A selection expression *must* contain only boolean clauses!
434
452
        if (!((*i)->boolean_clause()))
435
 
            throw InternalErr(__FILE__, __LINE__,
436
 
                              "A selection expression must contain only boolean clauses.");
 
453
            throw InternalErr(__FILE__, __LINE__, "A selection expression must contain only boolean clauses.");
437
454
        result = result && (*i)->value(dds);
438
455
    }
439
456
 
442
459
 
443
460
/** @brief Parse the constraint expression given the current DDS.
444
461
 
445
 
    Evaluate the constraint expression; return the value of the expression.
446
 
    As a side effect, mark the DDS so that BaseType's mfuncs can be used to
447
 
    correctly read the variable's value and send it to the client.
 
462
 Evaluate the constraint expression; return the value of the expression.
 
463
 As a side effect, mark the DDS so that BaseType's mfuncs can be used to
 
464
 correctly read the variable's value and send it to the client.
448
465
 
449
 
    @param constraint A string containing the constraint expression.
450
 
    @param dds The DDS that provides the environment within which the
451
 
    constraint is evaluated.
452
 
    @exception Throws Error if the constraint does not parse. */
453
 
void
454
 
ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
 
466
 @param constraint A string containing the constraint expression.
 
467
 @param dds The DDS that provides the environment within which the
 
468
 constraint is evaluated.
 
469
 @exception Throws Error if the constraint does not parse. */
 
470
void ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
455
471
{
456
472
    void *buffer = ce_expr_string(constraint.c_str());
 
473
 
 
474
    // Toggle this to debug the parser. A last resort...
 
475
    ce_exprdebug = false;
 
476
 
457
477
    ce_expr_switch_to_buffer(buffer);
458
478
 
459
479
    ce_parser_arg arg(this, &dds);
460
480
 
461
481
    // For all errors, exprparse will throw Error.
462
 
    ce_exprparse((void *)&arg);
463
 
 
464
 
    ce_expr_delete_buffer(buffer);
 
482
    try {
 
483
        ce_exprparse(&arg);
 
484
        ce_expr_delete_buffer(buffer);
 
485
    }
 
486
    catch (...) {
 
487
        // Make sure to remove the buffer when there's an error
 
488
        ce_expr_delete_buffer(buffer);
 
489
        throw;
 
490
    }
465
491
}
466
492
 
467
493
} // namespace libdap