1 |
26 |
unneback |
//{{{ Banner
|
2 |
|
|
|
3 |
|
|
//============================================================================
|
4 |
|
|
//
|
5 |
|
|
// value.cxx
|
6 |
|
|
//
|
7 |
|
|
// Implementation of value-related CDL classes.
|
8 |
|
|
//
|
9 |
|
|
//============================================================================
|
10 |
|
|
//####COPYRIGHTBEGIN####
|
11 |
|
|
//
|
12 |
|
|
// ----------------------------------------------------------------------------
|
13 |
|
|
// Copyright (C) 2002 Bart Veer
|
14 |
|
|
// Copyright (C) 1999, 2000, 2001 Red Hat, Inc.
|
15 |
|
|
//
|
16 |
|
|
// This file is part of the eCos host tools.
|
17 |
|
|
//
|
18 |
|
|
// This program is free software; you can redistribute it and/or modify it
|
19 |
|
|
// under the terms of the GNU General Public License as published by the Free
|
20 |
|
|
// Software Foundation; either version 2 of the License, or (at your option)
|
21 |
|
|
// any later version.
|
22 |
|
|
//
|
23 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
24 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
25 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
26 |
|
|
// more details.
|
27 |
|
|
//
|
28 |
|
|
// You should have received a copy of the GNU General Public License along with
|
29 |
|
|
// this program; if not, write to the Free Software Foundation, Inc.,
|
30 |
|
|
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
31 |
|
|
//
|
32 |
|
|
// ----------------------------------------------------------------------------
|
33 |
|
|
//
|
34 |
|
|
//####COPYRIGHTEND####
|
35 |
|
|
//============================================================================
|
36 |
|
|
//#####DESCRIPTIONBEGIN####
|
37 |
|
|
//
|
38 |
|
|
// Author(s): bartv
|
39 |
|
|
// Contact(s): bartv
|
40 |
|
|
// Date: 1999/07/12
|
41 |
|
|
// Version: 0.02
|
42 |
|
|
//
|
43 |
|
|
//####DESCRIPTIONEND####
|
44 |
|
|
//============================================================================
|
45 |
|
|
|
46 |
|
|
//}}}
|
47 |
|
|
//{{{ #include's
|
48 |
|
|
|
49 |
|
|
// ----------------------------------------------------------------------------
|
50 |
|
|
#include "cdlconfig.h"
|
51 |
|
|
|
52 |
|
|
// Get the infrastructure types, assertions, tracing and similar
|
53 |
|
|
// facilities.
|
54 |
|
|
#include <cyg/infra/cyg_ass.h>
|
55 |
|
|
#include <cyg/infra/cyg_trac.h>
|
56 |
|
|
|
57 |
|
|
// <cdlcore.hxx> defines everything implemented in this module.
|
58 |
|
|
// It implicitly supplies <string>, <vector> and <map> because
|
59 |
|
|
// the class definitions rely on these headers.
|
60 |
|
|
#include <cdlcore.hxx>
|
61 |
|
|
|
62 |
|
|
//}}}
|
63 |
|
|
|
64 |
|
|
//{{{ Statics
|
65 |
|
|
|
66 |
|
|
// ----------------------------------------------------------------------------
|
67 |
|
|
CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlValue);
|
68 |
|
|
CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlListValue);
|
69 |
|
|
CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlValuableBody);
|
70 |
|
|
|
71 |
|
|
//}}}
|
72 |
|
|
//{{{ CdlSimpleValue class
|
73 |
|
|
|
74 |
|
|
//{{{ Constructors
|
75 |
|
|
|
76 |
|
|
// ----------------------------------------------------------------------------
|
77 |
|
|
|
78 |
|
|
CdlSimpleValue::CdlSimpleValue()
|
79 |
|
|
{
|
80 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: default constructor");
|
81 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
82 |
|
|
|
83 |
|
|
value = "0";
|
84 |
|
|
int_value = 0;
|
85 |
|
|
double_value = 0.0;
|
86 |
|
|
valid_flags = int_valid | double_valid | string_valid;
|
87 |
|
|
format = CdlValueFormat_Default;
|
88 |
|
|
|
89 |
|
|
CYG_REPORT_RETURN();
|
90 |
|
|
}
|
91 |
|
|
|
92 |
|
|
CdlSimpleValue::CdlSimpleValue(std::string val)
|
93 |
|
|
{
|
94 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: string constructor");
|
95 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
96 |
|
|
|
97 |
|
|
value = val;
|
98 |
|
|
int_value = 0;
|
99 |
|
|
double_value = 0.0;
|
100 |
|
|
valid_flags = string_valid;
|
101 |
|
|
format = CdlValueFormat_Default;
|
102 |
|
|
|
103 |
|
|
CYG_REPORT_RETURN();
|
104 |
|
|
}
|
105 |
|
|
|
106 |
|
|
CdlSimpleValue::CdlSimpleValue(cdl_int val)
|
107 |
|
|
{
|
108 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: int constructor");
|
109 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
110 |
|
|
|
111 |
|
|
value = "0";
|
112 |
|
|
int_value = val;
|
113 |
|
|
double_value = 0.0;
|
114 |
|
|
valid_flags = int_valid;
|
115 |
|
|
format = CdlValueFormat_Default;
|
116 |
|
|
|
117 |
|
|
CYG_REPORT_RETURN();
|
118 |
|
|
}
|
119 |
|
|
|
120 |
|
|
CdlSimpleValue::CdlSimpleValue(double val)
|
121 |
|
|
{
|
122 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: double constructor");
|
123 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
124 |
|
|
|
125 |
|
|
value = "0";
|
126 |
|
|
int_value = 0;
|
127 |
|
|
double_value = val;
|
128 |
|
|
valid_flags = double_valid;
|
129 |
|
|
format = CdlValueFormat_Default;
|
130 |
|
|
|
131 |
|
|
CYG_REPORT_RETURN();
|
132 |
|
|
}
|
133 |
|
|
|
134 |
|
|
CdlSimpleValue::CdlSimpleValue(bool val)
|
135 |
|
|
{
|
136 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: bool constructor");
|
137 |
|
|
CYG_REPORT_FUNCARG2XV(this, val);
|
138 |
|
|
|
139 |
|
|
value = (val) ? "1" : "0";
|
140 |
|
|
int_value = (val) ? 1 : 0;
|
141 |
|
|
double_value = 0.0;
|
142 |
|
|
valid_flags = string_valid | int_valid;
|
143 |
|
|
format = CdlValueFormat_Default;
|
144 |
|
|
|
145 |
|
|
CYG_REPORT_RETURN();
|
146 |
|
|
}
|
147 |
|
|
|
148 |
|
|
CdlSimpleValue::CdlSimpleValue(const CdlSimpleValue& original)
|
149 |
|
|
{
|
150 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: copy constructor");
|
151 |
|
|
CYG_REPORT_FUNCARG2XV(this, &original);
|
152 |
|
|
|
153 |
|
|
value = original.value;
|
154 |
|
|
int_value = original.int_value;
|
155 |
|
|
double_value = original.double_value;
|
156 |
|
|
valid_flags = original.valid_flags;
|
157 |
|
|
format = original.format;
|
158 |
|
|
|
159 |
|
|
CYG_REPORT_RETURN();
|
160 |
|
|
}
|
161 |
|
|
|
162 |
|
|
//}}}
|
163 |
|
|
//{{{ Destructor
|
164 |
|
|
|
165 |
|
|
// ----------------------------------------------------------------------------
|
166 |
|
|
|
167 |
|
|
CdlSimpleValue::~CdlSimpleValue()
|
168 |
|
|
{
|
169 |
|
|
CYG_REPORT_FUNCNAME("CdlsimpleValue:: destructor");
|
170 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
171 |
|
|
|
172 |
|
|
value = "";
|
173 |
|
|
int_value = 0;
|
174 |
|
|
double_value = 0.0;
|
175 |
|
|
valid_flags = 0;
|
176 |
|
|
format = CdlValueFormat_Default;
|
177 |
|
|
|
178 |
|
|
CYG_REPORT_RETURN();
|
179 |
|
|
}
|
180 |
|
|
|
181 |
|
|
//}}}
|
182 |
|
|
//{{{ Assignment operators
|
183 |
|
|
|
184 |
|
|
// ----------------------------------------------------------------------------
|
185 |
|
|
|
186 |
|
|
CdlSimpleValue&
|
187 |
|
|
CdlSimpleValue::operator=(const CdlSimpleValue& original)
|
188 |
|
|
{
|
189 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: assignment operator");
|
190 |
|
|
CYG_REPORT_FUNCARG2XV(this, &original);
|
191 |
|
|
|
192 |
|
|
if (this != &original) {
|
193 |
|
|
value = original.value;
|
194 |
|
|
int_value = original.int_value;
|
195 |
|
|
double_value = original.double_value;
|
196 |
|
|
valid_flags = original.valid_flags;
|
197 |
|
|
format = original.format;
|
198 |
|
|
}
|
199 |
|
|
|
200 |
|
|
CYG_REPORT_RETURN();
|
201 |
|
|
return *this;
|
202 |
|
|
}
|
203 |
|
|
|
204 |
|
|
CdlSimpleValue&
|
205 |
|
|
CdlSimpleValue::operator=(std::string val)
|
206 |
|
|
{
|
207 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: string assignment");
|
208 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
209 |
|
|
|
210 |
|
|
value = val;
|
211 |
|
|
int_value = 0;
|
212 |
|
|
double_value = 0.0;
|
213 |
|
|
valid_flags = string_valid;
|
214 |
|
|
format = CdlValueFormat_Default;
|
215 |
|
|
|
216 |
|
|
CYG_REPORT_RETURN();
|
217 |
|
|
return *this;
|
218 |
|
|
}
|
219 |
|
|
|
220 |
|
|
CdlSimpleValue&
|
221 |
|
|
CdlSimpleValue::operator=(cdl_int val)
|
222 |
|
|
{
|
223 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: integer assignment");
|
224 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
225 |
|
|
|
226 |
|
|
value = "";
|
227 |
|
|
int_value = val;
|
228 |
|
|
double_value = 0.0;
|
229 |
|
|
valid_flags = int_valid;
|
230 |
|
|
format = CdlValueFormat_Default;
|
231 |
|
|
|
232 |
|
|
CYG_REPORT_RETURN();
|
233 |
|
|
return *this;
|
234 |
|
|
}
|
235 |
|
|
|
236 |
|
|
CdlSimpleValue&
|
237 |
|
|
CdlSimpleValue::operator=(double val)
|
238 |
|
|
{
|
239 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: double assignment");
|
240 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
241 |
|
|
|
242 |
|
|
value = "";
|
243 |
|
|
int_value = 0;
|
244 |
|
|
double_value = val;
|
245 |
|
|
valid_flags = double_valid;
|
246 |
|
|
format = CdlValueFormat_Default;
|
247 |
|
|
|
248 |
|
|
CYG_REPORT_RETURN();
|
249 |
|
|
return *this;
|
250 |
|
|
}
|
251 |
|
|
|
252 |
|
|
// ----------------------------------------------------------------------------
|
253 |
|
|
// Converting a boolean into a simple value. This is sufficiently common
|
254 |
|
|
// to warrant its own member function, and in addition it avoids
|
255 |
|
|
// ambiguity when assigning 0.
|
256 |
|
|
|
257 |
|
|
CdlSimpleValue&
|
258 |
|
|
CdlSimpleValue::operator=(bool val)
|
259 |
|
|
{
|
260 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: bool assignment");
|
261 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
262 |
|
|
|
263 |
|
|
value = (val) ? "1" : "0";
|
264 |
|
|
int_value = (val) ? 1 : 0;
|
265 |
|
|
double_value = 0.0;
|
266 |
|
|
valid_flags = string_valid | int_valid;
|
267 |
|
|
format = CdlValueFormat_Default;
|
268 |
|
|
|
269 |
|
|
CYG_REPORT_RETURN();
|
270 |
|
|
return *this;
|
271 |
|
|
}
|
272 |
|
|
|
273 |
|
|
//}}}
|
274 |
|
|
//{{{ CdlValuable -> CdlSimpleValue
|
275 |
|
|
|
276 |
|
|
// ----------------------------------------------------------------------------
|
277 |
|
|
// This routine bridges the gap between the full data held in the CdlValuable
|
278 |
|
|
// object and the basic information needed for expression evaluation.
|
279 |
|
|
|
280 |
|
|
void
|
281 |
|
|
CdlSimpleValue::eval_valuable(CdlEvalContext& context, CdlValuable valuable, CdlSimpleValue& result)
|
282 |
|
|
{
|
283 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue:: valuable assignment");
|
284 |
|
|
CYG_REPORT_FUNCARG3XV(&context, valuable, &result);
|
285 |
|
|
CYG_PRECONDITION_CLASSC(valuable);
|
286 |
|
|
|
287 |
|
|
// If the valuable is not currently active then its value is
|
288 |
|
|
// always zero for the purposes of expression evaluation.
|
289 |
|
|
// FIXME: this check should be on a per-transaction basis.
|
290 |
|
|
if (((0 != context.transaction) && !context.transaction->is_active(valuable)) ||
|
291 |
|
|
((0 == context.transaction) && !valuable->is_active())) {
|
292 |
|
|
|
293 |
|
|
result.value = "0";
|
294 |
|
|
result.int_value = 0;
|
295 |
|
|
result.double_value = 0.0;
|
296 |
|
|
result.valid_flags = string_valid | int_valid;
|
297 |
|
|
result.format = CdlValueFormat_Default;
|
298 |
|
|
CYG_REPORT_RETURN();
|
299 |
|
|
return;
|
300 |
|
|
}
|
301 |
|
|
|
302 |
|
|
// Get hold of the underlying CdlValue object
|
303 |
|
|
const CdlValue& val = (0 != context.transaction) ?
|
304 |
|
|
context.transaction->get_whole_value(valuable) : valuable->get_whole_value();
|
305 |
|
|
|
306 |
|
|
// Otherwise the value depends on the flavor.
|
307 |
|
|
switch(val.get_flavor()) {
|
308 |
|
|
case CdlValueFlavor_None :
|
309 |
|
|
{
|
310 |
|
|
// This could be treated as an error, but since valuables with flavor
|
311 |
|
|
// none are permanently enabled a constant "1" is a better result.
|
312 |
|
|
result.value = "1";
|
313 |
|
|
result.int_value = 1;
|
314 |
|
|
result.double_value = 0.0;
|
315 |
|
|
result.valid_flags = string_valid | int_valid;
|
316 |
|
|
result.format = CdlValueFormat_Default;
|
317 |
|
|
break;
|
318 |
|
|
}
|
319 |
|
|
case CdlValueFlavor_Bool :
|
320 |
|
|
{
|
321 |
|
|
bool enabled = val.is_enabled();
|
322 |
|
|
result.value = (enabled) ? "1" : "0";
|
323 |
|
|
result.int_value = (enabled) ? 1 : 0;
|
324 |
|
|
result.double_value = 0.0;
|
325 |
|
|
result.valid_flags = string_valid | int_valid;
|
326 |
|
|
result.format = CdlValueFormat_Default;
|
327 |
|
|
break;
|
328 |
|
|
}
|
329 |
|
|
case CdlValueFlavor_BoolData :
|
330 |
|
|
{
|
331 |
|
|
if (!val.is_enabled()) {
|
332 |
|
|
|
333 |
|
|
result.value = "0";
|
334 |
|
|
result.int_value = 0;
|
335 |
|
|
result.double_value = 0.0;
|
336 |
|
|
result.valid_flags = string_valid | int_valid;
|
337 |
|
|
result.format = CdlValueFormat_Default;
|
338 |
|
|
|
339 |
|
|
} else {
|
340 |
|
|
|
341 |
|
|
// Just use a copy constructor, let the compiler optimise things.
|
342 |
|
|
result = val.get_simple_value();
|
343 |
|
|
}
|
344 |
|
|
break;
|
345 |
|
|
}
|
346 |
|
|
case CdlValueFlavor_Data :
|
347 |
|
|
{
|
348 |
|
|
// Just like BoolData, but with no need to check the enabled flag.
|
349 |
|
|
result = val.get_simple_value();
|
350 |
|
|
break;
|
351 |
|
|
}
|
352 |
|
|
default:
|
353 |
|
|
{
|
354 |
|
|
CYG_FAIL("Valuable object with an unknown flavor encountered.");
|
355 |
|
|
}
|
356 |
|
|
}
|
357 |
|
|
|
358 |
|
|
CYG_REPORT_RETURN();
|
359 |
|
|
}
|
360 |
|
|
|
361 |
|
|
//}}}
|
362 |
|
|
//{{{ Getting the value
|
363 |
|
|
|
364 |
|
|
// ----------------------------------------------------------------------------
|
365 |
|
|
// Some of these calls involve conversion operators.
|
366 |
|
|
|
367 |
|
|
std::string
|
368 |
|
|
CdlSimpleValue::get_value() const
|
369 |
|
|
{
|
370 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue::get_value");
|
371 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
372 |
|
|
|
373 |
|
|
if (!(valid_flags & string_valid)) {
|
374 |
|
|
if (valid_flags & int_valid) {
|
375 |
|
|
Cdl::integer_to_string(int_value, value, format);
|
376 |
|
|
} else if (valid_flags & double_valid) {
|
377 |
|
|
Cdl::double_to_string(double_value, value, format);
|
378 |
|
|
} else {
|
379 |
|
|
CYG_FAIL("Attempt to use uninitialized SimpleValue");
|
380 |
|
|
}
|
381 |
|
|
valid_flags |= string_valid;
|
382 |
|
|
}
|
383 |
|
|
|
384 |
|
|
CYG_REPORT_RETURN();
|
385 |
|
|
return value;
|
386 |
|
|
}
|
387 |
|
|
|
388 |
|
|
bool
|
389 |
|
|
CdlSimpleValue::has_integer_value() const
|
390 |
|
|
{
|
391 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlSimpleValue::has_integer_value", "result %d");
|
392 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
393 |
|
|
|
394 |
|
|
if (!(valid_flags & (int_valid | int_invalid))) {
|
395 |
|
|
if (valid_flags & double_valid) {
|
396 |
|
|
if (Cdl::double_to_integer(double_value, int_value)) {
|
397 |
|
|
valid_flags |= int_valid;
|
398 |
|
|
} else {
|
399 |
|
|
valid_flags |= int_invalid;
|
400 |
|
|
}
|
401 |
|
|
} else if (valid_flags & string_valid) {
|
402 |
|
|
if (Cdl::string_to_integer(value, int_value)) {
|
403 |
|
|
valid_flags |= int_valid;
|
404 |
|
|
} else {
|
405 |
|
|
valid_flags |= int_invalid;
|
406 |
|
|
}
|
407 |
|
|
} else {
|
408 |
|
|
CYG_FAIL("Attempt to use uninitialized SimpleValue");
|
409 |
|
|
}
|
410 |
|
|
}
|
411 |
|
|
|
412 |
|
|
bool result = (valid_flags & int_valid);
|
413 |
|
|
CYG_REPORT_RETVAL(result);
|
414 |
|
|
return result;
|
415 |
|
|
}
|
416 |
|
|
|
417 |
|
|
cdl_int
|
418 |
|
|
CdlSimpleValue::get_integer_value() const
|
419 |
|
|
{
|
420 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlsimpleValue::get_integer_value", "result %ld");
|
421 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
422 |
|
|
|
423 |
|
|
cdl_int result = 0;
|
424 |
|
|
if ((valid_flags & int_valid) || has_integer_value()) {
|
425 |
|
|
result = int_value;
|
426 |
|
|
}
|
427 |
|
|
|
428 |
|
|
CYG_REPORT_RETVAL((int) result);
|
429 |
|
|
return result;
|
430 |
|
|
}
|
431 |
|
|
|
432 |
|
|
bool
|
433 |
|
|
CdlSimpleValue::has_double_value() const
|
434 |
|
|
{
|
435 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlSimpleValue::has_double_value", "result %d");
|
436 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
437 |
|
|
|
438 |
|
|
if (!(valid_flags & (double_valid | double_invalid))) {
|
439 |
|
|
if (valid_flags & int_valid) {
|
440 |
|
|
Cdl::integer_to_double(int_value, double_value);
|
441 |
|
|
valid_flags |= double_valid;
|
442 |
|
|
} else if (valid_flags & string_valid) {
|
443 |
|
|
if (Cdl::string_to_double(value, double_value)) {
|
444 |
|
|
valid_flags |= double_valid;
|
445 |
|
|
} else {
|
446 |
|
|
valid_flags |= double_invalid;
|
447 |
|
|
}
|
448 |
|
|
} else {
|
449 |
|
|
CYG_FAIL("Attempt to use uninitialized SimpleValue");
|
450 |
|
|
}
|
451 |
|
|
}
|
452 |
|
|
bool result = (valid_flags & double_valid);
|
453 |
|
|
CYG_REPORT_RETVAL(result);
|
454 |
|
|
return result;
|
455 |
|
|
}
|
456 |
|
|
|
457 |
|
|
double
|
458 |
|
|
CdlSimpleValue::get_double_value() const
|
459 |
|
|
{
|
460 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue::get_double_value");
|
461 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
462 |
|
|
|
463 |
|
|
double result = 0.0;
|
464 |
|
|
if ((valid_flags & double_valid) || has_double_value()) {
|
465 |
|
|
result = double_value;
|
466 |
|
|
}
|
467 |
|
|
|
468 |
|
|
CYG_REPORT_RETURN();
|
469 |
|
|
return result;
|
470 |
|
|
}
|
471 |
|
|
|
472 |
|
|
bool
|
473 |
|
|
CdlSimpleValue::get_bool_value() const
|
474 |
|
|
{
|
475 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlSimpleValue::get_bool_value", "result %d");
|
476 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
477 |
|
|
|
478 |
|
|
bool result = false;
|
479 |
|
|
if (valid_flags & int_valid) {
|
480 |
|
|
if (0 != int_value) {
|
481 |
|
|
result = true;
|
482 |
|
|
}
|
483 |
|
|
} else if (valid_flags & double_valid) {
|
484 |
|
|
// Leave it to the compiler to decide what is valid
|
485 |
|
|
result = double_value;
|
486 |
|
|
} else if (valid_flags & string_valid) {
|
487 |
|
|
// string_to_bool copes with "1", "true", and a few other cases.
|
488 |
|
|
// If the current value does not match any of these then
|
489 |
|
|
// true corresponds to a non-empty string.
|
490 |
|
|
if (!Cdl::string_to_bool(value, result)) {
|
491 |
|
|
if ("" == value) {
|
492 |
|
|
result = false;
|
493 |
|
|
} else {
|
494 |
|
|
result = true;
|
495 |
|
|
}
|
496 |
|
|
}
|
497 |
|
|
} else {
|
498 |
|
|
// No value defined, default to false.
|
499 |
|
|
result = false;
|
500 |
|
|
}
|
501 |
|
|
|
502 |
|
|
CYG_REPORT_RETVAL(result);
|
503 |
|
|
return result;
|
504 |
|
|
}
|
505 |
|
|
|
506 |
|
|
//}}}
|
507 |
|
|
//{{{ Updating the value
|
508 |
|
|
|
509 |
|
|
// ----------------------------------------------------------------------------
|
510 |
|
|
// Normally the assignment operators will be used for this instead.
|
511 |
|
|
|
512 |
|
|
void
|
513 |
|
|
CdlSimpleValue::set_value(std::string val, CdlValueFormat new_format)
|
514 |
|
|
{
|
515 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue::set_value (string)");
|
516 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
517 |
|
|
|
518 |
|
|
value = val;
|
519 |
|
|
int_value = 0;
|
520 |
|
|
double_value = 0.0;
|
521 |
|
|
valid_flags = string_valid;
|
522 |
|
|
format = new_format;
|
523 |
|
|
}
|
524 |
|
|
|
525 |
|
|
|
526 |
|
|
void
|
527 |
|
|
CdlSimpleValue::set_integer_value(cdl_int val, CdlValueFormat new_format)
|
528 |
|
|
{
|
529 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue::set_integer_value");
|
530 |
|
|
CYG_REPORT_FUNCARG2XV(this, (int) val);
|
531 |
|
|
|
532 |
|
|
value = "";
|
533 |
|
|
int_value = val;
|
534 |
|
|
double_value = 0.0;
|
535 |
|
|
valid_flags = int_valid;
|
536 |
|
|
format = new_format;
|
537 |
|
|
|
538 |
|
|
CYG_REPORT_RETURN();
|
539 |
|
|
}
|
540 |
|
|
|
541 |
|
|
|
542 |
|
|
void
|
543 |
|
|
CdlSimpleValue::set_double_value(double val, CdlValueFormat new_format)
|
544 |
|
|
{
|
545 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue::set_double_value");
|
546 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
547 |
|
|
|
548 |
|
|
value = "";
|
549 |
|
|
int_value = 0;
|
550 |
|
|
double_value = val;
|
551 |
|
|
valid_flags = double_valid;
|
552 |
|
|
format = new_format;
|
553 |
|
|
|
554 |
|
|
CYG_REPORT_RETURN();
|
555 |
|
|
}
|
556 |
|
|
|
557 |
|
|
//}}}
|
558 |
|
|
//{{{ Value format support
|
559 |
|
|
|
560 |
|
|
// ----------------------------------------------------------------------------
|
561 |
|
|
|
562 |
|
|
CdlValueFormat
|
563 |
|
|
CdlSimpleValue::get_value_format() const
|
564 |
|
|
{
|
565 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlSimpleValue::get_value_format", "result %d");
|
566 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
567 |
|
|
|
568 |
|
|
CdlValueFormat result = format;
|
569 |
|
|
CYG_REPORT_RETVAL(result);
|
570 |
|
|
return result;
|
571 |
|
|
}
|
572 |
|
|
|
573 |
|
|
void
|
574 |
|
|
CdlSimpleValue::set_value_format(CdlValueFormat new_format)
|
575 |
|
|
{
|
576 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue::set_value_format");
|
577 |
|
|
CYG_REPORT_FUNCARG2XV(this, new_format);
|
578 |
|
|
|
579 |
|
|
format = new_format;
|
580 |
|
|
|
581 |
|
|
CYG_REPORT_RETURN();
|
582 |
|
|
}
|
583 |
|
|
|
584 |
|
|
void
|
585 |
|
|
CdlSimpleValue::set_value_format(CdlSimpleValue& other_val)
|
586 |
|
|
{
|
587 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue::set_value_format (simple val)");
|
588 |
|
|
CYG_REPORT_FUNCARG2XV(this, &other_val);
|
589 |
|
|
|
590 |
|
|
format = other_val.format;
|
591 |
|
|
|
592 |
|
|
CYG_REPORT_RETURN();
|
593 |
|
|
}
|
594 |
|
|
|
595 |
|
|
// This gets used for binary operators, e.g. A + B
|
596 |
|
|
// If A has a non-default format then that gets used.
|
597 |
|
|
// Otherwise B's format gets used, which may or may not be default.
|
598 |
|
|
//
|
599 |
|
|
// e.g. 0x1000 + 4 -> 0x1004
|
600 |
|
|
// 10 + 0x100 -> 0x10A
|
601 |
|
|
// 10 + 32 -> 42
|
602 |
|
|
|
603 |
|
|
void
|
604 |
|
|
CdlSimpleValue::set_value_format(CdlSimpleValue& val1, CdlSimpleValue& val2)
|
605 |
|
|
{
|
606 |
|
|
CYG_REPORT_FUNCNAME("CdlSimpleValue::set_value_format");
|
607 |
|
|
CYG_REPORT_FUNCARG3XV(this, &val1, &val2);
|
608 |
|
|
|
609 |
|
|
format = (CdlValueFormat_Default != val1.format) ? val1.format : val2.format;
|
610 |
|
|
|
611 |
|
|
CYG_REPORT_RETURN();
|
612 |
|
|
}
|
613 |
|
|
|
614 |
|
|
//}}}
|
615 |
|
|
//{{{ Comparison operators
|
616 |
|
|
|
617 |
|
|
// ----------------------------------------------------------------------------
|
618 |
|
|
|
619 |
|
|
bool
|
620 |
|
|
CdlSimpleValue::operator==(const CdlSimpleValue& other) const
|
621 |
|
|
{
|
622 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlSimpleValue:: operator==", "result %d");
|
623 |
|
|
CYG_REPORT_FUNCARG2XV(this, &other);
|
624 |
|
|
|
625 |
|
|
bool result = false;
|
626 |
|
|
|
627 |
|
|
if (has_integer_value()) {
|
628 |
|
|
if (other.has_integer_value()) {
|
629 |
|
|
cdl_int val1 = get_integer_value();
|
630 |
|
|
cdl_int val2 = other.get_integer_value();
|
631 |
|
|
result = (val1 == val2);
|
632 |
|
|
}
|
633 |
|
|
} else if (has_double_value()) {
|
634 |
|
|
if (other.has_double_value()) {
|
635 |
|
|
double val1 = get_double_value();
|
636 |
|
|
double val2 = other.get_double_value();
|
637 |
|
|
result = (val1 == val2);
|
638 |
|
|
}
|
639 |
|
|
} else {
|
640 |
|
|
std::string val1 = get_value();
|
641 |
|
|
std::string val2 = other.get_value();
|
642 |
|
|
result = (val1 == val2);
|
643 |
|
|
}
|
644 |
|
|
|
645 |
|
|
CYG_REPORT_RETVAL(result);
|
646 |
|
|
return result;
|
647 |
|
|
}
|
648 |
|
|
|
649 |
|
|
bool
|
650 |
|
|
CdlSimpleValue::operator!=(const CdlSimpleValue& other) const
|
651 |
|
|
{
|
652 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlSimpleValue:: operator!=", "result %d");
|
653 |
|
|
CYG_REPORT_FUNCARG2XV(this, &other);
|
654 |
|
|
|
655 |
|
|
bool result = true;
|
656 |
|
|
if (has_integer_value()) {
|
657 |
|
|
if (other.has_integer_value()) {
|
658 |
|
|
cdl_int val1 = get_integer_value();
|
659 |
|
|
cdl_int val2 = other.get_integer_value();
|
660 |
|
|
result = (val1 != val2);
|
661 |
|
|
}
|
662 |
|
|
} else if (has_double_value()) {
|
663 |
|
|
if (other.has_double_value()) {
|
664 |
|
|
double val1 = get_double_value();
|
665 |
|
|
double val2 = other.get_double_value();
|
666 |
|
|
result = (val1 != val2);
|
667 |
|
|
}
|
668 |
|
|
} else {
|
669 |
|
|
std::string val1 = get_value();
|
670 |
|
|
std::string val2 = other.get_value();
|
671 |
|
|
result = (val1 != val2);
|
672 |
|
|
}
|
673 |
|
|
|
674 |
|
|
|
675 |
|
|
CYG_REPORT_RETVAL(result);
|
676 |
|
|
return result;
|
677 |
|
|
}
|
678 |
|
|
|
679 |
|
|
//}}}
|
680 |
|
|
|
681 |
|
|
//}}}
|
682 |
|
|
//{{{ CdlValue class
|
683 |
|
|
|
684 |
|
|
// ----------------------------------------------------------------------------
|
685 |
|
|
// This should really be a class static constant, but VC++ does not implement
|
686 |
|
|
// that part of the language. A constant here avoids the need for lots of
|
687 |
|
|
// occurrences of 4 throughout the value-related routines.
|
688 |
|
|
|
689 |
|
|
static const int CdlValue_number_of_sources = 4;
|
690 |
|
|
|
691 |
|
|
//{{{ Constructors
|
692 |
|
|
|
693 |
|
|
// ----------------------------------------------------------------------------
|
694 |
|
|
// The default flavor depends on the type of entity being created. For
|
695 |
|
|
// example CDL options are boolean by default, but packages are booldata.
|
696 |
|
|
// The intelligence to do the right thing lives in set_flavor().
|
697 |
|
|
|
698 |
|
|
CdlValue::CdlValue(CdlValueFlavor flavor_arg)
|
699 |
|
|
{
|
700 |
|
|
CYG_REPORT_FUNCNAME("CdlValue:: constructor");
|
701 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
702 |
|
|
|
703 |
|
|
current_source = CdlValueSource_Default;
|
704 |
|
|
source_valid[CdlValueSource_Default] = true;
|
705 |
|
|
source_valid[CdlValueSource_Inferred] = false;
|
706 |
|
|
source_valid[CdlValueSource_Wizard] = false;
|
707 |
|
|
source_valid[CdlValueSource_User] = false;
|
708 |
|
|
enabled[CdlValueSource_Default] = false;
|
709 |
|
|
enabled[CdlValueSource_Inferred] = false;
|
710 |
|
|
enabled[CdlValueSource_Wizard] = false;
|
711 |
|
|
enabled[CdlValueSource_User] = false;
|
712 |
|
|
|
713 |
|
|
// The SimpleValues will initialize themselves.
|
714 |
|
|
|
715 |
|
|
cdlvalue_cookie = CdlValue_Magic;
|
716 |
|
|
CYGDBG_MEMLEAK_CONSTRUCTOR();
|
717 |
|
|
|
718 |
|
|
// This cannot happen until after the object is valid.
|
719 |
|
|
set_flavor(flavor_arg);
|
720 |
|
|
|
721 |
|
|
CYG_POSTCONDITION_THISC();
|
722 |
|
|
CYG_REPORT_RETURN();
|
723 |
|
|
}
|
724 |
|
|
|
725 |
|
|
// ----------------------------------------------------------------------------
|
726 |
|
|
// Copy constructor. This is not really required, a default
|
727 |
|
|
// member-wise copy would be fine and more efficient, but it would
|
728 |
|
|
// lose tracing and assertion.
|
729 |
|
|
|
730 |
|
|
CdlValue::CdlValue(const CdlValue& original)
|
731 |
|
|
{
|
732 |
|
|
CYG_REPORT_FUNCNAME("CdlValue:: copy constructor");
|
733 |
|
|
CYG_REPORT_FUNCARG2XV(this, &original);
|
734 |
|
|
CYG_INVARIANT_CLASSOC(CdlValue, original);
|
735 |
|
|
|
736 |
|
|
flavor = original.flavor;
|
737 |
|
|
current_source = original.current_source;
|
738 |
|
|
for (int i = 0; i < CdlValue_number_of_sources; i++) {
|
739 |
|
|
source_valid[i] = original.source_valid[i];
|
740 |
|
|
enabled[i] = original.enabled[i];
|
741 |
|
|
values[i] = original.values[i];
|
742 |
|
|
}
|
743 |
|
|
|
744 |
|
|
cdlvalue_cookie = CdlValue_Magic;
|
745 |
|
|
CYGDBG_MEMLEAK_CONSTRUCTOR();
|
746 |
|
|
|
747 |
|
|
CYG_POSTCONDITION_THISC();
|
748 |
|
|
CYG_REPORT_RETURN();
|
749 |
|
|
}
|
750 |
|
|
|
751 |
|
|
// ----------------------------------------------------------------------------
|
752 |
|
|
// Assignment operator. Again this is not required, the default would be
|
753 |
|
|
// fine and more efficient, but tracing and assertions are good things.
|
754 |
|
|
|
755 |
|
|
CdlValue& CdlValue::operator=(const CdlValue& original)
|
756 |
|
|
{
|
757 |
|
|
CYG_REPORT_FUNCNAME("CdlValue:: assignment operator");
|
758 |
|
|
CYG_REPORT_FUNCARG2XV(this, &original);
|
759 |
|
|
CYG_INVARIANT_CLASSOC(CdlValue, original);
|
760 |
|
|
|
761 |
|
|
if (this != &original) {
|
762 |
|
|
flavor = original.flavor;
|
763 |
|
|
current_source = original.current_source;
|
764 |
|
|
for (int i = 0; i < CdlValue_number_of_sources; i++) {
|
765 |
|
|
source_valid[i] = original.source_valid[i];
|
766 |
|
|
enabled[i] = original.enabled[i];
|
767 |
|
|
values[i] = original.values[i];
|
768 |
|
|
}
|
769 |
|
|
}
|
770 |
|
|
|
771 |
|
|
cdlvalue_cookie = CdlValue_Magic;
|
772 |
|
|
CYG_POSTCONDITION_THISC();
|
773 |
|
|
CYG_REPORT_RETURN();
|
774 |
|
|
return *this;
|
775 |
|
|
}
|
776 |
|
|
|
777 |
|
|
//}}}
|
778 |
|
|
//{{{ Destructor
|
779 |
|
|
|
780 |
|
|
// ----------------------------------------------------------------------------
|
781 |
|
|
|
782 |
|
|
CdlValue::~CdlValue()
|
783 |
|
|
{
|
784 |
|
|
CYG_REPORT_FUNCNAME("CdlValue:: destructor");
|
785 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
786 |
|
|
CYG_PRECONDITION_THISC();
|
787 |
|
|
|
788 |
|
|
cdlvalue_cookie = CdlValue_Invalid;
|
789 |
|
|
flavor = CdlValueFlavor_Invalid;
|
790 |
|
|
current_source = CdlValueSource_Invalid;
|
791 |
|
|
for (int i = 0; i < CdlValue_number_of_sources; i++) {
|
792 |
|
|
source_valid[i] = false;
|
793 |
|
|
enabled[i] = false;
|
794 |
|
|
// The CdlSimpleValue array will take care of itself.
|
795 |
|
|
}
|
796 |
|
|
CYGDBG_MEMLEAK_DESTRUCTOR();
|
797 |
|
|
|
798 |
|
|
CYG_REPORT_RETURN();
|
799 |
|
|
}
|
800 |
|
|
|
801 |
|
|
//}}}
|
802 |
|
|
//{{{ check_this()
|
803 |
|
|
|
804 |
|
|
// ----------------------------------------------------------------------------
|
805 |
|
|
bool
|
806 |
|
|
CdlValue::check_this(cyg_assert_class_zeal zeal) const
|
807 |
|
|
{
|
808 |
|
|
if (CdlValue_Magic != cdlvalue_cookie) {
|
809 |
|
|
return false;
|
810 |
|
|
}
|
811 |
|
|
CYGDBG_MEMLEAK_CHECKTHIS();
|
812 |
|
|
|
813 |
|
|
if (!source_valid[CdlValueSource_Default]) {
|
814 |
|
|
return false;
|
815 |
|
|
}
|
816 |
|
|
|
817 |
|
|
if ((CdlValueFlavor_None == flavor) || (CdlValueFlavor_Data == flavor)) {
|
818 |
|
|
for (int i = 0; i < CdlValue_number_of_sources; i++) {
|
819 |
|
|
if (!enabled[i]) {
|
820 |
|
|
return false;
|
821 |
|
|
}
|
822 |
|
|
}
|
823 |
|
|
}
|
824 |
|
|
for (int i = 0; i < CdlValue_number_of_sources; i++) {
|
825 |
|
|
if (source_valid[i]) {
|
826 |
|
|
if (!values[i].check_this(zeal)) {
|
827 |
|
|
return false;
|
828 |
|
|
}
|
829 |
|
|
}
|
830 |
|
|
}
|
831 |
|
|
|
832 |
|
|
return true;
|
833 |
|
|
}
|
834 |
|
|
|
835 |
|
|
//}}}
|
836 |
|
|
//{{{ Flavor manipulation
|
837 |
|
|
|
838 |
|
|
// ----------------------------------------------------------------------------
|
839 |
|
|
// Get hold of the current flavor.
|
840 |
|
|
CdlValueFlavor
|
841 |
|
|
CdlValue::get_flavor(void) const
|
842 |
|
|
{
|
843 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValue::get_flavor", "result %d");
|
844 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
845 |
|
|
CYG_PRECONDITION_THISC();
|
846 |
|
|
|
847 |
|
|
CdlValueFlavor result = flavor;
|
848 |
|
|
CYG_REPORT_RETVAL(result);
|
849 |
|
|
return result;
|
850 |
|
|
}
|
851 |
|
|
|
852 |
|
|
// ----------------------------------------------------------------------------
|
853 |
|
|
// set_flavor() may be invoked once or twice for a given entity. The first
|
854 |
|
|
// time is from inside the constructor with the default flavor for this
|
855 |
|
|
// particular class of entity. It may then be called again if the
|
856 |
|
|
// entity has a "flavor" property that overrides this. All old data
|
857 |
|
|
// will be lost, so evaluating a default value etc. should be done after
|
858 |
|
|
// the call to set_flavor(), and there should be no subsequent calls to
|
859 |
|
|
// set_flavor().
|
860 |
|
|
|
861 |
|
|
void
|
862 |
|
|
CdlValue::set_flavor(CdlValueFlavor flavor_arg)
|
863 |
|
|
{
|
864 |
|
|
CYG_REPORT_FUNCNAME("CdlValue:: set_flavor");
|
865 |
|
|
CYG_REPORT_FUNCARG2XV(this, flavor_arg);
|
866 |
|
|
|
867 |
|
|
// No precondition here, set_flavor() is called from inside the constructor
|
868 |
|
|
CYG_PRECONDITIONC((CdlValueFlavor_None == flavor_arg) || \
|
869 |
|
|
(CdlValueFlavor_Bool == flavor_arg) || \
|
870 |
|
|
(CdlValueFlavor_BoolData == flavor_arg) || \
|
871 |
|
|
(CdlValueFlavor_Data == flavor_arg));
|
872 |
|
|
|
873 |
|
|
flavor = flavor_arg;
|
874 |
|
|
switch(flavor) {
|
875 |
|
|
case CdlValueFlavor_None :
|
876 |
|
|
{
|
877 |
|
|
// All value sources are enabled, but "default" remains
|
878 |
|
|
// the only valid one. All data parts are set to "1",
|
879 |
|
|
// although that should not really matter.
|
880 |
|
|
enabled[CdlValueSource_Default] = true;
|
881 |
|
|
enabled[CdlValueSource_Inferred] = true;
|
882 |
|
|
enabled[CdlValueSource_Wizard] = true;
|
883 |
|
|
enabled[CdlValueSource_User] = true;
|
884 |
|
|
|
885 |
|
|
CdlSimpleValue simple_val((cdl_int) 1);
|
886 |
|
|
values[CdlValueSource_Default] = simple_val;
|
887 |
|
|
values[CdlValueSource_Inferred] = simple_val;
|
888 |
|
|
values[CdlValueSource_Wizard] = simple_val;
|
889 |
|
|
values[CdlValueSource_User] = simple_val;
|
890 |
|
|
break;
|
891 |
|
|
}
|
892 |
|
|
|
893 |
|
|
case CdlValueFlavor_Bool :
|
894 |
|
|
{
|
895 |
|
|
// All value sources start out as disabled, but with a
|
896 |
|
|
// constant data part of 1. Users can only control the
|
897 |
|
|
// boolean part. This is consistent with header file
|
898 |
|
|
// generation: no #define is generated for disabled
|
899 |
|
|
// options, but if the option is enabled then the data
|
900 |
|
|
// part will be used for the value.
|
901 |
|
|
enabled[CdlValueSource_Default] = false;
|
902 |
|
|
enabled[CdlValueSource_Inferred] = false;
|
903 |
|
|
enabled[CdlValueSource_Wizard] = false;
|
904 |
|
|
enabled[CdlValueSource_User] = false;
|
905 |
|
|
|
906 |
|
|
// BLV - keep the data part at 0 for now. There is too
|
907 |
|
|
// much confusion in the code between value as a string
|
908 |
|
|
// representation, and value as the data part of the
|
909 |
|
|
// bool/data pair. This needs to be fixed, but it requires
|
910 |
|
|
// significant API changes.
|
911 |
|
|
#if 0
|
912 |
|
|
CdlSimpleValue simple_val(cdl_int(1));
|
913 |
|
|
#else
|
914 |
|
|
CdlSimpleValue simple_val(cdl_int(0));
|
915 |
|
|
#endif
|
916 |
|
|
values[CdlValueSource_Default] = simple_val;
|
917 |
|
|
values[CdlValueSource_Inferred] = simple_val;
|
918 |
|
|
values[CdlValueSource_Wizard] = simple_val;
|
919 |
|
|
values[CdlValueSource_User] = simple_val;
|
920 |
|
|
break;
|
921 |
|
|
}
|
922 |
|
|
|
923 |
|
|
case CdlValueFlavor_BoolData :
|
924 |
|
|
{
|
925 |
|
|
// All value sources start out as disabled, just like
|
926 |
|
|
// booleans. Nothing is known about the data part.
|
927 |
|
|
enabled[CdlValueSource_Default] = false;
|
928 |
|
|
enabled[CdlValueSource_Inferred] = false;
|
929 |
|
|
enabled[CdlValueSource_Wizard] = false;
|
930 |
|
|
enabled[CdlValueSource_User] = false;
|
931 |
|
|
break;
|
932 |
|
|
}
|
933 |
|
|
|
934 |
|
|
case CdlValueFlavor_Data :
|
935 |
|
|
{
|
936 |
|
|
// All value sources start out as enabled, and cannot be
|
937 |
|
|
// changed. Nothing is known about the data part.
|
938 |
|
|
enabled[CdlValueSource_Default] = true;
|
939 |
|
|
enabled[CdlValueSource_Inferred] = true;
|
940 |
|
|
enabled[CdlValueSource_Wizard] = true;
|
941 |
|
|
enabled[CdlValueSource_User] = true;
|
942 |
|
|
break;
|
943 |
|
|
}
|
944 |
|
|
|
945 |
|
|
default :
|
946 |
|
|
break;
|
947 |
|
|
}
|
948 |
|
|
|
949 |
|
|
CYG_REPORT_RETURN();
|
950 |
|
|
}
|
951 |
|
|
|
952 |
|
|
//}}}
|
953 |
|
|
//{{{ Source manipulation
|
954 |
|
|
|
955 |
|
|
// ----------------------------------------------------------------------------
|
956 |
|
|
|
957 |
|
|
void
|
958 |
|
|
CdlValue::set_source(CdlValueSource source)
|
959 |
|
|
{
|
960 |
|
|
CYG_REPORT_FUNCNAME("CdlValue::set_source");
|
961 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
962 |
|
|
CYG_INVARIANT_THISC(CdlValue);
|
963 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source <= CdlValue_number_of_sources));
|
964 |
|
|
CYG_PRECONDITIONC(source_valid[source]);
|
965 |
|
|
|
966 |
|
|
current_source = source;
|
967 |
|
|
|
968 |
|
|
CYG_REPORT_RETURN();
|
969 |
|
|
}
|
970 |
|
|
|
971 |
|
|
CdlValueSource
|
972 |
|
|
CdlValue::get_source(void) const
|
973 |
|
|
{
|
974 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValue::get_source", "source %d");
|
975 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
976 |
|
|
CYG_PRECONDITION_THISC();
|
977 |
|
|
|
978 |
|
|
CdlValueSource result = current_source;
|
979 |
|
|
CYG_REPORT_RETVAL(result);
|
980 |
|
|
return result;
|
981 |
|
|
}
|
982 |
|
|
|
983 |
|
|
bool
|
984 |
|
|
CdlValue::has_source(CdlValueSource source) const
|
985 |
|
|
{
|
986 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValue::has_source", "result %d");
|
987 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
988 |
|
|
CYG_PRECONDITION_THISC();
|
989 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
990 |
|
|
|
991 |
|
|
bool result = source_valid[source];
|
992 |
|
|
CYG_REPORT_RETVAL(result);
|
993 |
|
|
return result;
|
994 |
|
|
}
|
995 |
|
|
|
996 |
|
|
// ----------------------------------------------------------------------------
|
997 |
|
|
// Invalidate a specific source. If that source happens to be the current one,
|
998 |
|
|
// switch to the highest-priority valid source.
|
999 |
|
|
|
1000 |
|
|
void
|
1001 |
|
|
CdlValue::invalidate_source(CdlValueSource source)
|
1002 |
|
|
{
|
1003 |
|
|
CYG_REPORT_FUNCNAME("CdlValue::invalidate_source");
|
1004 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
1005 |
|
|
CYG_PRECONDITION_THISC();
|
1006 |
|
|
CYG_PRECONDITIONC(CdlValueSource_Default != source);
|
1007 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1008 |
|
|
|
1009 |
|
|
if (CdlValueSource_Default != source) {
|
1010 |
|
|
source_valid[source] = false;
|
1011 |
|
|
if (current_source == source) {
|
1012 |
|
|
if (source_valid[CdlValueSource_User]) {
|
1013 |
|
|
current_source = CdlValueSource_User;
|
1014 |
|
|
} else if (source_valid[CdlValueSource_Wizard]) {
|
1015 |
|
|
current_source = CdlValueSource_Wizard;
|
1016 |
|
|
} else if (source_valid[CdlValueSource_Inferred]) {
|
1017 |
|
|
current_source = CdlValueSource_Inferred;
|
1018 |
|
|
} else {
|
1019 |
|
|
current_source = CdlValueSource_Default;
|
1020 |
|
|
}
|
1021 |
|
|
}
|
1022 |
|
|
}
|
1023 |
|
|
|
1024 |
|
|
CYG_POSTCONDITIONC(source_valid[current_source]);
|
1025 |
|
|
}
|
1026 |
|
|
|
1027 |
|
|
//}}}
|
1028 |
|
|
//{{{ Retrieving the data
|
1029 |
|
|
|
1030 |
|
|
// ----------------------------------------------------------------------------
|
1031 |
|
|
// Check the enabled flag for the appropriate source. The specified source
|
1032 |
|
|
// is normally provided by a default argument CdlValueSource_Current, which
|
1033 |
|
|
// 99.9...% of the time is what we are after.
|
1034 |
|
|
//
|
1035 |
|
|
// Note that this member can be used even for entities of flavor none
|
1036 |
|
|
// and data, and the result will be true. However it is not legal to
|
1037 |
|
|
// disable such entities.
|
1038 |
|
|
|
1039 |
|
|
bool
|
1040 |
|
|
CdlValue::is_enabled(CdlValueSource source) const
|
1041 |
|
|
{
|
1042 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValue::is_enabled", "enabled %d");
|
1043 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
1044 |
|
|
CYG_PRECONDITION_THISC();
|
1045 |
|
|
|
1046 |
|
|
if (CdlValueSource_Current == source) {
|
1047 |
|
|
source = current_source;
|
1048 |
|
|
}
|
1049 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1050 |
|
|
CYG_PRECONDITIONC(source_valid[source]);
|
1051 |
|
|
|
1052 |
|
|
bool result = enabled[source];
|
1053 |
|
|
CYG_REPORT_RETVAL(result);
|
1054 |
|
|
return result;
|
1055 |
|
|
}
|
1056 |
|
|
|
1057 |
|
|
// ----------------------------------------------------------------------------
|
1058 |
|
|
// Access to the value field.
|
1059 |
|
|
|
1060 |
|
|
std::string
|
1061 |
|
|
CdlValue::get_value(CdlValueSource source) const
|
1062 |
|
|
{
|
1063 |
|
|
CYG_REPORT_FUNCNAME("CdlValue::get_value");
|
1064 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
1065 |
|
|
CYG_PRECONDITION_THISC();
|
1066 |
|
|
|
1067 |
|
|
if (CdlValueSource_Current == source) {
|
1068 |
|
|
source = current_source;
|
1069 |
|
|
}
|
1070 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1071 |
|
|
CYG_PRECONDITIONC(source_valid[source]);
|
1072 |
|
|
|
1073 |
|
|
std::string result = values[source].get_value();
|
1074 |
|
|
CYG_REPORT_RETURN();
|
1075 |
|
|
return result;
|
1076 |
|
|
}
|
1077 |
|
|
|
1078 |
|
|
bool
|
1079 |
|
|
CdlValue::has_integer_value(CdlValueSource source) const
|
1080 |
|
|
{
|
1081 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValue::has_integer_value", "result %d");
|
1082 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
1083 |
|
|
CYG_INVARIANT_THISC(CdlValue);
|
1084 |
|
|
|
1085 |
|
|
if (CdlValueSource_Current == source) {
|
1086 |
|
|
source = current_source;
|
1087 |
|
|
}
|
1088 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1089 |
|
|
CYG_PRECONDITIONC(source_valid[source]);
|
1090 |
|
|
|
1091 |
|
|
bool result = values[source].has_integer_value();
|
1092 |
|
|
CYG_REPORT_RETVAL(result);
|
1093 |
|
|
return result;
|
1094 |
|
|
}
|
1095 |
|
|
|
1096 |
|
|
bool
|
1097 |
|
|
CdlValue::has_double_value(CdlValueSource source) const
|
1098 |
|
|
{
|
1099 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValue::has_value", "result %d");
|
1100 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
1101 |
|
|
CYG_INVARIANT_THISC(CdlValue);
|
1102 |
|
|
|
1103 |
|
|
if (CdlValueSource_Current == source) {
|
1104 |
|
|
source = current_source;
|
1105 |
|
|
}
|
1106 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1107 |
|
|
CYG_PRECONDITIONC(source_valid[source]);
|
1108 |
|
|
|
1109 |
|
|
bool result = values[source].has_double_value();
|
1110 |
|
|
CYG_REPORT_RETVAL(result);
|
1111 |
|
|
return result;
|
1112 |
|
|
}
|
1113 |
|
|
|
1114 |
|
|
cdl_int
|
1115 |
|
|
CdlValue::get_integer_value(CdlValueSource source) const
|
1116 |
|
|
{
|
1117 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValue::get_integer_value", "value %ld");
|
1118 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
1119 |
|
|
CYG_PRECONDITION_THISC();
|
1120 |
|
|
|
1121 |
|
|
if (CdlValueSource_Current == source) {
|
1122 |
|
|
source = current_source;
|
1123 |
|
|
}
|
1124 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1125 |
|
|
CYG_PRECONDITIONC(source_valid[source]);
|
1126 |
|
|
|
1127 |
|
|
cdl_int result = values[source].get_integer_value();
|
1128 |
|
|
CYG_REPORT_RETVAL(result);
|
1129 |
|
|
return result;
|
1130 |
|
|
}
|
1131 |
|
|
|
1132 |
|
|
double
|
1133 |
|
|
CdlValue::get_double_value(CdlValueSource source) const
|
1134 |
|
|
{
|
1135 |
|
|
CYG_REPORT_FUNCNAME("CdlValue::get_double_value");
|
1136 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
1137 |
|
|
CYG_PRECONDITION_THISC();
|
1138 |
|
|
|
1139 |
|
|
if (CdlValueSource_Current == source) {
|
1140 |
|
|
source = current_source;
|
1141 |
|
|
}
|
1142 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1143 |
|
|
CYG_PRECONDITIONC(source_valid[source]);
|
1144 |
|
|
|
1145 |
|
|
double result = values[source].get_double_value();
|
1146 |
|
|
CYG_REPORT_RETURN();
|
1147 |
|
|
return result;
|
1148 |
|
|
}
|
1149 |
|
|
|
1150 |
|
|
CdlSimpleValue
|
1151 |
|
|
CdlValue::get_simple_value(CdlValueSource source) const
|
1152 |
|
|
{
|
1153 |
|
|
CYG_REPORT_FUNCNAME("CdlValue::get_simple_value");
|
1154 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
1155 |
|
|
CYG_PRECONDITION_THISC();
|
1156 |
|
|
|
1157 |
|
|
if (CdlValueSource_Current == source) {
|
1158 |
|
|
source = current_source;
|
1159 |
|
|
}
|
1160 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1161 |
|
|
CYG_PRECONDITIONC(source_valid[source]);
|
1162 |
|
|
|
1163 |
|
|
CYG_REPORT_RETURN();
|
1164 |
|
|
return values[source];
|
1165 |
|
|
}
|
1166 |
|
|
|
1167 |
|
|
//}}}
|
1168 |
|
|
//{{{ Value modification
|
1169 |
|
|
|
1170 |
|
|
// ----------------------------------------------------------------------------
|
1171 |
|
|
|
1172 |
|
|
void
|
1173 |
|
|
CdlValue::set_enabled(bool val, CdlValueSource source)
|
1174 |
|
|
{
|
1175 |
|
|
CYG_REPORT_FUNCNAME("CdlValue::set_enabled");
|
1176 |
|
|
CYG_REPORT_FUNCARG3XV(this, val, source);
|
1177 |
|
|
CYG_INVARIANT_THISC(CdlValue);
|
1178 |
|
|
CYG_PRECONDITIONC((CdlValueFlavor_Bool == flavor) || (CdlValueFlavor_BoolData == flavor));
|
1179 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1180 |
|
|
|
1181 |
|
|
enabled[source] = val;
|
1182 |
|
|
source_valid[source] = true;
|
1183 |
|
|
if (source > current_source) {
|
1184 |
|
|
current_source = source;
|
1185 |
|
|
}
|
1186 |
|
|
|
1187 |
|
|
CYG_REPORT_RETURN();
|
1188 |
|
|
}
|
1189 |
|
|
|
1190 |
|
|
void
|
1191 |
|
|
CdlValue::set_value(CdlSimpleValue& val, CdlValueSource source)
|
1192 |
|
|
{
|
1193 |
|
|
CYG_REPORT_FUNCNAME("CdlValue::set_value");
|
1194 |
|
|
CYG_REPORT_FUNCARG3XV(this, &val, source);
|
1195 |
|
|
CYG_INVARIANT_THISC(CdlValue);
|
1196 |
|
|
CYG_PRECONDITIONC((CdlValueFlavor_BoolData == flavor) || (CdlValueFlavor_Data == flavor));
|
1197 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1198 |
|
|
|
1199 |
|
|
values[source] = val;
|
1200 |
|
|
source_valid[source] = true;
|
1201 |
|
|
if (source > current_source) {
|
1202 |
|
|
current_source = source;
|
1203 |
|
|
}
|
1204 |
|
|
|
1205 |
|
|
CYG_REPORT_RETURN();
|
1206 |
|
|
}
|
1207 |
|
|
|
1208 |
|
|
void
|
1209 |
|
|
CdlValue::set_enabled_and_value(bool enabled_arg, CdlSimpleValue& val, CdlValueSource source)
|
1210 |
|
|
{
|
1211 |
|
|
CYG_REPORT_FUNCNAME("CdlValue::set_enabled_and_value");
|
1212 |
|
|
CYG_REPORT_FUNCARG4XV(this, enabled_arg, &val, source);
|
1213 |
|
|
CYG_INVARIANT_THISC(CdlValue);
|
1214 |
|
|
CYG_PRECONDITIONC(CdlValueFlavor_BoolData == flavor);
|
1215 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1216 |
|
|
|
1217 |
|
|
enabled[source] = enabled_arg;
|
1218 |
|
|
values[source] = val;
|
1219 |
|
|
source_valid[source] = true;
|
1220 |
|
|
if (source > current_source) {
|
1221 |
|
|
current_source = source;
|
1222 |
|
|
}
|
1223 |
|
|
|
1224 |
|
|
CYG_REPORT_RETURN();
|
1225 |
|
|
}
|
1226 |
|
|
|
1227 |
|
|
// ----------------------------------------------------------------------------
|
1228 |
|
|
// Given a SimpleValue, this member function does the right thing
|
1229 |
|
|
// for the flavor.
|
1230 |
|
|
|
1231 |
|
|
void
|
1232 |
|
|
CdlValue::set(CdlSimpleValue& val, CdlValueSource source)
|
1233 |
|
|
{
|
1234 |
|
|
CYG_REPORT_FUNCNAME("CdlValue::set");
|
1235 |
|
|
CYG_REPORT_FUNCARG3XV(this, &val, source);
|
1236 |
|
|
CYG_INVARIANT_THISC(CdlValue);
|
1237 |
|
|
CYG_ASSERTC((CdlValueFlavor_Bool == flavor) || (CdlValueFlavor_BoolData == flavor) || (CdlValueFlavor_Data == flavor));
|
1238 |
|
|
CYG_PRECONDITIONC((0 <= source) && (source < CdlValue_number_of_sources));
|
1239 |
|
|
|
1240 |
|
|
switch(flavor) {
|
1241 |
|
|
case CdlValueFlavor_Bool:
|
1242 |
|
|
enabled[source] = val.get_bool_value();
|
1243 |
|
|
break;
|
1244 |
|
|
|
1245 |
|
|
case CdlValueFlavor_BoolData:
|
1246 |
|
|
if (!val.get_bool_value()) {
|
1247 |
|
|
enabled[source] = false;
|
1248 |
|
|
values[source] = (cdl_int) 0;
|
1249 |
|
|
} else {
|
1250 |
|
|
enabled[source] = true;
|
1251 |
|
|
values[source] = val;
|
1252 |
|
|
}
|
1253 |
|
|
break;
|
1254 |
|
|
|
1255 |
|
|
case CdlValueFlavor_Data:
|
1256 |
|
|
values[source] = val;
|
1257 |
|
|
break;
|
1258 |
|
|
|
1259 |
|
|
default:
|
1260 |
|
|
CYG_FAIL("Unknown value flavor detected.");
|
1261 |
|
|
}
|
1262 |
|
|
|
1263 |
|
|
source_valid[source] = true;
|
1264 |
|
|
if (source > current_source) {
|
1265 |
|
|
current_source = source;
|
1266 |
|
|
}
|
1267 |
|
|
|
1268 |
|
|
CYG_REPORT_RETURN();
|
1269 |
|
|
}
|
1270 |
|
|
|
1271 |
|
|
//}}}
|
1272 |
|
|
|
1273 |
|
|
//}}}
|
1274 |
|
|
//{{{ CdlListValue class
|
1275 |
|
|
|
1276 |
|
|
// ----------------------------------------------------------------------------
|
1277 |
|
|
// List values. Most of this is straightforward.
|
1278 |
|
|
|
1279 |
|
|
CdlListValue::CdlListValue()
|
1280 |
|
|
{
|
1281 |
|
|
CYG_REPORT_FUNCNAME("CdlListValue:: default constructor");
|
1282 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1283 |
|
|
|
1284 |
|
|
// The only data fields are embedded objects which will have been
|
1285 |
|
|
// filled in already.
|
1286 |
|
|
cdllistvalue_cookie = CdlListValue_Magic;
|
1287 |
|
|
CYGDBG_MEMLEAK_CONSTRUCTOR();
|
1288 |
|
|
|
1289 |
|
|
CYG_POSTCONDITION_THISC();
|
1290 |
|
|
CYG_REPORT_RETURN();
|
1291 |
|
|
}
|
1292 |
|
|
|
1293 |
|
|
CdlListValue::CdlListValue(const CdlListValue& original)
|
1294 |
|
|
{
|
1295 |
|
|
CYG_REPORT_FUNCNAME("CdlListValue:: copy constructor");
|
1296 |
|
|
CYG_REPORT_FUNCARG2XV(this, &original);
|
1297 |
|
|
CYG_INVARIANT_CLASSOC(CdlListValue, original);
|
1298 |
|
|
|
1299 |
|
|
// This may get expensive, but should not happen very often.
|
1300 |
|
|
table = original.table;
|
1301 |
|
|
integer_ranges = original.integer_ranges;
|
1302 |
|
|
double_ranges = original.double_ranges;
|
1303 |
|
|
cdllistvalue_cookie = CdlListValue_Magic;
|
1304 |
|
|
CYGDBG_MEMLEAK_CONSTRUCTOR();
|
1305 |
|
|
|
1306 |
|
|
CYG_POSTCONDITION_THISC();
|
1307 |
|
|
CYG_REPORT_RETURN();
|
1308 |
|
|
}
|
1309 |
|
|
|
1310 |
|
|
CdlListValue & CdlListValue::operator=(const CdlListValue& original)
|
1311 |
|
|
{
|
1312 |
|
|
CYG_REPORT_FUNCNAME("CdlListValue:: assignment operator");
|
1313 |
|
|
CYG_REPORT_FUNCARG2XV(this, &original);
|
1314 |
|
|
CYG_INVARIANT_CLASSOC(CdlListValue, original);
|
1315 |
|
|
|
1316 |
|
|
if (this != &original) {
|
1317 |
|
|
table.clear();
|
1318 |
|
|
integer_ranges.clear();
|
1319 |
|
|
double_ranges.clear();
|
1320 |
|
|
table = original.table;
|
1321 |
|
|
integer_ranges = original.integer_ranges;
|
1322 |
|
|
double_ranges = original.double_ranges;
|
1323 |
|
|
}
|
1324 |
|
|
|
1325 |
|
|
CYG_POSTCONDITION_THISC();
|
1326 |
|
|
CYG_REPORT_RETURN();
|
1327 |
|
|
return *this;
|
1328 |
|
|
}
|
1329 |
|
|
|
1330 |
|
|
CdlListValue::~CdlListValue()
|
1331 |
|
|
{
|
1332 |
|
|
CYG_REPORT_FUNCNAME("CdlListValue:: destructor");
|
1333 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1334 |
|
|
CYG_PRECONDITION_THISC();
|
1335 |
|
|
|
1336 |
|
|
cdllistvalue_cookie = CdlListValue_Invalid;
|
1337 |
|
|
table.clear();
|
1338 |
|
|
integer_ranges.clear();
|
1339 |
|
|
double_ranges.clear();
|
1340 |
|
|
CYGDBG_MEMLEAK_DESTRUCTOR();
|
1341 |
|
|
|
1342 |
|
|
CYG_REPORT_RETURN();
|
1343 |
|
|
}
|
1344 |
|
|
|
1345 |
|
|
// ----------------------------------------------------------------------------
|
1346 |
|
|
// Finding out about the current legal values. These routines can be
|
1347 |
|
|
// used by GUI-related code to figure out a sensible widget to be used
|
1348 |
|
|
// for a CDL entity. In nearly all cases life will be simple: either
|
1349 |
|
|
// there will be a fixed set of legal values and the user merely has
|
1350 |
|
|
// to choose one of these; or there will be a simple numerical range.
|
1351 |
|
|
// Occasionally life may be more complicated, if the full generality
|
1352 |
|
|
// of CDL list expressions is being used, and it will be necessary to
|
1353 |
|
|
// use an entry box instead. Note that the entity's flavor may also
|
1354 |
|
|
// affect the user interface.
|
1355 |
|
|
|
1356 |
|
|
const std::vector<CdlSimpleValue>&
|
1357 |
|
|
CdlListValue::get_table(void) const
|
1358 |
|
|
{
|
1359 |
|
|
CYG_REPORT_FUNCNAME("CdlListValue::get_table");
|
1360 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1361 |
|
|
CYG_PRECONDITION_THISC();
|
1362 |
|
|
|
1363 |
|
|
CYG_REPORT_RETURN();
|
1364 |
|
|
return table;
|
1365 |
|
|
}
|
1366 |
|
|
|
1367 |
|
|
const std::vector<std::pair<cdl_int, cdl_int> >&
|
1368 |
|
|
CdlListValue::get_integer_ranges(void) const
|
1369 |
|
|
{
|
1370 |
|
|
CYG_REPORT_FUNCNAME("CdlListValue::get_integer_ranges");
|
1371 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1372 |
|
|
CYG_PRECONDITION_THISC();
|
1373 |
|
|
|
1374 |
|
|
CYG_REPORT_RETURN();
|
1375 |
|
|
return integer_ranges;
|
1376 |
|
|
}
|
1377 |
|
|
|
1378 |
|
|
const std::vector<std::pair<double, double> >&
|
1379 |
|
|
CdlListValue::get_double_ranges(void) const
|
1380 |
|
|
{
|
1381 |
|
|
CYG_REPORT_FUNCNAME("CdlListValue::get_double_ranges");
|
1382 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1383 |
|
|
CYG_PRECONDITION_THISC();
|
1384 |
|
|
|
1385 |
|
|
CYG_REPORT_RETURN();
|
1386 |
|
|
return double_ranges;
|
1387 |
|
|
}
|
1388 |
|
|
|
1389 |
|
|
// ----------------------------------------------------------------------------
|
1390 |
|
|
// Membership. This can be quite complicated.
|
1391 |
|
|
//
|
1392 |
|
|
// 1) anything which has an integer representation must be checked against
|
1393 |
|
|
// the integer ranges and the vector of integer constants. It must
|
1394 |
|
|
// also be checked against the floating point ranges, since calculations
|
1395 |
|
|
// may have resulted in the fractional part disappearing, assuming that
|
1396 |
|
|
// the integer has a floating point representation.
|
1397 |
|
|
//
|
1398 |
|
|
// 2) similarly anything which has a floating point representation must
|
1399 |
|
|
// be checked against the floating point ranges and constant vector.
|
1400 |
|
|
// In addition it may have an empty fractional part in which case
|
1401 |
|
|
// integer comparisons have to be attempted as well.
|
1402 |
|
|
//
|
1403 |
|
|
// 3) string data needs to be tested first of all for integer and double
|
1404 |
|
|
// representations. If these fail then the comparison should be against
|
1405 |
|
|
// the string vector.
|
1406 |
|
|
//
|
1407 |
|
|
// For floating point data exact comparisons are of course meaningless,
|
1408 |
|
|
// and arguably the vector of floating point constants is useless. The
|
1409 |
|
|
// ranges vector is better, but still not ideal. It may be necessary
|
1410 |
|
|
// to introduce an epsilon fudge factor.
|
1411 |
|
|
|
1412 |
|
|
bool
|
1413 |
|
|
CdlListValue::is_member(CdlSimpleValue& val) const
|
1414 |
|
|
{
|
1415 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlListValue::is_member (CdlSimpleValue)", "result %d");
|
1416 |
|
|
CYG_REPORT_FUNCARG2XV(this, &val);
|
1417 |
|
|
CYG_PRECONDITION_THISC();
|
1418 |
|
|
|
1419 |
|
|
bool result = false;
|
1420 |
|
|
if (val.has_integer_value()) {
|
1421 |
|
|
result = is_member(val.get_integer_value(), false);
|
1422 |
|
|
}
|
1423 |
|
|
if (!result && val.has_double_value()) {
|
1424 |
|
|
result = is_member(val.get_double_value(), false);
|
1425 |
|
|
}
|
1426 |
|
|
if (!result) {
|
1427 |
|
|
result = is_member(val.get_value());
|
1428 |
|
|
}
|
1429 |
|
|
|
1430 |
|
|
CYG_REPORT_RETVAL(result);
|
1431 |
|
|
return result;
|
1432 |
|
|
}
|
1433 |
|
|
|
1434 |
|
|
bool
|
1435 |
|
|
CdlListValue::is_member(std::string val, bool allow_conversions) const
|
1436 |
|
|
{
|
1437 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlListValue::is_member (string)", "result %d");
|
1438 |
|
|
CYG_REPORT_FUNCARG3XV(this, &val, allow_conversions);
|
1439 |
|
|
CYG_PRECONDITION_THISC();
|
1440 |
|
|
|
1441 |
|
|
bool result = false;
|
1442 |
|
|
if (allow_conversions) {
|
1443 |
|
|
cdl_int integer_value;
|
1444 |
|
|
double double_value;
|
1445 |
|
|
|
1446 |
|
|
if (Cdl::string_to_integer(val, integer_value)) {
|
1447 |
|
|
result = is_member(integer_value, false);
|
1448 |
|
|
}
|
1449 |
|
|
if (!result && Cdl::string_to_double(val, double_value)) {
|
1450 |
|
|
result = is_member(double_value, false);
|
1451 |
|
|
}
|
1452 |
|
|
}
|
1453 |
|
|
if (!result) {
|
1454 |
|
|
for (std::vector<CdlSimpleValue>::const_iterator val_i = table.begin(); val_i != table.end(); val_i++) {
|
1455 |
|
|
if (val_i->get_value() == val) {
|
1456 |
|
|
result = true;
|
1457 |
|
|
break;
|
1458 |
|
|
}
|
1459 |
|
|
}
|
1460 |
|
|
}
|
1461 |
|
|
|
1462 |
|
|
CYG_REPORT_RETVAL(result);
|
1463 |
|
|
return result;
|
1464 |
|
|
}
|
1465 |
|
|
|
1466 |
|
|
bool
|
1467 |
|
|
CdlListValue::is_member(cdl_int val, bool allow_conversions) const
|
1468 |
|
|
{
|
1469 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlListValue::is_member (int)", "result %d");
|
1470 |
|
|
CYG_REPORT_FUNCARG3XV(this, &val, allow_conversions);
|
1471 |
|
|
CYG_PRECONDITION_THISC();
|
1472 |
|
|
|
1473 |
|
|
bool result = false;
|
1474 |
|
|
for (std::vector<CdlSimpleValue>::const_iterator val_i = table.begin(); val_i != table.end(); val_i++) {
|
1475 |
|
|
if (val_i->has_integer_value() && (val_i->get_integer_value() == val)) {
|
1476 |
|
|
result = true;
|
1477 |
|
|
break;
|
1478 |
|
|
}
|
1479 |
|
|
}
|
1480 |
|
|
if (!result) {
|
1481 |
|
|
for (std::vector<std::pair<cdl_int,cdl_int> >::const_iterator i = integer_ranges.begin();
|
1482 |
|
|
i != integer_ranges.end(); i++) {
|
1483 |
|
|
if ((val >= i->first) && (val <= i->second)) {
|
1484 |
|
|
result = true;
|
1485 |
|
|
break;
|
1486 |
|
|
}
|
1487 |
|
|
}
|
1488 |
|
|
}
|
1489 |
|
|
if (!result && allow_conversions) {
|
1490 |
|
|
double double_value = Cdl::integer_to_double(val);
|
1491 |
|
|
result = is_member(double_value, false);
|
1492 |
|
|
}
|
1493 |
|
|
|
1494 |
|
|
CYG_REPORT_RETVAL(result);
|
1495 |
|
|
return result;
|
1496 |
|
|
}
|
1497 |
|
|
|
1498 |
|
|
bool
|
1499 |
|
|
CdlListValue::is_member(double val, bool allow_conversions) const
|
1500 |
|
|
{
|
1501 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlListValue::is_member (double)", "result %d");
|
1502 |
|
|
CYG_REPORT_FUNCARG3XV(this, &val, allow_conversions);
|
1503 |
|
|
CYG_PRECONDITION_THISC();
|
1504 |
|
|
|
1505 |
|
|
bool result = false;
|
1506 |
|
|
for (std::vector<CdlSimpleValue>::const_iterator val_i = table.begin(); val_i != table.end(); val_i++) {
|
1507 |
|
|
if (val_i->has_double_value() && (val_i->get_double_value() == val)) {
|
1508 |
|
|
result = true;
|
1509 |
|
|
break;
|
1510 |
|
|
}
|
1511 |
|
|
}
|
1512 |
|
|
if (!result) {
|
1513 |
|
|
for (std::vector<std::pair<double,double> >::const_iterator i = double_ranges.begin();
|
1514 |
|
|
i != double_ranges.end(); i++) {
|
1515 |
|
|
if ((val >= i->first) && (val <= i->second)) {
|
1516 |
|
|
result = true;
|
1517 |
|
|
break;
|
1518 |
|
|
}
|
1519 |
|
|
}
|
1520 |
|
|
}
|
1521 |
|
|
if (!result && allow_conversions) {
|
1522 |
|
|
cdl_int integer_value;
|
1523 |
|
|
if (Cdl::double_to_integer(val, integer_value)) {
|
1524 |
|
|
result = is_member(integer_value, false);
|
1525 |
|
|
}
|
1526 |
|
|
}
|
1527 |
|
|
|
1528 |
|
|
CYG_REPORT_RETVAL(result);
|
1529 |
|
|
return result;
|
1530 |
|
|
}
|
1531 |
|
|
|
1532 |
|
|
// ----------------------------------------------------------------------------
|
1533 |
|
|
|
1534 |
|
|
bool
|
1535 |
|
|
CdlListValue::check_this(cyg_assert_class_zeal zeal) const
|
1536 |
|
|
{
|
1537 |
|
|
if (CdlListValue_Magic != cdllistvalue_cookie) {
|
1538 |
|
|
return false;
|
1539 |
|
|
}
|
1540 |
|
|
CYGDBG_MEMLEAK_CHECKTHIS();
|
1541 |
|
|
|
1542 |
|
|
// After construction the various vectors will still be empty, they
|
1543 |
|
|
// do not get filled in until a list expression is evaluated. No
|
1544 |
|
|
// further tests are possible here.
|
1545 |
|
|
return true;
|
1546 |
|
|
}
|
1547 |
|
|
|
1548 |
|
|
//}}}
|
1549 |
|
|
|
1550 |
|
|
//{{{ dialog property
|
1551 |
|
|
|
1552 |
|
|
// ----------------------------------------------------------------------------
|
1553 |
|
|
// Syntax: dialog <reference>
|
1554 |
|
|
|
1555 |
|
|
void
|
1556 |
|
|
CdlValuableBody::dialog_update_handler(CdlTransaction transaction, CdlNode source, CdlProperty prop, CdlNode dest,
|
1557 |
|
|
CdlUpdate change)
|
1558 |
|
|
{
|
1559 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::dialog_update_handler");
|
1560 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
1561 |
|
|
CYG_PRECONDITION_CLASSC(source);
|
1562 |
|
|
CYG_PRECONDITION_CLASSC(prop);
|
1563 |
|
|
|
1564 |
|
|
// The main update of interest is Loaded (iff dest != 0), and
|
1565 |
|
|
// Created. These updates indicate that the destination now exists,
|
1566 |
|
|
// so it is possible to check that the destination is a dialog.
|
1567 |
|
|
if (((CdlUpdate_Loaded == change) && (0 != dest)) ||
|
1568 |
|
|
(CdlUpdate_Created == change)) {
|
1569 |
|
|
|
1570 |
|
|
CYG_ASSERT_CLASSC(dest);
|
1571 |
|
|
CdlDialog dialog = dynamic_cast<CdlDialog>(dest);
|
1572 |
|
|
if (0 == dialog) {
|
1573 |
|
|
std::string msg = dest->get_class_name() + " " + dest->get_name() +
|
1574 |
|
|
" cannot be used in a dialog property, it is not a custom dialog.";
|
1575 |
|
|
CdlConflict_DataBody::make(transaction, source, prop, msg);
|
1576 |
|
|
}
|
1577 |
|
|
|
1578 |
|
|
} else if (CdlUpdate_Destroyed == change) {
|
1579 |
|
|
// If there was a data conflict object, it is no longer relevant
|
1580 |
|
|
transaction->clear_structural_conflicts(source, prop, &CdlConflict_DataBody::test);
|
1581 |
|
|
}
|
1582 |
|
|
|
1583 |
|
|
CYG_REPORT_RETURN();
|
1584 |
|
|
}
|
1585 |
|
|
|
1586 |
|
|
int
|
1587 |
|
|
CdlValuableBody::parse_dialog(CdlInterpreter interp, int argc, const char* argv[])
|
1588 |
|
|
{
|
1589 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_dialog", "result %d");
|
1590 |
|
|
|
1591 |
|
|
int result = CdlParse::parse_reference_property(interp, argc, argv, CdlPropertyId_Dialog, 0, 0, false, &dialog_update_handler);
|
1592 |
|
|
|
1593 |
|
|
CYG_REPORT_RETVAL(result);
|
1594 |
|
|
return result;
|
1595 |
|
|
}
|
1596 |
|
|
|
1597 |
|
|
bool
|
1598 |
|
|
CdlValuableBody::has_dialog() const
|
1599 |
|
|
{
|
1600 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_dialog", "result %d");
|
1601 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1602 |
|
|
CYG_PRECONDITION_THISC();
|
1603 |
|
|
|
1604 |
|
|
// It is not enough to have the property, the dialog reference must also be
|
1605 |
|
|
// resolved and go to a dialog.
|
1606 |
|
|
bool result = false;
|
1607 |
|
|
CdlProperty property = get_property(CdlPropertyId_Dialog);
|
1608 |
|
|
if (0 != property) {
|
1609 |
|
|
CdlProperty_Reference ref_prop = dynamic_cast<CdlProperty_Reference>(property);
|
1610 |
|
|
CYG_ASSERTC(0 != ref_prop);
|
1611 |
|
|
|
1612 |
|
|
CdlNode destination = ref_prop->get_destination();
|
1613 |
|
|
if (0 != destination) {
|
1614 |
|
|
CdlDialog dialog = dynamic_cast<CdlDialog>(destination);
|
1615 |
|
|
if (0 != dialog) {
|
1616 |
|
|
result = true;
|
1617 |
|
|
}
|
1618 |
|
|
}
|
1619 |
|
|
}
|
1620 |
|
|
CYG_REPORT_RETVAL(result);
|
1621 |
|
|
return result;
|
1622 |
|
|
}
|
1623 |
|
|
|
1624 |
|
|
|
1625 |
|
|
CdlDialog
|
1626 |
|
|
CdlValuableBody::get_dialog() const
|
1627 |
|
|
{
|
1628 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_dialog", "result %p");
|
1629 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1630 |
|
|
CYG_PRECONDITION_THISC();
|
1631 |
|
|
|
1632 |
|
|
CdlDialog result = 0;
|
1633 |
|
|
CdlProperty property = get_property(CdlPropertyId_Dialog);
|
1634 |
|
|
if (0 != property) {
|
1635 |
|
|
CdlProperty_Reference ref_prop = dynamic_cast<CdlProperty_Reference>(property);
|
1636 |
|
|
CYG_ASSERTC(0 != ref_prop);
|
1637 |
|
|
|
1638 |
|
|
CdlNode destination = ref_prop->get_destination();
|
1639 |
|
|
if (0 != destination) {
|
1640 |
|
|
result = dynamic_cast<CdlDialog>(destination);
|
1641 |
|
|
}
|
1642 |
|
|
}
|
1643 |
|
|
|
1644 |
|
|
CYG_REPORT_RETVAL(result);
|
1645 |
|
|
return result;
|
1646 |
|
|
}
|
1647 |
|
|
|
1648 |
|
|
//}}}
|
1649 |
|
|
//{{{ wizard property
|
1650 |
|
|
|
1651 |
|
|
// ----------------------------------------------------------------------------
|
1652 |
|
|
// Syntax: wizard <reference>
|
1653 |
|
|
|
1654 |
|
|
void
|
1655 |
|
|
CdlValuableBody::wizard_update_handler(CdlTransaction transaction, CdlNode source, CdlProperty prop, CdlNode dest,
|
1656 |
|
|
CdlUpdate change)
|
1657 |
|
|
{
|
1658 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::wizard_update_handler");
|
1659 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
1660 |
|
|
CYG_PRECONDITION_CLASSC(source);
|
1661 |
|
|
CYG_PRECONDITION_CLASSC(prop);
|
1662 |
|
|
|
1663 |
|
|
// The main update of interest is Loaded (iff dest != 0), and
|
1664 |
|
|
// Created. These updates indicate that the destination now exists,
|
1665 |
|
|
// so it is possible to check that the destination is a dialog.
|
1666 |
|
|
if (((CdlUpdate_Loaded == change) && (0 != dest)) ||
|
1667 |
|
|
(CdlUpdate_Created == change)) {
|
1668 |
|
|
|
1669 |
|
|
CYG_ASSERT_CLASSC(dest);
|
1670 |
|
|
CdlWizard wizard = dynamic_cast<CdlWizard>(dest);
|
1671 |
|
|
if (0 == wizard) {
|
1672 |
|
|
std::string msg = dest->get_class_name() + " " + dest->get_name() +
|
1673 |
|
|
" cannot be used in a wizard property, it is not a wizard.";
|
1674 |
|
|
CdlConflict_DataBody::make(transaction, source, prop, msg);
|
1675 |
|
|
}
|
1676 |
|
|
|
1677 |
|
|
} else if (CdlUpdate_Destroyed == change) {
|
1678 |
|
|
// If there was a data conflict object, it is no longer relevant
|
1679 |
|
|
transaction->clear_structural_conflicts(source, prop, &CdlConflict_DataBody::test);
|
1680 |
|
|
}
|
1681 |
|
|
|
1682 |
|
|
CYG_REPORT_RETURN();
|
1683 |
|
|
}
|
1684 |
|
|
|
1685 |
|
|
int
|
1686 |
|
|
CdlValuableBody::parse_wizard(CdlInterpreter interp, int argc, const char* argv[])
|
1687 |
|
|
{
|
1688 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_wizard", "result %d");
|
1689 |
|
|
|
1690 |
|
|
int result = CdlParse::parse_reference_property(interp, argc, argv, CdlPropertyId_Wizard, 0, 0, false, &wizard_update_handler);
|
1691 |
|
|
CYG_REPORT_RETVAL(result);
|
1692 |
|
|
return result;
|
1693 |
|
|
}
|
1694 |
|
|
|
1695 |
|
|
bool
|
1696 |
|
|
CdlValuableBody::has_wizard() const
|
1697 |
|
|
{
|
1698 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_wizard", "result %d");
|
1699 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1700 |
|
|
CYG_PRECONDITION_THISC();
|
1701 |
|
|
|
1702 |
|
|
// It is not enough to have the property, the wizard reference
|
1703 |
|
|
// must also be resolved to a wizard object.
|
1704 |
|
|
bool result = false;
|
1705 |
|
|
CdlProperty property = get_property(CdlPropertyId_Wizard);
|
1706 |
|
|
if (0 != property) {
|
1707 |
|
|
CdlProperty_Reference ref_prop = dynamic_cast<CdlProperty_Reference>(property);
|
1708 |
|
|
CYG_ASSERTC(0 != ref_prop);
|
1709 |
|
|
|
1710 |
|
|
CdlNode destination = ref_prop->get_destination();
|
1711 |
|
|
if (0 != destination) {
|
1712 |
|
|
CdlWizard wizard = dynamic_cast<CdlWizard>(destination);
|
1713 |
|
|
CYG_ASSERTC(0 != wizard);
|
1714 |
|
|
CYG_UNUSED_PARAM(CdlWizard, wizard);
|
1715 |
|
|
result = true;
|
1716 |
|
|
}
|
1717 |
|
|
}
|
1718 |
|
|
CYG_REPORT_RETVAL(result);
|
1719 |
|
|
return result;
|
1720 |
|
|
}
|
1721 |
|
|
|
1722 |
|
|
CdlWizard
|
1723 |
|
|
CdlValuableBody::get_wizard() const
|
1724 |
|
|
{
|
1725 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_wizard", "result %p");
|
1726 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1727 |
|
|
CYG_PRECONDITION_THISC();
|
1728 |
|
|
|
1729 |
|
|
CdlWizard result = 0;
|
1730 |
|
|
CdlProperty property = get_property(CdlPropertyId_Wizard);
|
1731 |
|
|
if (0 != property) {
|
1732 |
|
|
CdlProperty_Reference ref_prop = dynamic_cast<CdlProperty_Reference>(property);
|
1733 |
|
|
CYG_ASSERTC(0 != ref_prop);
|
1734 |
|
|
|
1735 |
|
|
CdlNode destination = ref_prop->get_destination();
|
1736 |
|
|
if (0 != destination) {
|
1737 |
|
|
result = dynamic_cast<CdlWizard>(destination);
|
1738 |
|
|
CYG_ASSERTC(0 != result);
|
1739 |
|
|
}
|
1740 |
|
|
}
|
1741 |
|
|
|
1742 |
|
|
CYG_REPORT_RETVAL(result);
|
1743 |
|
|
return result;
|
1744 |
|
|
}
|
1745 |
|
|
|
1746 |
|
|
//}}}
|
1747 |
|
|
//{{{ legal_values property
|
1748 |
|
|
|
1749 |
|
|
// ----------------------------------------------------------------------------
|
1750 |
|
|
// Syntax: legal_values <list expression>
|
1751 |
|
|
|
1752 |
|
|
void
|
1753 |
|
|
CdlValuableBody::legal_values_update_handler(CdlTransaction transaction, CdlNode source, CdlProperty prop, CdlNode dest,
|
1754 |
|
|
CdlUpdate change)
|
1755 |
|
|
{
|
1756 |
|
|
CYG_REPORT_FUNCNAME("legal_values_update_handler");
|
1757 |
|
|
|
1758 |
|
|
// Loaded and Unloading are of no immediate interest, reference
|
1759 |
|
|
// updating happens in the calling code.
|
1760 |
|
|
//
|
1761 |
|
|
// Any other change can affect the list expression and hence
|
1762 |
|
|
// invalidate the current value.
|
1763 |
|
|
if ((CdlUpdate_Loaded == change) || (CdlUpdate_Unloading == change)) {
|
1764 |
|
|
CYG_REPORT_RETURN();
|
1765 |
|
|
return;
|
1766 |
|
|
}
|
1767 |
|
|
|
1768 |
|
|
CdlValuable valuable = dynamic_cast<CdlValuable>(source);
|
1769 |
|
|
CdlProperty_ListExpression lexpr = dynamic_cast<CdlProperty_ListExpression>(prop);
|
1770 |
|
|
CYG_ASSERT_CLASSC(valuable);
|
1771 |
|
|
CYG_ASSERT_CLASSC(lexpr);
|
1772 |
|
|
|
1773 |
|
|
valuable->check_value(transaction);
|
1774 |
|
|
|
1775 |
|
|
CYG_UNUSED_PARAM(CdlNode, dest);
|
1776 |
|
|
CYG_UNUSED_PARAM(CdlProperty_ListExpression, lexpr);
|
1777 |
|
|
CYG_REPORT_RETURN();
|
1778 |
|
|
}
|
1779 |
|
|
|
1780 |
|
|
int
|
1781 |
|
|
CdlValuableBody::parse_legal_values(CdlInterpreter interp, int argc, const char* argv[])
|
1782 |
|
|
{
|
1783 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_legal_values", "result %d");
|
1784 |
|
|
|
1785 |
|
|
int result = CdlParse::parse_listexpression_property(interp, argc, argv, CdlPropertyId_LegalValues, 0, 0,
|
1786 |
|
|
&legal_values_update_handler);
|
1787 |
|
|
CYG_REPORT_RETVAL(result);
|
1788 |
|
|
return result;
|
1789 |
|
|
}
|
1790 |
|
|
|
1791 |
|
|
bool
|
1792 |
|
|
CdlValuableBody::has_legal_values() const
|
1793 |
|
|
{
|
1794 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_legal_values", "result %d");
|
1795 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1796 |
|
|
CYG_PRECONDITION_THISC();
|
1797 |
|
|
|
1798 |
|
|
bool result = has_property(CdlPropertyId_LegalValues);
|
1799 |
|
|
CYG_REPORT_RETVAL(result);
|
1800 |
|
|
return result;
|
1801 |
|
|
}
|
1802 |
|
|
|
1803 |
|
|
CdlProperty_ListExpression
|
1804 |
|
|
CdlValuableBody::get_legal_values() const
|
1805 |
|
|
{
|
1806 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_legal_values", "result %p");
|
1807 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1808 |
|
|
CYG_PRECONDITION_THISC();
|
1809 |
|
|
|
1810 |
|
|
CdlProperty_ListExpression result = 0;
|
1811 |
|
|
CdlProperty property = get_property(CdlPropertyId_LegalValues);
|
1812 |
|
|
if (0 != property) {
|
1813 |
|
|
result = dynamic_cast<CdlProperty_ListExpression>(property);
|
1814 |
|
|
CYG_ASSERTC(0 != result);
|
1815 |
|
|
}
|
1816 |
|
|
|
1817 |
|
|
CYG_REPORT_RETVAL(result);
|
1818 |
|
|
return result;
|
1819 |
|
|
}
|
1820 |
|
|
|
1821 |
|
|
//}}}
|
1822 |
|
|
//{{{ default_value property
|
1823 |
|
|
|
1824 |
|
|
// ----------------------------------------------------------------------------
|
1825 |
|
|
// syntax: default_value <expr>
|
1826 |
|
|
|
1827 |
|
|
void
|
1828 |
|
|
CdlValuableBody::default_value_update_handler(CdlTransaction transaction, CdlNode source, CdlProperty prop, CdlNode dest,
|
1829 |
|
|
CdlUpdate change)
|
1830 |
|
|
{
|
1831 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::default_value_update_handler");
|
1832 |
|
|
CYG_REPORT_FUNCARG5XV(transaction, source, prop, dest, change);
|
1833 |
|
|
|
1834 |
|
|
// Loaded and unloading should be ignored.
|
1835 |
|
|
if ((CdlUpdate_Loaded == change) || (CdlUpdate_Unloading == change)) {
|
1836 |
|
|
CYG_REPORT_RETURN();
|
1837 |
|
|
return;
|
1838 |
|
|
}
|
1839 |
|
|
|
1840 |
|
|
// Init, Created, Destroyed, ValueChange and ActiveChange should
|
1841 |
|
|
// all result in the expression being re-evaluated and the result
|
1842 |
|
|
// applied.
|
1843 |
|
|
CdlValuable valuable = dynamic_cast<CdlValuable>(source);
|
1844 |
|
|
CYG_ASSERTC(0 != valuable);
|
1845 |
|
|
CdlProperty_Expression expr = dynamic_cast<CdlProperty_Expression>(prop);
|
1846 |
|
|
CYG_ASSERTC(0 != expr);
|
1847 |
|
|
|
1848 |
|
|
CdlSimpleValue val;
|
1849 |
|
|
|
1850 |
|
|
try {
|
1851 |
|
|
|
1852 |
|
|
CdlEvalContext context(transaction, source, prop);
|
1853 |
|
|
expr->eval(context, val);
|
1854 |
|
|
|
1855 |
|
|
valuable->set(transaction, val, CdlValueSource_Default);
|
1856 |
|
|
|
1857 |
|
|
} catch(CdlEvalException e) {
|
1858 |
|
|
|
1859 |
|
|
|
1860 |
|
|
// An EvalException conflict will have been created, so the
|
1861 |
|
|
// user knows that this default_value is not kosher. It is
|
1862 |
|
|
// still a good idea to make sure that the object retains a
|
1863 |
|
|
// sensible value.
|
1864 |
|
|
val = (cdl_int) 0;
|
1865 |
|
|
valuable->set(transaction, val, CdlValueSource_Default);
|
1866 |
|
|
}
|
1867 |
|
|
|
1868 |
|
|
CYG_UNUSED_PARAM(CdlNode, dest);
|
1869 |
|
|
CYG_REPORT_RETURN();
|
1870 |
|
|
}
|
1871 |
|
|
|
1872 |
|
|
int
|
1873 |
|
|
CdlValuableBody::parse_default_value(CdlInterpreter interp, int argc, const char* argv[])
|
1874 |
|
|
{
|
1875 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_default_value", "result %d");
|
1876 |
|
|
int result = CdlParse::parse_expression_property(interp, argc, argv, CdlPropertyId_DefaultValue, 0, 0,
|
1877 |
|
|
&default_value_update_handler);
|
1878 |
|
|
CYG_REPORT_RETVAL(result);
|
1879 |
|
|
return result;
|
1880 |
|
|
}
|
1881 |
|
|
|
1882 |
|
|
bool
|
1883 |
|
|
CdlValuableBody::has_default_value_expression() const
|
1884 |
|
|
{
|
1885 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_default_value_expression", "result %d");
|
1886 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1887 |
|
|
CYG_PRECONDITION_THISC();
|
1888 |
|
|
|
1889 |
|
|
bool result = has_property(CdlPropertyId_DefaultValue);
|
1890 |
|
|
CYG_REPORT_RETVAL(result);
|
1891 |
|
|
return result;
|
1892 |
|
|
}
|
1893 |
|
|
|
1894 |
|
|
CdlProperty_Expression
|
1895 |
|
|
CdlValuableBody::get_default_value_expression() const
|
1896 |
|
|
{
|
1897 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_default_value_expression", "result %");
|
1898 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1899 |
|
|
CYG_PRECONDITION_THISC();
|
1900 |
|
|
|
1901 |
|
|
CdlProperty_Expression result = 0;
|
1902 |
|
|
CdlProperty property = get_property(CdlPropertyId_DefaultValue);
|
1903 |
|
|
if (0 != property) {
|
1904 |
|
|
result = dynamic_cast<CdlProperty_Expression>(property);
|
1905 |
|
|
CYG_ASSERTC(0 != result);
|
1906 |
|
|
}
|
1907 |
|
|
|
1908 |
|
|
CYG_REPORT_RETVAL(result);
|
1909 |
|
|
return result;
|
1910 |
|
|
}
|
1911 |
|
|
|
1912 |
|
|
//}}}
|
1913 |
|
|
//{{{ calculated_property
|
1914 |
|
|
|
1915 |
|
|
// ----------------------------------------------------------------------------
|
1916 |
|
|
// Syntax: calculated <expression>
|
1917 |
|
|
|
1918 |
|
|
void
|
1919 |
|
|
CdlValuableBody::calculated_update_handler(CdlTransaction transaction, CdlNode source, CdlProperty prop, CdlNode dest,
|
1920 |
|
|
CdlUpdate change)
|
1921 |
|
|
{
|
1922 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::default_value_update_handler");
|
1923 |
|
|
CYG_REPORT_FUNCARG5XV(transaction, source, prop, dest, change);
|
1924 |
|
|
|
1925 |
|
|
// Loaded and unloading should be ignored.
|
1926 |
|
|
if ((CdlUpdate_Loaded == change) || (CdlUpdate_Unloading == change)) {
|
1927 |
|
|
CYG_REPORT_RETURN();
|
1928 |
|
|
return;
|
1929 |
|
|
}
|
1930 |
|
|
|
1931 |
|
|
// Init, Created, Destroyed, ValueChange and ActiveChange should
|
1932 |
|
|
// all result in the expression being re-evaluated and the result
|
1933 |
|
|
// applied.
|
1934 |
|
|
CdlValuable valuable = dynamic_cast<CdlValuable>(source);
|
1935 |
|
|
CYG_ASSERTC(0 != valuable);
|
1936 |
|
|
CdlProperty_Expression expr = dynamic_cast<CdlProperty_Expression>(prop);
|
1937 |
|
|
CYG_ASSERTC(0 != expr);
|
1938 |
|
|
|
1939 |
|
|
CdlSimpleValue val;
|
1940 |
|
|
|
1941 |
|
|
try {
|
1942 |
|
|
|
1943 |
|
|
CdlEvalContext context(transaction, source, prop);
|
1944 |
|
|
expr->eval(context, val);
|
1945 |
|
|
|
1946 |
|
|
valuable->set(transaction, val, CdlValueSource_Default);
|
1947 |
|
|
|
1948 |
|
|
} catch(CdlEvalException e) {
|
1949 |
|
|
|
1950 |
|
|
|
1951 |
|
|
// An EvalException conflict will have been created, so the
|
1952 |
|
|
// user knows that this default_value is not kosher. It is
|
1953 |
|
|
// still a good idea to make sure that the object retains a
|
1954 |
|
|
// sensible value.
|
1955 |
|
|
val = (cdl_int) 0;
|
1956 |
|
|
valuable->set(transaction, val, CdlValueSource_Default);
|
1957 |
|
|
}
|
1958 |
|
|
|
1959 |
|
|
CYG_UNUSED_PARAM(CdlNode, dest);
|
1960 |
|
|
CYG_REPORT_RETURN();
|
1961 |
|
|
}
|
1962 |
|
|
|
1963 |
|
|
// FIXME: check for flavor none?
|
1964 |
|
|
int
|
1965 |
|
|
CdlValuableBody::parse_calculated(CdlInterpreter interp, int argc, const char* argv[])
|
1966 |
|
|
{
|
1967 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_calculated", "result %d");
|
1968 |
|
|
|
1969 |
|
|
int result = CdlParse::parse_expression_property(interp, argc, argv, CdlPropertyId_Calculated, 0, 0,
|
1970 |
|
|
&calculated_update_handler);
|
1971 |
|
|
CYG_REPORT_RETVAL(result);
|
1972 |
|
|
return result;
|
1973 |
|
|
}
|
1974 |
|
|
|
1975 |
|
|
bool
|
1976 |
|
|
CdlValuableBody::has_calculated_expression() const
|
1977 |
|
|
{
|
1978 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_calculated_expression", "result %d");
|
1979 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1980 |
|
|
CYG_PRECONDITION_THISC();
|
1981 |
|
|
|
1982 |
|
|
bool result = has_property(CdlPropertyId_Calculated);
|
1983 |
|
|
CYG_REPORT_RETVAL(result);
|
1984 |
|
|
return result;
|
1985 |
|
|
}
|
1986 |
|
|
|
1987 |
|
|
CdlProperty_Expression
|
1988 |
|
|
CdlValuableBody::get_calculated_expression() const
|
1989 |
|
|
{
|
1990 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_calculated_expression", "result %p");
|
1991 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
1992 |
|
|
CYG_PRECONDITION_THISC();
|
1993 |
|
|
|
1994 |
|
|
CdlProperty_Expression result = 0;
|
1995 |
|
|
CdlProperty property = get_property(CdlPropertyId_Calculated);
|
1996 |
|
|
if (0 != property) {
|
1997 |
|
|
result = dynamic_cast<CdlProperty_Expression>(property);
|
1998 |
|
|
CYG_ASSERTC(0 != result);
|
1999 |
|
|
}
|
2000 |
|
|
|
2001 |
|
|
CYG_REPORT_RETVAL(result);
|
2002 |
|
|
return result;
|
2003 |
|
|
}
|
2004 |
|
|
|
2005 |
|
|
//}}}
|
2006 |
|
|
//{{{ active_if property
|
2007 |
|
|
|
2008 |
|
|
// ----------------------------------------------------------------------------
|
2009 |
|
|
// Syntax:
|
2010 |
|
|
// active_if <goal expression>
|
2011 |
|
|
|
2012 |
|
|
void
|
2013 |
|
|
CdlValuableBody::active_if_update_handler(CdlTransaction transaction, CdlNode source, CdlProperty prop, CdlNode dest,
|
2014 |
|
|
CdlUpdate change)
|
2015 |
|
|
{
|
2016 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::active_if_update_handler");
|
2017 |
|
|
CYG_REPORT_FUNCARG5XV(transaction, source, prop, dest, change);
|
2018 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2019 |
|
|
CYG_PRECONDITION_CLASSC(source);
|
2020 |
|
|
CYG_PRECONDITION_CLASSC(prop);
|
2021 |
|
|
|
2022 |
|
|
// Loaded should be ignored here, the world is still getting sorted out.
|
2023 |
|
|
// Unloading is of no interest, the source is disappearing anyway.
|
2024 |
|
|
if ((CdlUpdate_Loaded == change) || (CdlUpdate_Unloading == change)) {
|
2025 |
|
|
CYG_REPORT_RETURN();
|
2026 |
|
|
return;
|
2027 |
|
|
}
|
2028 |
|
|
|
2029 |
|
|
// Any other change warrants re-evaluating the active status of the source.
|
2030 |
|
|
// This can be achieved via a test_active() call, although that may do
|
2031 |
|
|
// more work than is strictly necessary e.g. it may re-evaluate other
|
2032 |
|
|
// is_active properties. In practice it is unlikely that there will
|
2033 |
|
|
// be enough other constraints to warrant more efficient processing.
|
2034 |
|
|
bool old_state = transaction->is_active(source);
|
2035 |
|
|
bool new_state = source->test_active(transaction);
|
2036 |
|
|
if (old_state != new_state) {
|
2037 |
|
|
transaction->set_active(source, new_state);
|
2038 |
|
|
}
|
2039 |
|
|
|
2040 |
|
|
CYG_UNUSED_PARAM(CdlNode, dest);
|
2041 |
|
|
CYG_REPORT_RETURN();
|
2042 |
|
|
}
|
2043 |
|
|
|
2044 |
|
|
int
|
2045 |
|
|
CdlValuableBody::parse_active_if(CdlInterpreter interp, int argc, const char* argv[])
|
2046 |
|
|
{
|
2047 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_active_if", "result %d");
|
2048 |
|
|
|
2049 |
|
|
int result = CdlParse::parse_goalexpression_property(interp, argc, argv, CdlPropertyId_ActiveIf, 0, 0,
|
2050 |
|
|
&active_if_update_handler);
|
2051 |
|
|
CYG_REPORT_RETVAL(result);
|
2052 |
|
|
return result;
|
2053 |
|
|
}
|
2054 |
|
|
|
2055 |
|
|
bool
|
2056 |
|
|
CdlValuableBody::has_active_if_conditions() const
|
2057 |
|
|
{
|
2058 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_active_if_conditions", "result %d");
|
2059 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2060 |
|
|
CYG_PRECONDITION_THISC();
|
2061 |
|
|
|
2062 |
|
|
bool result = has_property(CdlPropertyId_ActiveIf);
|
2063 |
|
|
CYG_REPORT_RETVAL(result);
|
2064 |
|
|
return result;
|
2065 |
|
|
}
|
2066 |
|
|
|
2067 |
|
|
void
|
2068 |
|
|
CdlValuableBody::get_active_if_conditions(std::vector<CdlProperty_GoalExpression>& result) const
|
2069 |
|
|
{
|
2070 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_active_if_conditions");
|
2071 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2072 |
|
|
CYG_PRECONDITION_THISC();
|
2073 |
|
|
|
2074 |
|
|
std::vector<CdlProperty> properties;
|
2075 |
|
|
get_properties(CdlPropertyId_ActiveIf, properties);
|
2076 |
|
|
std::vector<CdlProperty>::const_iterator i;
|
2077 |
|
|
for (i = properties.begin(); i != properties.end(); i++) {
|
2078 |
|
|
CdlProperty_GoalExpression goal = dynamic_cast<CdlProperty_GoalExpression>(*i);
|
2079 |
|
|
CYG_ASSERTC(0 != goal);
|
2080 |
|
|
result.push_back(goal);
|
2081 |
|
|
}
|
2082 |
|
|
|
2083 |
|
|
CYG_REPORT_RETURN();
|
2084 |
|
|
}
|
2085 |
|
|
|
2086 |
|
|
//}}}
|
2087 |
|
|
//{{{ requires property
|
2088 |
|
|
|
2089 |
|
|
// ----------------------------------------------------------------------------
|
2090 |
|
|
// Syntax: requires <goal expression>
|
2091 |
|
|
|
2092 |
|
|
void
|
2093 |
|
|
CdlValuableBody::requires_update_handler(CdlTransaction transaction, CdlNode source, CdlProperty prop, CdlNode dest,
|
2094 |
|
|
CdlUpdate change)
|
2095 |
|
|
{
|
2096 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::requires_update_handler");
|
2097 |
|
|
CYG_REPORT_FUNCARG5XV(transaction, source, prop, dest, change);
|
2098 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2099 |
|
|
|
2100 |
|
|
// Loaded and Unloading are not of interest.
|
2101 |
|
|
if ((CdlUpdate_Loaded == change) || (CdlUpdate_Unloading == change)) {
|
2102 |
|
|
CYG_REPORT_RETURN();
|
2103 |
|
|
return;
|
2104 |
|
|
}
|
2105 |
|
|
|
2106 |
|
|
// Any other change should cause normal handling. This happens in
|
2107 |
|
|
// a separate function because "requires" properties also need to
|
2108 |
|
|
// be checked when e.g. the source becomes inactive.
|
2109 |
|
|
CdlValuable valuable = dynamic_cast<CdlValuable>(source);
|
2110 |
|
|
CdlProperty_GoalExpression gexpr = dynamic_cast<CdlProperty_GoalExpression>(prop);
|
2111 |
|
|
CYG_ASSERT_CLASSC(valuable);
|
2112 |
|
|
CYG_ASSERT_CLASSC(gexpr);
|
2113 |
|
|
|
2114 |
|
|
valuable->check_requires(transaction, gexpr);
|
2115 |
|
|
|
2116 |
|
|
CYG_UNUSED_PARAM(CdlNode, dest);
|
2117 |
|
|
CYG_REPORT_RETURN();
|
2118 |
|
|
}
|
2119 |
|
|
|
2120 |
|
|
int
|
2121 |
|
|
CdlValuableBody::parse_requires(CdlInterpreter interp, int argc, const char* argv[])
|
2122 |
|
|
{
|
2123 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_requires", "result %d");
|
2124 |
|
|
|
2125 |
|
|
int result = CdlParse::parse_goalexpression_property(interp, argc, argv, CdlPropertyId_Requires, 0, 0,
|
2126 |
|
|
&requires_update_handler);
|
2127 |
|
|
CYG_REPORT_RETVAL(result);
|
2128 |
|
|
return result;
|
2129 |
|
|
}
|
2130 |
|
|
|
2131 |
|
|
bool
|
2132 |
|
|
CdlValuableBody::has_requires_goals() const
|
2133 |
|
|
{
|
2134 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_requires_goals", "result %d");
|
2135 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2136 |
|
|
CYG_PRECONDITION_THISC();
|
2137 |
|
|
|
2138 |
|
|
bool result = has_property(CdlPropertyId_Requires);
|
2139 |
|
|
CYG_REPORT_RETVAL(result);
|
2140 |
|
|
return result;
|
2141 |
|
|
}
|
2142 |
|
|
|
2143 |
|
|
void
|
2144 |
|
|
CdlValuableBody::get_requires_goals(std::vector<CdlProperty_GoalExpression>& result) const
|
2145 |
|
|
{
|
2146 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_requires_goals");
|
2147 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2148 |
|
|
CYG_PRECONDITION_THISC();
|
2149 |
|
|
|
2150 |
|
|
std::vector<CdlProperty> properties;
|
2151 |
|
|
get_properties(CdlPropertyId_Requires, properties);
|
2152 |
|
|
std::vector<CdlProperty>::const_iterator i;
|
2153 |
|
|
for (i = properties.begin(); i != properties.end(); i++) {
|
2154 |
|
|
CdlProperty_GoalExpression goal = dynamic_cast<CdlProperty_GoalExpression>(*i);
|
2155 |
|
|
CYG_ASSERTC(0 != goal);
|
2156 |
|
|
result.push_back(goal);
|
2157 |
|
|
}
|
2158 |
|
|
|
2159 |
|
|
CYG_REPORT_RETURN();
|
2160 |
|
|
}
|
2161 |
|
|
|
2162 |
|
|
//}}}
|
2163 |
|
|
//{{{ implements property
|
2164 |
|
|
|
2165 |
|
|
// ----------------------------------------------------------------------------
|
2166 |
|
|
// Syntax: implements <reference to interface>
|
2167 |
|
|
|
2168 |
|
|
void
|
2169 |
|
|
CdlValuableBody::implements_update_handler(CdlTransaction transaction, CdlNode source, CdlProperty prop, CdlNode dest,
|
2170 |
|
|
CdlUpdate change)
|
2171 |
|
|
{
|
2172 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::implements_update_handler");
|
2173 |
|
|
CYG_REPORT_FUNCARG5XV(transaction, source, prop, dest, change);
|
2174 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2175 |
|
|
|
2176 |
|
|
// Calculation of interface values happens inside
|
2177 |
|
|
// CdlInterfaceBody::recalculate(). That member function simply
|
2178 |
|
|
// checks all of the implementors and recalculates the value from
|
2179 |
|
|
// scratch. It needs to be invoked whenever there is a relevant
|
2180 |
|
|
// change to the implementors. Currently no attempt is made to
|
2181 |
|
|
// optimise interface updates, although this may have to change in
|
2182 |
|
|
// future.
|
2183 |
|
|
|
2184 |
|
|
// Any changes to the interface itself can be ignored.
|
2185 |
|
|
if ((CdlUpdate_ValueChange == change) || (CdlUpdate_ActiveChange == change)) {
|
2186 |
|
|
CYG_REPORT_RETURN();
|
2187 |
|
|
return;
|
2188 |
|
|
}
|
2189 |
|
|
|
2190 |
|
|
// The second stage init is irrelevant
|
2191 |
|
|
if (CdlUpdate_Init == change) {
|
2192 |
|
|
CYG_REPORT_RETURN();
|
2193 |
|
|
return;
|
2194 |
|
|
}
|
2195 |
|
|
|
2196 |
|
|
// Possibilities:
|
2197 |
|
|
// 1) source is being loaded, dest valid
|
2198 |
|
|
// 2) source is being loaded, dest unknown
|
2199 |
|
|
// 3) source is being unloaded, dest valid
|
2200 |
|
|
// 4) source is being unloaded, dest unknown
|
2201 |
|
|
// 5) dest has been created
|
2202 |
|
|
// 6) dest is going away
|
2203 |
|
|
//
|
2204 |
|
|
// If we have a valid dest, it needs to be updated and any structural
|
2205 |
|
|
// conflicts have to be cleared.
|
2206 |
|
|
//
|
2207 |
|
|
// If there is no dest, the implements property remains unbound.
|
2208 |
|
|
// A suitable conflict is created in the base class.
|
2209 |
|
|
//
|
2210 |
|
|
// If the dest is invalid, a structural conflict has to be created.
|
2211 |
|
|
if (CdlUpdate_Destroyed == change) {
|
2212 |
|
|
// There is no need to do any clean-ups in the dest.
|
2213 |
|
|
dest = 0;
|
2214 |
|
|
}
|
2215 |
|
|
if (0 == dest) {
|
2216 |
|
|
transaction->clear_structural_conflicts(source, prop, &CdlConflict_DataBody::test);
|
2217 |
|
|
} else {
|
2218 |
|
|
CdlInterface interface = dynamic_cast<CdlInterface>(dest);
|
2219 |
|
|
|
2220 |
|
|
if (0 == interface) {
|
2221 |
|
|
std::string msg = source->get_class_name() + " " + source->get_name() + " cannot implement " +
|
2222 |
|
|
dest->get_name() + "\n The latter is not an interface.";
|
2223 |
|
|
CdlConflict_DataBody::make(transaction, source, prop, msg);
|
2224 |
|
|
} else {
|
2225 |
|
|
transaction->clear_structural_conflicts(source, prop, &CdlConflict_DataBody::test);
|
2226 |
|
|
interface->recalculate(transaction);
|
2227 |
|
|
}
|
2228 |
|
|
}
|
2229 |
|
|
|
2230 |
|
|
CYG_REPORT_RETURN();
|
2231 |
|
|
}
|
2232 |
|
|
|
2233 |
|
|
int
|
2234 |
|
|
CdlValuableBody::parse_implements(CdlInterpreter interp, int argc, const char* argv[])
|
2235 |
|
|
{
|
2236 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_implements", "result %d");
|
2237 |
|
|
|
2238 |
|
|
int result = CdlParse::parse_reference_property(interp, argc, argv, CdlPropertyId_Implements, 0, 0, false,
|
2239 |
|
|
&implements_update_handler);
|
2240 |
|
|
|
2241 |
|
|
CYG_REPORT_RETVAL(result);
|
2242 |
|
|
return result;
|
2243 |
|
|
}
|
2244 |
|
|
|
2245 |
|
|
void
|
2246 |
|
|
CdlValuableBody::get_implemented_interfaces(std::vector<CdlInterface>& result) const
|
2247 |
|
|
{
|
2248 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_implemented_interfaces");
|
2249 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2250 |
|
|
CYG_PRECONDITION_THISC();
|
2251 |
|
|
|
2252 |
|
|
std::vector<CdlProperty> properties;
|
2253 |
|
|
get_properties(CdlPropertyId_Implements, properties);
|
2254 |
|
|
std::vector<CdlProperty>::const_iterator i;
|
2255 |
|
|
for (i = properties.begin(); i != properties.end(); i++) {
|
2256 |
|
|
CdlProperty_Reference refprop = dynamic_cast<CdlProperty_Reference>(*i);
|
2257 |
|
|
CYG_ASSERTC(0 != refprop);
|
2258 |
|
|
CdlNode node = refprop->get_destination();
|
2259 |
|
|
if (0 != node) {
|
2260 |
|
|
CdlInterface interface = dynamic_cast<CdlInterface>(node);
|
2261 |
|
|
CYG_ASSERT_CLASSC(interface);
|
2262 |
|
|
result.push_back(interface);
|
2263 |
|
|
}
|
2264 |
|
|
}
|
2265 |
|
|
|
2266 |
|
|
CYG_REPORT_RETURN();
|
2267 |
|
|
}
|
2268 |
|
|
|
2269 |
|
|
//}}}
|
2270 |
|
|
//{{{ Other properties
|
2271 |
|
|
|
2272 |
|
|
// ----------------------------------------------------------------------------
|
2273 |
|
|
// Syntax: flavor <legal flavor>
|
2274 |
|
|
|
2275 |
|
|
static void
|
2276 |
|
|
parse_flavor_final_check(CdlInterpreter interp, CdlProperty_String prop)
|
2277 |
|
|
{
|
2278 |
|
|
CYG_REPORT_FUNCNAME("parse_flavor_final_check");
|
2279 |
|
|
CYG_PRECONDITION_CLASSC(interp);
|
2280 |
|
|
CYG_PRECONDITION_CLASSC(prop);
|
2281 |
|
|
|
2282 |
|
|
const std::string& str = prop->get_string();
|
2283 |
|
|
std::string copy = std::string(str);
|
2284 |
|
|
CdlValueFlavor flavor;
|
2285 |
|
|
|
2286 |
|
|
if (!Cdl::string_to_flavor(copy, flavor)) {
|
2287 |
|
|
CdlParse::report_property_parse_error(interp, prop, str + " is not a valid CDL flavor.");
|
2288 |
|
|
}
|
2289 |
|
|
|
2290 |
|
|
CYG_REPORT_RETURN();
|
2291 |
|
|
}
|
2292 |
|
|
|
2293 |
|
|
|
2294 |
|
|
int
|
2295 |
|
|
CdlValuableBody::parse_flavor(CdlInterpreter interp, int argc, const char* argv[])
|
2296 |
|
|
{
|
2297 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_flavor", "result %d");
|
2298 |
|
|
|
2299 |
|
|
int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_Flavor, 0, &parse_flavor_final_check);
|
2300 |
|
|
CYG_REPORT_RETVAL(result);
|
2301 |
|
|
return result;
|
2302 |
|
|
}
|
2303 |
|
|
|
2304 |
|
|
// ----------------------------------------------------------------------------
|
2305 |
|
|
// syntax: group <group name>
|
2306 |
|
|
int
|
2307 |
|
|
CdlValuableBody::parse_group(CdlInterpreter interp, int argc, const char* argv[])
|
2308 |
|
|
{
|
2309 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_group", "result %d");
|
2310 |
|
|
|
2311 |
|
|
int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_Group, 0, 0);
|
2312 |
|
|
|
2313 |
|
|
CYG_REPORT_RETVAL(result);
|
2314 |
|
|
return result;
|
2315 |
|
|
}
|
2316 |
|
|
|
2317 |
|
|
// ----------------------------------------------------------------------------
|
2318 |
|
|
// Syntax: check_proc <tclcode>
|
2319 |
|
|
|
2320 |
|
|
int
|
2321 |
|
|
CdlValuableBody::parse_check_proc(CdlInterpreter interp, int argc, const char* argv[])
|
2322 |
|
|
{
|
2323 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_check_proc", "result %d");
|
2324 |
|
|
|
2325 |
|
|
int result = CdlParse::parse_tclcode_property(interp, argc, argv, CdlPropertyId_CheckProc, 0, 0);
|
2326 |
|
|
|
2327 |
|
|
CYG_REPORT_RETVAL(result);
|
2328 |
|
|
return result;
|
2329 |
|
|
}
|
2330 |
|
|
|
2331 |
|
|
bool
|
2332 |
|
|
CdlValuableBody::has_check_proc() const
|
2333 |
|
|
{
|
2334 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_check_proc", "result %d");
|
2335 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2336 |
|
|
CYG_PRECONDITION_THISC();
|
2337 |
|
|
|
2338 |
|
|
bool result = has_property(CdlPropertyId_CheckProc);
|
2339 |
|
|
CYG_REPORT_RETVAL(result);
|
2340 |
|
|
return result;
|
2341 |
|
|
}
|
2342 |
|
|
|
2343 |
|
|
cdl_tcl_code
|
2344 |
|
|
CdlValuableBody::get_check_proc() const
|
2345 |
|
|
{
|
2346 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_check_proc");
|
2347 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2348 |
|
|
CYG_PRECONDITION_THISC();
|
2349 |
|
|
|
2350 |
|
|
cdl_tcl_code result = "";
|
2351 |
|
|
CdlProperty property = get_property(CdlPropertyId_CheckProc);
|
2352 |
|
|
if (0 != property) {
|
2353 |
|
|
CdlProperty_TclCode code_prop = dynamic_cast<CdlProperty_TclCode>(property);
|
2354 |
|
|
CYG_ASSERTC(0 != code_prop);
|
2355 |
|
|
result = code_prop->get_code();
|
2356 |
|
|
}
|
2357 |
|
|
|
2358 |
|
|
CYG_REPORT_RETURN();
|
2359 |
|
|
return result;
|
2360 |
|
|
}
|
2361 |
|
|
|
2362 |
|
|
// ----------------------------------------------------------------------------
|
2363 |
|
|
// Syntax: entry_proc <tclcode>
|
2364 |
|
|
|
2365 |
|
|
int
|
2366 |
|
|
CdlValuableBody::parse_entry_proc(CdlInterpreter interp, int argc, const char* argv[])
|
2367 |
|
|
{
|
2368 |
|
|
CYG_REPORT_FUNCNAMETYPE("parse_entry_proc", "result %d");
|
2369 |
|
|
|
2370 |
|
|
int result = CdlParse::parse_tclcode_property(interp, argc, argv, CdlPropertyId_EntryProc, 0, 0);
|
2371 |
|
|
|
2372 |
|
|
CYG_REPORT_RETVAL(result);
|
2373 |
|
|
return result;
|
2374 |
|
|
}
|
2375 |
|
|
|
2376 |
|
|
bool
|
2377 |
|
|
CdlValuableBody::has_entry_proc() const
|
2378 |
|
|
{
|
2379 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_entry_proc", "result %d");
|
2380 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2381 |
|
|
CYG_PRECONDITION_THISC();
|
2382 |
|
|
|
2383 |
|
|
bool result = has_property(CdlPropertyId_EntryProc);
|
2384 |
|
|
CYG_REPORT_RETVAL(result);
|
2385 |
|
|
return result;
|
2386 |
|
|
}
|
2387 |
|
|
cdl_tcl_code
|
2388 |
|
|
CdlValuableBody::get_entry_proc() const
|
2389 |
|
|
{
|
2390 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_entry_proc");
|
2391 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2392 |
|
|
CYG_PRECONDITION_THISC();
|
2393 |
|
|
|
2394 |
|
|
cdl_tcl_code result = "";
|
2395 |
|
|
CdlProperty property = get_property(CdlPropertyId_EntryProc);
|
2396 |
|
|
if (0 != property) {
|
2397 |
|
|
CdlProperty_TclCode code_prop = dynamic_cast<CdlProperty_TclCode>(property);
|
2398 |
|
|
CYG_ASSERTC(0 != code_prop);
|
2399 |
|
|
result = code_prop->get_code();
|
2400 |
|
|
}
|
2401 |
|
|
|
2402 |
|
|
CYG_REPORT_RETURN();
|
2403 |
|
|
return result;
|
2404 |
|
|
}
|
2405 |
|
|
|
2406 |
|
|
//}}}
|
2407 |
|
|
|
2408 |
|
|
//{{{ CdlValuable misc
|
2409 |
|
|
|
2410 |
|
|
// ----------------------------------------------------------------------------
|
2411 |
|
|
// Objects with flavor none are not modifiable. Also, objects with the
|
2412 |
|
|
// calculated property are not modifiable. Everything else is ok.
|
2413 |
|
|
|
2414 |
|
|
bool
|
2415 |
|
|
CdlValuableBody::is_modifiable() const
|
2416 |
|
|
{
|
2417 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuableBody::is_modifiable", "result %d");
|
2418 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2419 |
|
|
CYG_PRECONDITION_THISC();
|
2420 |
|
|
|
2421 |
|
|
bool result = true;
|
2422 |
|
|
if (CdlValueFlavor_None == get_flavor()) {
|
2423 |
|
|
result = false;
|
2424 |
|
|
} else if (has_property(CdlPropertyId_Calculated)) {
|
2425 |
|
|
result = false;
|
2426 |
|
|
}
|
2427 |
|
|
|
2428 |
|
|
CYG_REPORT_RETVAL(result);
|
2429 |
|
|
return result;
|
2430 |
|
|
}
|
2431 |
|
|
|
2432 |
|
|
//}}}
|
2433 |
|
|
//{{{ CdlValuable::get_widget_hint()
|
2434 |
|
|
|
2435 |
|
|
// ----------------------------------------------------------------------------
|
2436 |
|
|
|
2437 |
|
|
void
|
2438 |
|
|
CdlValuableBody::get_widget_hint(CdlWidgetHint& hint)
|
2439 |
|
|
{
|
2440 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_widget_hint");
|
2441 |
|
|
CYG_REPORT_FUNCARG2XV(this, &hint);
|
2442 |
|
|
CYG_PRECONDITION_THISC();
|
2443 |
|
|
|
2444 |
|
|
// Start by resetting the hint to default values.
|
2445 |
|
|
hint.bool_widget = CdlBoolWidget_None;
|
2446 |
|
|
hint.value_widget = CdlValueWidget_None;
|
2447 |
|
|
hint.radio_button_interface = "";
|
2448 |
|
|
|
2449 |
|
|
// If the valuable is a loadable then it cannot be modified directly.
|
2450 |
|
|
// Changing the value means unloading and/or loading more data
|
2451 |
|
|
// into the configuration. This should always be handled via a
|
2452 |
|
|
// separate dialog, followed by a tree redisplay
|
2453 |
|
|
CdlConstLoadable loadable = dynamic_cast<CdlConstLoadable>(this);
|
2454 |
|
|
if (0 != loadable) {
|
2455 |
|
|
hint.value_widget = CdlValueWidget_Loadable;
|
2456 |
|
|
CYG_REPORT_RETURN();
|
2457 |
|
|
return;
|
2458 |
|
|
}
|
2459 |
|
|
|
2460 |
|
|
// If the valuable is not modifiable then we are already done.
|
2461 |
|
|
CdlValueFlavor flavor = this->get_flavor();
|
2462 |
|
|
if ((CdlValueFlavor_None == flavor) || !this->is_modifiable()) {
|
2463 |
|
|
CYG_REPORT_RETURN();
|
2464 |
|
|
return;
|
2465 |
|
|
}
|
2466 |
|
|
|
2467 |
|
|
// If there is a custom dialog and dialogs are enabled, use it.
|
2468 |
|
|
if (this->has_dialog() && CdlDialogBody::dialogs_are_enabled()) {
|
2469 |
|
|
if ((CdlValueFlavor_Bool == flavor) || (CdlValueFlavor_BoolData == flavor)) {
|
2470 |
|
|
hint.bool_widget = CdlBoolWidget_CustomDialog;
|
2471 |
|
|
}
|
2472 |
|
|
if ((CdlValueFlavor_Data == flavor) || (CdlValueFlavor_BoolData == flavor)) {
|
2473 |
|
|
hint.value_widget = CdlValueWidget_CustomDialog;
|
2474 |
|
|
}
|
2475 |
|
|
CYG_REPORT_RETURN();
|
2476 |
|
|
return;
|
2477 |
|
|
}
|
2478 |
|
|
|
2479 |
|
|
// Process the bool part, if any
|
2480 |
|
|
if ((CdlValueFlavor_Bool == flavor) || (CdlValueFlavor_BoolData == flavor)) {
|
2481 |
|
|
|
2482 |
|
|
// Default to a CheckButton
|
2483 |
|
|
hint.bool_widget = CdlBoolWidget_CheckButton;
|
2484 |
|
|
|
2485 |
|
|
// Under some circumstances it is appropriate to use a radio button instead.
|
2486 |
|
|
// This is the case when there are several mutually exclusive entities.
|
2487 |
|
|
// Most of the time radio buttons should actually be handled by a single
|
2488 |
|
|
// option which has a list of legal values. There are a couple of cases
|
2489 |
|
|
// where this is not appropriate:
|
2490 |
|
|
//
|
2491 |
|
|
// 1) grouping. Some of the mutually exclusive entities could be containers.
|
2492 |
|
|
// With clever use of a single option and some active_if properties it
|
2493 |
|
|
// would be possible to get almost the same effect, but not quite.
|
2494 |
|
|
//
|
2495 |
|
|
// 2) external packages. It should be possible to have a third party package
|
2496 |
|
|
// which could add e.g. a new scheduler.
|
2497 |
|
|
//
|
2498 |
|
|
// The implementation of this involves interfaces. Basically mutually
|
2499 |
|
|
// exclusive entities should implement the same interface, and that
|
2500 |
|
|
// interface should have an explicit requires $cdl_value == 1
|
2501 |
|
|
// In addition all of the options involved should have the same parent.
|
2502 |
|
|
// An entity may implement multiple interfaces, so they all have to be checked
|
2503 |
|
|
CdlInterface radio_interface = 0;
|
2504 |
|
|
std::vector<CdlProperty> implements = this->get_properties(CdlPropertyId_Implements);
|
2505 |
|
|
std::vector<CdlProperty>::const_iterator imp_i;
|
2506 |
|
|
for (imp_i = implements.begin(); (imp_i != implements.end()) && (0 == radio_interface); imp_i++) {
|
2507 |
|
|
CdlProperty_Reference refprop = dynamic_cast<CdlProperty_Reference>(*imp_i);
|
2508 |
|
|
CYG_ASSERT_CLASSC(refprop);
|
2509 |
|
|
|
2510 |
|
|
CdlNode destnode = refprop->get_destination();
|
2511 |
|
|
if (0 == destnode) {
|
2512 |
|
|
continue;
|
2513 |
|
|
}
|
2514 |
|
|
CdlInterface interface = dynamic_cast<CdlInterface>(destnode);
|
2515 |
|
|
CYG_ASSERT_CLASSC(interface);
|
2516 |
|
|
|
2517 |
|
|
std::vector<CdlProperty_GoalExpression> requires;
|
2518 |
|
|
std::vector<CdlProperty_GoalExpression>::const_iterator req_i;
|
2519 |
|
|
interface->get_requires_goals(requires);
|
2520 |
|
|
for (req_i = requires.begin(); req_i != requires.end(); req_i++) {
|
2521 |
|
|
|
2522 |
|
|
CdlExpression expr = (*req_i)->get_expression();
|
2523 |
|
|
CdlSubexpression& subexpr = expr->sub_expressions[expr->first_subexpression];
|
2524 |
|
|
if (CdlExprOp_Equal != subexpr.op) {
|
2525 |
|
|
continue;
|
2526 |
|
|
}
|
2527 |
|
|
|
2528 |
|
|
CdlSubexpression& lhs = expr->sub_expressions[subexpr.lhs_index];
|
2529 |
|
|
CdlSubexpression& rhs = expr->sub_expressions[subexpr.rhs_index];
|
2530 |
|
|
CdlSubexpression* ref_operand = &lhs;
|
2531 |
|
|
|
2532 |
|
|
// Allow for "a == 1" or "1 == a"
|
2533 |
|
|
if ((CdlExprOp_IntegerConstant == lhs.op) && (1 == lhs.constants.get_integer_value())) {
|
2534 |
|
|
ref_operand = &rhs;
|
2535 |
|
|
} else if ((CdlExprOp_IntegerConstant == rhs.op) && (1 == rhs.constants.get_integer_value())) {
|
2536 |
|
|
ref_operand = &lhs;
|
2537 |
|
|
} else {
|
2538 |
|
|
continue;
|
2539 |
|
|
}
|
2540 |
|
|
|
2541 |
|
|
if (CdlExprOp_Reference != ref_operand->op) {
|
2542 |
|
|
continue;
|
2543 |
|
|
}
|
2544 |
|
|
CdlReference& ref = expr->references[ref_operand->reference_index];
|
2545 |
|
|
if (ref.get_destination() == interface) {
|
2546 |
|
|
break;
|
2547 |
|
|
}
|
2548 |
|
|
}
|
2549 |
|
|
if (req_i == requires.end()) {
|
2550 |
|
|
continue;
|
2551 |
|
|
}
|
2552 |
|
|
|
2553 |
|
|
CdlContainer parent = this->get_parent();
|
2554 |
|
|
CYG_ASSERT_CLASSC(parent);
|
2555 |
|
|
|
2556 |
|
|
std::vector<CdlValuable> implementers;
|
2557 |
|
|
std::vector<CdlValuable>::const_iterator imp_i;
|
2558 |
|
|
interface->get_implementers(implementers);
|
2559 |
|
|
for (imp_i = implementers.begin(); imp_i != implementers.end(); imp_i++) {
|
2560 |
|
|
if (parent != (*imp_i)->get_parent()) {
|
2561 |
|
|
break;
|
2562 |
|
|
}
|
2563 |
|
|
}
|
2564 |
|
|
|
2565 |
|
|
if (imp_i == implementers.end()) {
|
2566 |
|
|
// An interface has been found that matches the constraints.
|
2567 |
|
|
radio_interface = interface;
|
2568 |
|
|
}
|
2569 |
|
|
}
|
2570 |
|
|
if (0 != radio_interface) {
|
2571 |
|
|
hint.bool_widget = CdlBoolWidget_Radio;
|
2572 |
|
|
hint.radio_button_interface = radio_interface->get_name();
|
2573 |
|
|
}
|
2574 |
|
|
}
|
2575 |
|
|
|
2576 |
|
|
// Process the data part, if any
|
2577 |
|
|
if ((CdlValueFlavor_Data == flavor) || (CdlValueFlavor_BoolData == flavor)) {
|
2578 |
|
|
|
2579 |
|
|
// Default to a simple entry box.
|
2580 |
|
|
hint.value_widget = CdlValueWidget_EntryBox;
|
2581 |
|
|
|
2582 |
|
|
// If there is a legal_values list, this will normally indicate
|
2583 |
|
|
// which widget should be used.
|
2584 |
|
|
if (this->has_legal_values()) {
|
2585 |
|
|
// The legal_values expression needs to be evaluated and examined.
|
2586 |
|
|
// If the result is a simple numerical range then all we need to
|
2587 |
|
|
// figure out is whether to default to decimal, hex, octal or double.
|
2588 |
|
|
// Otherwise if the result is a simple list and all of the entries
|
2589 |
|
|
// are numerical, that is sufficient information. If a list with
|
2590 |
|
|
// non-numerical entries that is fine as well. Anything more complicated
|
2591 |
|
|
// needs to revert to an entry box.
|
2592 |
|
|
CdlProperty_ListExpression lexpr = this->get_legal_values();
|
2593 |
|
|
CdlEvalContext context(0, this, lexpr);
|
2594 |
|
|
CdlListValue val;
|
2595 |
|
|
|
2596 |
|
|
try {
|
2597 |
|
|
lexpr->eval(context, val);
|
2598 |
|
|
const std::vector<CdlSimpleValue>& table = val.get_table();
|
2599 |
|
|
const std::vector<std::pair<cdl_int, cdl_int> >& int_ranges = val.get_integer_ranges();
|
2600 |
|
|
const std::vector<std::pair<double, double> >& double_ranges = val.get_double_ranges();
|
2601 |
|
|
|
2602 |
|
|
if ((0 == table.size()) && (0 == int_ranges.size()) && (1 == double_ranges.size())) {
|
2603 |
|
|
|
2604 |
|
|
// A straightforward range of double precision numbers
|
2605 |
|
|
hint.value_widget = CdlValueWidget_DoubleRange;
|
2606 |
|
|
|
2607 |
|
|
} else if ((0 == table.size()) && (1 == int_ranges.size()) && (0 == double_ranges.size())) {
|
2608 |
|
|
|
2609 |
|
|
// Bummer. The formatting information has been lost.
|
2610 |
|
|
// To fix this the two sets of ranges should be collapsed into pairs of
|
2611 |
|
|
// CdlSimpleValue's.
|
2612 |
|
|
hint.value_widget = CdlValueWidget_DecimalRange;
|
2613 |
|
|
|
2614 |
|
|
} else if ((1 <= table.size() && (0 == int_ranges.size()) && (0 == double_ranges.size()))) {
|
2615 |
|
|
|
2616 |
|
|
// If all of the values are numerical, then we have a numeric set.
|
2617 |
|
|
// Otherwise we have a string set.
|
2618 |
|
|
bool all_numeric = true;
|
2619 |
|
|
std::vector<CdlSimpleValue>::const_iterator tab_i;
|
2620 |
|
|
for (tab_i = table.begin(); (tab_i != table.end()) && all_numeric; tab_i++) {
|
2621 |
|
|
if (!tab_i->has_double_value() && !tab_i->has_integer_value()) {
|
2622 |
|
|
all_numeric = false;
|
2623 |
|
|
}
|
2624 |
|
|
}
|
2625 |
|
|
if (all_numeric) {
|
2626 |
|
|
hint.value_widget = CdlValueWidget_NumericSet;
|
2627 |
|
|
} else {
|
2628 |
|
|
hint.value_widget = CdlValueWidget_StringSet;
|
2629 |
|
|
}
|
2630 |
|
|
|
2631 |
|
|
} else {
|
2632 |
|
|
// The list expression is a complex combination. Leave it as an entry box.
|
2633 |
|
|
// In some cases it would be possible to do better, for example
|
2634 |
|
|
// legal_values -1 1 to 4 8 to 12
|
2635 |
|
|
// Support for cases like these may get added in future, if such cases
|
2636 |
|
|
// ever arise in practice.
|
2637 |
|
|
}
|
2638 |
|
|
|
2639 |
|
|
} catch(...) {
|
2640 |
|
|
// Not a lot that can be done here, unfortunately
|
2641 |
|
|
}
|
2642 |
|
|
} else {
|
2643 |
|
|
// There is no legal_values property, so an entry box is probably the
|
2644 |
|
|
// right thing to use. There is a special case for multiline strings,
|
2645 |
|
|
// identified by a default_value expression that contains a newline.
|
2646 |
|
|
if (this->has_default_value_expression()) {
|
2647 |
|
|
CdlProperty_Expression expr = this->get_default_value_expression();
|
2648 |
|
|
CdlEvalContext context(0, this, expr);
|
2649 |
|
|
CdlSimpleValue val;
|
2650 |
|
|
try {
|
2651 |
|
|
expr->eval(context, val);
|
2652 |
|
|
std::string tmp = val.get_value();
|
2653 |
|
|
if (std::string::npos != tmp.find('\n')) {
|
2654 |
|
|
hint.value_widget = CdlValueWidget_MultilineString;
|
2655 |
|
|
}
|
2656 |
|
|
} catch(...) {
|
2657 |
|
|
// Not a lot that can be done here, unfortunately
|
2658 |
|
|
}
|
2659 |
|
|
}
|
2660 |
|
|
}
|
2661 |
|
|
}
|
2662 |
|
|
|
2663 |
|
|
CYG_REPORT_RETURN();
|
2664 |
|
|
}
|
2665 |
|
|
|
2666 |
|
|
//}}}
|
2667 |
|
|
//{{{ CdlValuable get operations
|
2668 |
|
|
|
2669 |
|
|
// ----------------------------------------------------------------------------
|
2670 |
|
|
const CdlValue&
|
2671 |
|
|
CdlValuableBody::get_whole_value() const
|
2672 |
|
|
{
|
2673 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_whole_value", "result %p");
|
2674 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2675 |
|
|
CYG_PRECONDITION_THISC();
|
2676 |
|
|
|
2677 |
|
|
CYG_REPORT_RETVAL(&value);
|
2678 |
|
|
return value;
|
2679 |
|
|
}
|
2680 |
|
|
|
2681 |
|
|
CdlValueFlavor
|
2682 |
|
|
CdlValuableBody::get_flavor() const
|
2683 |
|
|
{
|
2684 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_flavor", "result %d");
|
2685 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2686 |
|
|
CYG_PRECONDITION_THISC();
|
2687 |
|
|
|
2688 |
|
|
CdlValueFlavor result = value.get_flavor();
|
2689 |
|
|
CYG_REPORT_RETVAL((int) result);
|
2690 |
|
|
return result;
|
2691 |
|
|
}
|
2692 |
|
|
|
2693 |
|
|
CdlValueSource
|
2694 |
|
|
CdlValuableBody::get_source() const
|
2695 |
|
|
{
|
2696 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_source", "result %d");
|
2697 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
2698 |
|
|
CYG_PRECONDITION_THISC();
|
2699 |
|
|
|
2700 |
|
|
CdlValueSource result = value.get_source();
|
2701 |
|
|
CYG_REPORT_RETVAL((int) result);
|
2702 |
|
|
return result;
|
2703 |
|
|
}
|
2704 |
|
|
|
2705 |
|
|
bool
|
2706 |
|
|
CdlValuableBody::has_source(CdlValueSource source) const
|
2707 |
|
|
{
|
2708 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_source", "result %d");
|
2709 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
2710 |
|
|
CYG_PRECONDITION_THISC();
|
2711 |
|
|
|
2712 |
|
|
bool result = value.has_source(source);
|
2713 |
|
|
CYG_REPORT_RETVAL(result);
|
2714 |
|
|
return result;
|
2715 |
|
|
}
|
2716 |
|
|
|
2717 |
|
|
bool
|
2718 |
|
|
CdlValuableBody::is_enabled(CdlValueSource source) const
|
2719 |
|
|
{
|
2720 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::is_enabled", "result %d");
|
2721 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
2722 |
|
|
CYG_PRECONDITION_THISC();
|
2723 |
|
|
|
2724 |
|
|
bool result = value.is_enabled(source);
|
2725 |
|
|
CYG_REPORT_RETVAL(result);
|
2726 |
|
|
return result;
|
2727 |
|
|
}
|
2728 |
|
|
|
2729 |
|
|
std::string
|
2730 |
|
|
CdlValuableBody::get_value(CdlValueSource source) const
|
2731 |
|
|
{
|
2732 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_value");
|
2733 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
2734 |
|
|
CYG_PRECONDITION_THISC();
|
2735 |
|
|
|
2736 |
|
|
std::string result = value.get_value(source);
|
2737 |
|
|
CYG_REPORT_RETURN();
|
2738 |
|
|
return result;
|
2739 |
|
|
}
|
2740 |
|
|
|
2741 |
|
|
bool
|
2742 |
|
|
CdlValuableBody::has_integer_value(CdlValueSource source) const
|
2743 |
|
|
{
|
2744 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_integer_value", "result %d");
|
2745 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
2746 |
|
|
CYG_PRECONDITION_THISC();
|
2747 |
|
|
|
2748 |
|
|
bool result = value.has_integer_value(source);
|
2749 |
|
|
CYG_REPORT_RETVAL(result);
|
2750 |
|
|
return result;
|
2751 |
|
|
}
|
2752 |
|
|
|
2753 |
|
|
cdl_int
|
2754 |
|
|
CdlValuableBody::get_integer_value(CdlValueSource source) const
|
2755 |
|
|
{
|
2756 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_integer_value", "result %d");
|
2757 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
2758 |
|
|
CYG_PRECONDITION_THISC();
|
2759 |
|
|
|
2760 |
|
|
cdl_int result = value.get_integer_value(source);
|
2761 |
|
|
CYG_REPORT_RETVAL((int) result);
|
2762 |
|
|
return result;
|
2763 |
|
|
}
|
2764 |
|
|
|
2765 |
|
|
bool
|
2766 |
|
|
CdlValuableBody::has_double_value(CdlValueSource source) const
|
2767 |
|
|
{
|
2768 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_double_value", "result %d");
|
2769 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
2770 |
|
|
CYG_PRECONDITION_THISC();
|
2771 |
|
|
|
2772 |
|
|
bool result = value.has_double_value(source);
|
2773 |
|
|
CYG_REPORT_RETVAL(result);
|
2774 |
|
|
return result;
|
2775 |
|
|
}
|
2776 |
|
|
|
2777 |
|
|
double
|
2778 |
|
|
CdlValuableBody::get_double_value(CdlValueSource source) const
|
2779 |
|
|
{
|
2780 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_double_value");
|
2781 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
2782 |
|
|
CYG_PRECONDITION_THISC();
|
2783 |
|
|
|
2784 |
|
|
double result = value.get_double_value();
|
2785 |
|
|
CYG_REPORT_RETURN();
|
2786 |
|
|
return result;
|
2787 |
|
|
}
|
2788 |
|
|
|
2789 |
|
|
CdlSimpleValue
|
2790 |
|
|
CdlValuableBody::get_simple_value(CdlValueSource source) const
|
2791 |
|
|
{
|
2792 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_simple_value");
|
2793 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
2794 |
|
|
CYG_PRECONDITION_THISC();
|
2795 |
|
|
|
2796 |
|
|
CdlSimpleValue result = value.get_simple_value(source);
|
2797 |
|
|
CYG_REPORT_RETURN();
|
2798 |
|
|
return result;
|
2799 |
|
|
}
|
2800 |
|
|
|
2801 |
|
|
// ----------------------------------------------------------------------------
|
2802 |
|
|
CdlValueSource
|
2803 |
|
|
CdlValuableBody::get_source(CdlTransaction transaction) const
|
2804 |
|
|
{
|
2805 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_source", "result %d");
|
2806 |
|
|
CYG_REPORT_FUNCARG2XV(this, transaction);
|
2807 |
|
|
CYG_PRECONDITION_THISC();
|
2808 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2809 |
|
|
|
2810 |
|
|
const CdlValue& transaction_value = transaction->get_whole_value(this);
|
2811 |
|
|
CdlValueSource result = transaction_value.get_source();
|
2812 |
|
|
CYG_REPORT_RETVAL((int) result);
|
2813 |
|
|
return result;
|
2814 |
|
|
}
|
2815 |
|
|
|
2816 |
|
|
bool
|
2817 |
|
|
CdlValuableBody::has_source(CdlTransaction transaction, CdlValueSource source) const
|
2818 |
|
|
{
|
2819 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_source", "result %d");
|
2820 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
2821 |
|
|
CYG_PRECONDITION_THISC();
|
2822 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2823 |
|
|
|
2824 |
|
|
const CdlValue& transaction_value = transaction->get_whole_value(this);
|
2825 |
|
|
bool result = transaction_value.has_source(source);
|
2826 |
|
|
CYG_REPORT_RETVAL(result);
|
2827 |
|
|
return result;
|
2828 |
|
|
}
|
2829 |
|
|
|
2830 |
|
|
bool
|
2831 |
|
|
CdlValuableBody::is_enabled(CdlTransaction transaction, CdlValueSource source) const
|
2832 |
|
|
{
|
2833 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::is_enabled", "result %d");
|
2834 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
2835 |
|
|
CYG_PRECONDITION_THISC();
|
2836 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2837 |
|
|
|
2838 |
|
|
const CdlValue& transaction_value = transaction->get_whole_value(this);
|
2839 |
|
|
bool result = transaction_value.is_enabled(source);
|
2840 |
|
|
CYG_REPORT_RETVAL(result);
|
2841 |
|
|
return result;
|
2842 |
|
|
}
|
2843 |
|
|
|
2844 |
|
|
std::string
|
2845 |
|
|
CdlValuableBody::get_value(CdlTransaction transaction, CdlValueSource source) const
|
2846 |
|
|
{
|
2847 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_value");
|
2848 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
2849 |
|
|
CYG_PRECONDITION_THISC();
|
2850 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2851 |
|
|
|
2852 |
|
|
const CdlValue& transaction_value = transaction->get_whole_value(this);
|
2853 |
|
|
std::string result = transaction_value.get_value(source);
|
2854 |
|
|
CYG_REPORT_RETURN();
|
2855 |
|
|
return result;
|
2856 |
|
|
}
|
2857 |
|
|
|
2858 |
|
|
bool
|
2859 |
|
|
CdlValuableBody::has_integer_value(CdlTransaction transaction, CdlValueSource source) const
|
2860 |
|
|
{
|
2861 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_integer_value", "result %d");
|
2862 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
2863 |
|
|
CYG_PRECONDITION_THISC();
|
2864 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2865 |
|
|
|
2866 |
|
|
const CdlValue& transaction_value = transaction->get_whole_value(this);
|
2867 |
|
|
bool result = transaction_value.has_integer_value(source);
|
2868 |
|
|
CYG_REPORT_RETVAL(result);
|
2869 |
|
|
return result;
|
2870 |
|
|
}
|
2871 |
|
|
|
2872 |
|
|
cdl_int
|
2873 |
|
|
CdlValuableBody::get_integer_value(CdlTransaction transaction, CdlValueSource source) const
|
2874 |
|
|
{
|
2875 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::get_integer_value", "result %d");
|
2876 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
2877 |
|
|
CYG_PRECONDITION_THISC();
|
2878 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2879 |
|
|
|
2880 |
|
|
const CdlValue& transaction_value = transaction->get_whole_value(this);
|
2881 |
|
|
cdl_int result = transaction_value.get_integer_value(source);
|
2882 |
|
|
CYG_REPORT_RETVAL((int) result);
|
2883 |
|
|
return result;
|
2884 |
|
|
}
|
2885 |
|
|
|
2886 |
|
|
bool
|
2887 |
|
|
CdlValuableBody::has_double_value(CdlTransaction transaction, CdlValueSource source) const
|
2888 |
|
|
{
|
2889 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::has_double_value", "result %d");
|
2890 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
2891 |
|
|
CYG_PRECONDITION_THISC();
|
2892 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2893 |
|
|
|
2894 |
|
|
const CdlValue& transaction_value = transaction->get_whole_value(this);
|
2895 |
|
|
bool result = transaction_value.has_double_value(source);
|
2896 |
|
|
CYG_REPORT_RETVAL(result);
|
2897 |
|
|
return result;
|
2898 |
|
|
}
|
2899 |
|
|
|
2900 |
|
|
double
|
2901 |
|
|
CdlValuableBody::get_double_value(CdlTransaction transaction, CdlValueSource source) const
|
2902 |
|
|
{
|
2903 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_double_value");
|
2904 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
2905 |
|
|
CYG_PRECONDITION_THISC();
|
2906 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2907 |
|
|
|
2908 |
|
|
const CdlValue& transaction_value = transaction->get_whole_value(this);
|
2909 |
|
|
double result = transaction_value.get_double_value();
|
2910 |
|
|
CYG_REPORT_RETURN();
|
2911 |
|
|
return result;
|
2912 |
|
|
}
|
2913 |
|
|
|
2914 |
|
|
CdlSimpleValue
|
2915 |
|
|
CdlValuableBody::get_simple_value(CdlTransaction transaction, CdlValueSource source) const
|
2916 |
|
|
{
|
2917 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_simple_value");
|
2918 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
2919 |
|
|
CYG_PRECONDITION_THISC();
|
2920 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2921 |
|
|
|
2922 |
|
|
const CdlValue& transaction_value = transaction->get_whole_value(this);
|
2923 |
|
|
CdlSimpleValue result = transaction_value.get_simple_value(source);
|
2924 |
|
|
CYG_REPORT_RETURN();
|
2925 |
|
|
return result;
|
2926 |
|
|
}
|
2927 |
|
|
|
2928 |
|
|
//}}}
|
2929 |
|
|
//{{{ CdlValuable internal modify ops
|
2930 |
|
|
|
2931 |
|
|
// ----------------------------------------------------------------------------
|
2932 |
|
|
// There has been a change to either the value itself or to the
|
2933 |
|
|
// set of legal values. It is necessary to validate the current
|
2934 |
|
|
// value, maintaining a suitable conflict object.
|
2935 |
|
|
void
|
2936 |
|
|
CdlValuableBody::check_value(CdlTransaction transaction)
|
2937 |
|
|
{
|
2938 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::check_value");
|
2939 |
|
|
CYG_REPORT_FUNCARG2XV(this, transaction);
|
2940 |
|
|
CYG_PRECONDITION_THISC();
|
2941 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
2942 |
|
|
|
2943 |
|
|
// Checking the value only makes sense for BoolData and Data
|
2944 |
|
|
// values.
|
2945 |
|
|
CdlValueFlavor flavor = value.get_flavor();
|
2946 |
|
|
if ((CdlValueFlavor_BoolData != flavor) && (CdlValueFlavor_Data != flavor)) {
|
2947 |
|
|
CYG_REPORT_RETURN();
|
2948 |
|
|
return;
|
2949 |
|
|
}
|
2950 |
|
|
|
2951 |
|
|
// If the valuable is not currently active and enabled then it
|
2952 |
|
|
// does not matter whether or not the value is legal. Any old
|
2953 |
|
|
// conflicts should be destroyed.
|
2954 |
|
|
if (!(transaction->is_active(this) && this->is_enabled(transaction))) {
|
2955 |
|
|
transaction->clear_conflicts(this, &CdlConflict_IllegalValueBody::test);
|
2956 |
|
|
CYG_REPORT_RETURN();
|
2957 |
|
|
return;
|
2958 |
|
|
}
|
2959 |
|
|
|
2960 |
|
|
// If there is a legal_values property, check membership.
|
2961 |
|
|
if (this->has_property(CdlPropertyId_LegalValues)) {
|
2962 |
|
|
CdlProperty_ListExpression lexpr = dynamic_cast<CdlProperty_ListExpression>(get_property(CdlPropertyId_LegalValues));
|
2963 |
|
|
CYG_ASSERT_CLASSC(lexpr);
|
2964 |
|
|
|
2965 |
|
|
CdlSimpleValue val = this->get_simple_value(transaction);
|
2966 |
|
|
CdlEvalContext context(transaction, this, lexpr);
|
2967 |
|
|
try {
|
2968 |
|
|
if (!lexpr->is_member(context, val)) {
|
2969 |
|
|
if (!transaction->has_conflict(this, lexpr, &CdlConflict_IllegalValueBody::test)) {
|
2970 |
|
|
CdlConflict_IllegalValueBody::make(transaction, this, lexpr);
|
2971 |
|
|
}
|
2972 |
|
|
|
2973 |
|
|
} else {
|
2974 |
|
|
// Tne current value is legal. Get rid of any old conflicts.
|
2975 |
|
|
transaction->clear_conflicts(this, lexpr, &CdlConflict_IllegalValueBody::test);
|
2976 |
|
|
}
|
2977 |
|
|
} catch(CdlEvalException e) {
|
2978 |
|
|
// There should now be an EvalException conflict for this
|
2979 |
|
|
// node, so there is no point in having an IllegalValue conflict
|
2980 |
|
|
// as well.
|
2981 |
|
|
transaction->clear_conflicts(this, lexpr, &CdlConflict_IllegalValueBody::test);
|
2982 |
|
|
}
|
2983 |
|
|
|
2984 |
|
|
// FIXME: add support for check_proc
|
2985 |
|
|
}
|
2986 |
|
|
|
2987 |
|
|
CYG_REPORT_RETURN();
|
2988 |
|
|
}
|
2989 |
|
|
|
2990 |
|
|
// ----------------------------------------------------------------------------
|
2991 |
|
|
// There has been a change that may affect "requires" properties.
|
2992 |
|
|
// Again do the necessary checking and maintain suitable conflict
|
2993 |
|
|
// objects.
|
2994 |
|
|
void
|
2995 |
|
|
CdlValuableBody::check_requires(CdlTransaction transaction)
|
2996 |
|
|
{
|
2997 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::check_requires");
|
2998 |
|
|
CYG_REPORT_FUNCARG2XV(this, transaction);
|
2999 |
|
|
CYG_PRECONDITION_THISC();
|
3000 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3001 |
|
|
|
3002 |
|
|
std::vector<CdlProperty> requires_properties;
|
3003 |
|
|
std::vector<CdlProperty>::const_iterator prop_i;
|
3004 |
|
|
get_properties(CdlPropertyId_Requires, requires_properties);
|
3005 |
|
|
for (prop_i = requires_properties.begin(); prop_i != requires_properties.end(); prop_i++) {
|
3006 |
|
|
|
3007 |
|
|
CdlProperty_GoalExpression gexpr = dynamic_cast<CdlProperty_GoalExpression>(*prop_i);
|
3008 |
|
|
CYG_ASSERT_CLASSC(gexpr);
|
3009 |
|
|
this->check_requires(transaction, gexpr);
|
3010 |
|
|
}
|
3011 |
|
|
|
3012 |
|
|
CYG_REPORT_RETURN();
|
3013 |
|
|
}
|
3014 |
|
|
|
3015 |
|
|
void
|
3016 |
|
|
CdlValuableBody::check_requires(CdlTransaction transaction, CdlProperty_GoalExpression gexpr)
|
3017 |
|
|
{
|
3018 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::check_requires (property)");
|
3019 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, gexpr);
|
3020 |
|
|
CYG_PRECONDITION_THISC();
|
3021 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3022 |
|
|
CYG_ASSERT_CLASSC(gexpr);
|
3023 |
|
|
|
3024 |
|
|
// If the valuable is not currently active and enabled then the "requires"
|
3025 |
|
|
// properties are irrelevant, and any old conflicts should be destroyed.
|
3026 |
|
|
if (!transaction->is_active(this) || !this->is_enabled(transaction)) {
|
3027 |
|
|
transaction->clear_conflicts(this, gexpr, &CdlConflict_RequiresBody::test);
|
3028 |
|
|
CYG_REPORT_RETURN();
|
3029 |
|
|
return;
|
3030 |
|
|
}
|
3031 |
|
|
|
3032 |
|
|
// What is the current value of the goal expression?
|
3033 |
|
|
try {
|
3034 |
|
|
CdlEvalContext context(transaction, this, gexpr);
|
3035 |
|
|
if (gexpr->eval(context)) {
|
3036 |
|
|
// The goal is satisfied.
|
3037 |
|
|
transaction->clear_conflicts(this, gexpr, &CdlConflict_RequiresBody::test);
|
3038 |
|
|
} else {
|
3039 |
|
|
// The goal is not satisfied. Make sure there is a conflict object.
|
3040 |
|
|
if (!transaction->has_conflict(this, gexpr, &CdlConflict_RequiresBody::test)) {
|
3041 |
|
|
CdlConflict_RequiresBody::make(transaction, this, gexpr);
|
3042 |
|
|
}
|
3043 |
|
|
}
|
3044 |
|
|
} catch(CdlEvalException e) {
|
3045 |
|
|
// There should now be an EvalException conflict associated with this node,
|
3046 |
|
|
// having a requires conflict as well serves no purpose
|
3047 |
|
|
transaction->clear_conflicts(this, gexpr, &CdlConflict_RequiresBody::test);
|
3048 |
|
|
}
|
3049 |
|
|
|
3050 |
|
|
CYG_REPORT_RETURN();
|
3051 |
|
|
}
|
3052 |
|
|
|
3053 |
|
|
// ----------------------------------------------------------------------------
|
3054 |
|
|
// The update handler. If there is a change to the value or active state
|
3055 |
|
|
// then it is necessary to reevaluate any requires properties, and to
|
3056 |
|
|
// check whether or not the value is legal wrt legal_values etc.
|
3057 |
|
|
void
|
3058 |
|
|
CdlValuableBody::update(CdlTransaction transaction, CdlUpdate update)
|
3059 |
|
|
{
|
3060 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::update");
|
3061 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, update);
|
3062 |
|
|
CYG_PRECONDITION_THISC();
|
3063 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3064 |
|
|
|
3065 |
|
|
if ((CdlUpdate_ValueChange == update) || (CdlUpdate_ActiveChange == update)) {
|
3066 |
|
|
this->check_value(transaction);
|
3067 |
|
|
this->check_requires(transaction);
|
3068 |
|
|
}
|
3069 |
|
|
|
3070 |
|
|
CYG_REPORT_RETURN();
|
3071 |
|
|
}
|
3072 |
|
|
|
3073 |
|
|
// ----------------------------------------------------------------------------
|
3074 |
|
|
// Should this node be active. In addition to the base class' checks that
|
3075 |
|
|
// the parent is active and enabled, any active_if constraints need
|
3076 |
|
|
// to be evaluated.
|
3077 |
|
|
|
3078 |
|
|
bool
|
3079 |
|
|
CdlValuableBody::test_active(CdlTransaction transaction)
|
3080 |
|
|
{
|
3081 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::test_active", "result %d");
|
3082 |
|
|
CYG_REPORT_FUNCARG2XV(this, transaction);
|
3083 |
|
|
CYG_PRECONDITION_THISC();
|
3084 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3085 |
|
|
|
3086 |
|
|
bool result = true;
|
3087 |
|
|
if (!this->CdlNodeBody::test_active(transaction)) {
|
3088 |
|
|
result = false;
|
3089 |
|
|
}
|
3090 |
|
|
|
3091 |
|
|
if (result) {
|
3092 |
|
|
std::vector<CdlProperty> active_if_properties;
|
3093 |
|
|
std::vector<CdlProperty>::const_iterator prop_i;
|
3094 |
|
|
|
3095 |
|
|
this->get_properties(CdlPropertyId_ActiveIf, active_if_properties);
|
3096 |
|
|
for (prop_i = active_if_properties.begin(); result && (prop_i != active_if_properties.end()); prop_i++) {
|
3097 |
|
|
|
3098 |
|
|
CdlProperty_GoalExpression gexpr = dynamic_cast<CdlProperty_GoalExpression>(*prop_i);
|
3099 |
|
|
CYG_ASSERT_CLASSC(gexpr);
|
3100 |
|
|
CdlEvalContext context(transaction, this, gexpr);
|
3101 |
|
|
try {
|
3102 |
|
|
if (!gexpr->eval(context)) {
|
3103 |
|
|
result = false;
|
3104 |
|
|
}
|
3105 |
|
|
} catch(CdlEvalException e) {
|
3106 |
|
|
// Hmmm, an active_if property cannot be evaluated.
|
3107 |
|
|
// Tricky. If the node is inactive then its conflicts
|
3108 |
|
|
// are ignored, which would be a bad thing. For now
|
3109 |
|
|
// assume that the node is active, unless it was already
|
3110 |
|
|
// inactive for other reasons.
|
3111 |
|
|
}
|
3112 |
|
|
}
|
3113 |
|
|
}
|
3114 |
|
|
|
3115 |
|
|
CYG_REPORT_RETVAL(result);
|
3116 |
|
|
return result;
|
3117 |
|
|
}
|
3118 |
|
|
|
3119 |
|
|
//}}}
|
3120 |
|
|
//{{{ CdlValuable modify operations
|
3121 |
|
|
|
3122 |
|
|
// ----------------------------------------------------------------------------
|
3123 |
|
|
// Start with the non-transaction versions. These allocate a new transaction,
|
3124 |
|
|
// perform their operation in the context of that transaction, and then
|
3125 |
|
|
// commit the transaction.
|
3126 |
|
|
|
3127 |
|
|
void
|
3128 |
|
|
CdlValuableBody::set_source(CdlValueSource source)
|
3129 |
|
|
{
|
3130 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set_source (no transaction)");
|
3131 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
3132 |
|
|
CYG_PRECONDITION_THISC();
|
3133 |
|
|
|
3134 |
|
|
CdlTransaction transaction = CdlTransactionBody::make(get_toplevel());
|
3135 |
|
|
this->set_source(transaction, source);
|
3136 |
|
|
transaction->body();
|
3137 |
|
|
delete transaction;
|
3138 |
|
|
|
3139 |
|
|
CYG_REPORT_RETURN();
|
3140 |
|
|
}
|
3141 |
|
|
|
3142 |
|
|
void
|
3143 |
|
|
CdlValuableBody::invalidate_source(CdlValueSource source)
|
3144 |
|
|
{
|
3145 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::invalidate_source (no transaction)");
|
3146 |
|
|
CYG_REPORT_FUNCARG2XV(this, source);
|
3147 |
|
|
CYG_PRECONDITION_THISC();
|
3148 |
|
|
|
3149 |
|
|
CdlTransaction transaction = CdlTransactionBody::make(get_toplevel());
|
3150 |
|
|
this->invalidate_source(transaction, source);
|
3151 |
|
|
transaction->body();
|
3152 |
|
|
delete transaction;
|
3153 |
|
|
|
3154 |
|
|
CYG_REPORT_RETURN();
|
3155 |
|
|
}
|
3156 |
|
|
|
3157 |
|
|
void
|
3158 |
|
|
CdlValuableBody::set_enabled(bool val, CdlValueSource source)
|
3159 |
|
|
{
|
3160 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set_enabled (no transaction)");
|
3161 |
|
|
CYG_REPORT_FUNCARG3XV(this, val, source);
|
3162 |
|
|
CYG_PRECONDITION_THISC();
|
3163 |
|
|
|
3164 |
|
|
CdlTransaction transaction = CdlTransactionBody::make(get_toplevel());
|
3165 |
|
|
this->set_enabled(transaction, val, source);
|
3166 |
|
|
transaction->body();
|
3167 |
|
|
delete transaction;
|
3168 |
|
|
|
3169 |
|
|
CYG_REPORT_RETURN();
|
3170 |
|
|
}
|
3171 |
|
|
|
3172 |
|
|
void
|
3173 |
|
|
CdlValuableBody::set_value(CdlSimpleValue& val, CdlValueSource source)
|
3174 |
|
|
{
|
3175 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set_value (no transaction)");
|
3176 |
|
|
CYG_REPORT_FUNCARG3XV(this, &val, source);
|
3177 |
|
|
CYG_PRECONDITION_THISC();
|
3178 |
|
|
|
3179 |
|
|
CdlTransaction transaction = CdlTransactionBody::make(get_toplevel());
|
3180 |
|
|
this->set_value(transaction, val, source);
|
3181 |
|
|
transaction->body();
|
3182 |
|
|
delete transaction;
|
3183 |
|
|
|
3184 |
|
|
CYG_REPORT_RETURN();
|
3185 |
|
|
}
|
3186 |
|
|
|
3187 |
|
|
void
|
3188 |
|
|
CdlValuableBody::set_enabled_and_value(bool enabled_arg, CdlSimpleValue& val, CdlValueSource source)
|
3189 |
|
|
{
|
3190 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set_enabled_and_value (no transaction)");
|
3191 |
|
|
CYG_REPORT_FUNCARG4XV(this, enabled_arg, &val, source);
|
3192 |
|
|
CYG_PRECONDITION_THISC();
|
3193 |
|
|
|
3194 |
|
|
CdlTransaction transaction = CdlTransactionBody::make(get_toplevel());
|
3195 |
|
|
this->set_enabled_and_value(transaction, enabled_arg, val, source);
|
3196 |
|
|
transaction->body();
|
3197 |
|
|
delete transaction;
|
3198 |
|
|
|
3199 |
|
|
CYG_REPORT_RETURN();
|
3200 |
|
|
}
|
3201 |
|
|
|
3202 |
|
|
void
|
3203 |
|
|
CdlValuableBody::set(CdlSimpleValue& val, CdlValueSource source)
|
3204 |
|
|
{
|
3205 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set (no transaction)");
|
3206 |
|
|
CYG_REPORT_FUNCARG3XV(this, &val, source);
|
3207 |
|
|
CYG_PRECONDITION_THISC();
|
3208 |
|
|
|
3209 |
|
|
CdlTransaction transaction = CdlTransactionBody::make(get_toplevel());
|
3210 |
|
|
this->set(transaction, val, source);
|
3211 |
|
|
transaction->body();
|
3212 |
|
|
delete transaction;
|
3213 |
|
|
|
3214 |
|
|
CYG_REPORT_RETURN();
|
3215 |
|
|
}
|
3216 |
|
|
|
3217 |
|
|
// ----------------------------------------------------------------------------
|
3218 |
|
|
// These member functions operate in the context of a transaction. The
|
3219 |
|
|
// basic format is:
|
3220 |
|
|
//
|
3221 |
|
|
// 1) find out the state before the change
|
3222 |
|
|
// 2) make a local CdlValue copy, and modify it.
|
3223 |
|
|
// 3) update the value held in the transaction.
|
3224 |
|
|
//
|
3225 |
|
|
// Values checks etc. happen during propagation, mainly from inside
|
3226 |
|
|
// the update handler. There is code in CdlTransaction::set_whole_value()
|
3227 |
|
|
// to avoid unnecessary propagation.
|
3228 |
|
|
|
3229 |
|
|
void
|
3230 |
|
|
CdlValuableBody::set_source(CdlTransaction transaction, CdlValueSource source)
|
3231 |
|
|
{
|
3232 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set_source");
|
3233 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
3234 |
|
|
CYG_ASSERTC((source == CdlValueSource_Default) || !has_property(CdlPropertyId_Calculated));
|
3235 |
|
|
CYG_PRECONDITION_THISC();
|
3236 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3237 |
|
|
|
3238 |
|
|
const CdlValue& old_value = transaction->get_whole_value(this);
|
3239 |
|
|
CdlValue new_value = old_value;
|
3240 |
|
|
new_value.set_source(source);
|
3241 |
|
|
transaction->set_whole_value(this, old_value, new_value);
|
3242 |
|
|
|
3243 |
|
|
CYG_REPORT_RETURN();
|
3244 |
|
|
}
|
3245 |
|
|
|
3246 |
|
|
void
|
3247 |
|
|
CdlValuableBody::invalidate_source(CdlTransaction transaction, CdlValueSource source)
|
3248 |
|
|
{
|
3249 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::invalidate_source");
|
3250 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
3251 |
|
|
CYG_PRECONDITION_THISC();
|
3252 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3253 |
|
|
|
3254 |
|
|
const CdlValue& old_value = transaction->get_whole_value(this);
|
3255 |
|
|
CdlValue new_value = old_value;
|
3256 |
|
|
new_value.invalidate_source(source);
|
3257 |
|
|
transaction->set_whole_value(this, old_value, new_value);
|
3258 |
|
|
|
3259 |
|
|
CYG_REPORT_RETURN();
|
3260 |
|
|
}
|
3261 |
|
|
|
3262 |
|
|
void
|
3263 |
|
|
CdlValuableBody::set_enabled(CdlTransaction transaction, bool enabled_arg, CdlValueSource source)
|
3264 |
|
|
{
|
3265 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set_enabled");
|
3266 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
3267 |
|
|
CYG_ASSERTC((source == CdlValueSource_Default) || !has_property(CdlPropertyId_Calculated));
|
3268 |
|
|
CYG_PRECONDITION_THISC();
|
3269 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3270 |
|
|
|
3271 |
|
|
const CdlValue& old_value = transaction->get_whole_value(this);
|
3272 |
|
|
CdlValue new_value = old_value;
|
3273 |
|
|
new_value.set_enabled(enabled_arg, source);
|
3274 |
|
|
transaction->set_whole_value(this, old_value, new_value);
|
3275 |
|
|
|
3276 |
|
|
CYG_REPORT_RETURN();
|
3277 |
|
|
}
|
3278 |
|
|
|
3279 |
|
|
void
|
3280 |
|
|
CdlValuableBody::set_value(CdlTransaction transaction, CdlSimpleValue& val, CdlValueSource source)
|
3281 |
|
|
{
|
3282 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set_enabled");
|
3283 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
3284 |
|
|
CYG_ASSERTC((source == CdlValueSource_Default) || !has_property(CdlPropertyId_Calculated));
|
3285 |
|
|
CYG_PRECONDITION_THISC();
|
3286 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3287 |
|
|
|
3288 |
|
|
const CdlValue& old_value = transaction->get_whole_value(this);
|
3289 |
|
|
CdlValue new_value = old_value;
|
3290 |
|
|
new_value.set_value(val, source);
|
3291 |
|
|
transaction->set_whole_value(this, old_value, new_value);
|
3292 |
|
|
|
3293 |
|
|
CYG_REPORT_RETURN();
|
3294 |
|
|
}
|
3295 |
|
|
|
3296 |
|
|
void
|
3297 |
|
|
CdlValuableBody::set_enabled_and_value(CdlTransaction transaction, bool enabled_arg, CdlSimpleValue& val,
|
3298 |
|
|
CdlValueSource source)
|
3299 |
|
|
{
|
3300 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set_enabled");
|
3301 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
3302 |
|
|
CYG_ASSERTC((source == CdlValueSource_Default) || !has_property(CdlPropertyId_Calculated));
|
3303 |
|
|
CYG_PRECONDITION_THISC();
|
3304 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3305 |
|
|
|
3306 |
|
|
const CdlValue& old_value = transaction->get_whole_value(this);
|
3307 |
|
|
CdlValue new_value = old_value;
|
3308 |
|
|
new_value.set_enabled_and_value(enabled_arg, val, source);
|
3309 |
|
|
transaction->set_whole_value(this, old_value, new_value);
|
3310 |
|
|
|
3311 |
|
|
CYG_REPORT_RETURN();
|
3312 |
|
|
}
|
3313 |
|
|
|
3314 |
|
|
void
|
3315 |
|
|
CdlValuableBody::set(CdlTransaction transaction, CdlSimpleValue& val, CdlValueSource source)
|
3316 |
|
|
{
|
3317 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set");
|
3318 |
|
|
CYG_REPORT_FUNCARG3XV(this, transaction, source);
|
3319 |
|
|
CYG_ASSERTC((source == CdlValueSource_Default) || !has_property(CdlPropertyId_Calculated));
|
3320 |
|
|
CYG_PRECONDITION_THISC();
|
3321 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3322 |
|
|
|
3323 |
|
|
const CdlValue& old_value = transaction->get_whole_value(this);
|
3324 |
|
|
CdlValue new_value = old_value;
|
3325 |
|
|
new_value.set(val, source);
|
3326 |
|
|
transaction->set_whole_value(this, old_value, new_value);
|
3327 |
|
|
|
3328 |
|
|
CYG_REPORT_RETURN();
|
3329 |
|
|
}
|
3330 |
|
|
|
3331 |
|
|
void
|
3332 |
|
|
CdlValuableBody::set(CdlTransaction transaction, const CdlValue& val)
|
3333 |
|
|
{
|
3334 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::set");
|
3335 |
|
|
CYG_REPORT_FUNCARG2XV(this, transaction);
|
3336 |
|
|
CYG_PRECONDITION_THISC();
|
3337 |
|
|
CYG_PRECONDITION_CLASSC(transaction);
|
3338 |
|
|
|
3339 |
|
|
const CdlValue& old_value = transaction->get_whole_value(this);
|
3340 |
|
|
CdlValue new_value = val;
|
3341 |
|
|
transaction->set_whole_value(this, old_value, new_value);
|
3342 |
|
|
|
3343 |
|
|
CYG_REPORT_RETURN();
|
3344 |
|
|
}
|
3345 |
|
|
|
3346 |
|
|
//}}}
|
3347 |
|
|
//{{{ CdlValuable basics
|
3348 |
|
|
|
3349 |
|
|
// ----------------------------------------------------------------------------
|
3350 |
|
|
// The CdlValuable class implements the concept of CDL objects that take
|
3351 |
|
|
// a value. There are lots of properties associated with that.
|
3352 |
|
|
|
3353 |
|
|
CdlValuableBody::CdlValuableBody(CdlValueFlavor flavor)
|
3354 |
|
|
: value(flavor)
|
3355 |
|
|
{
|
3356 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable:: default constructor");
|
3357 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
3358 |
|
|
|
3359 |
|
|
cdlvaluablebody_cookie = CdlValuableBody_Magic;
|
3360 |
|
|
CYGDBG_MEMLEAK_CONSTRUCTOR();
|
3361 |
|
|
|
3362 |
|
|
CYG_POSTCONDITION_THISC();
|
3363 |
|
|
CYG_REPORT_RETURN();
|
3364 |
|
|
}
|
3365 |
|
|
|
3366 |
|
|
CdlValuableBody::~CdlValuableBody()
|
3367 |
|
|
{
|
3368 |
|
|
CYG_REPORT_FUNCNAME("CdlValuableBody:: destructor");
|
3369 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
3370 |
|
|
CYG_PRECONDITION_THISC();
|
3371 |
|
|
|
3372 |
|
|
cdlvaluablebody_cookie = CdlValuableBody_Invalid;
|
3373 |
|
|
CYGDBG_MEMLEAK_DESTRUCTOR();
|
3374 |
|
|
|
3375 |
|
|
CYG_REPORT_RETURN();
|
3376 |
|
|
}
|
3377 |
|
|
|
3378 |
|
|
// ----------------------------------------------------------------------------
|
3379 |
|
|
|
3380 |
|
|
std::string
|
3381 |
|
|
CdlValuableBody::get_class_name() const
|
3382 |
|
|
{
|
3383 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::get_class_name");
|
3384 |
|
|
CYG_PRECONDITION_THISC();
|
3385 |
|
|
CYG_REPORT_RETURN();
|
3386 |
|
|
return "valuable";
|
3387 |
|
|
}
|
3388 |
|
|
|
3389 |
|
|
// ----------------------------------------------------------------------------
|
3390 |
|
|
bool
|
3391 |
|
|
CdlValuableBody::check_this(cyg_assert_class_zeal zeal) const
|
3392 |
|
|
{
|
3393 |
|
|
if (CdlValuableBody_Magic != cdlvaluablebody_cookie) {
|
3394 |
|
|
return false;
|
3395 |
|
|
}
|
3396 |
|
|
CYGDBG_MEMLEAK_CHECKTHIS();
|
3397 |
|
|
|
3398 |
|
|
if (has_property(CdlPropertyId_Calculated) && (CdlValueSource_Default != value.get_source())) {
|
3399 |
|
|
CYG_FAIL("Calculated valuables can only have a default value.");
|
3400 |
|
|
return false;
|
3401 |
|
|
}
|
3402 |
|
|
|
3403 |
|
|
return CdlNodeBody::check_this(zeal) && value.check_this(zeal);
|
3404 |
|
|
}
|
3405 |
|
|
|
3406 |
|
|
//}}}
|
3407 |
|
|
//{{{ CdlValuable parsing support
|
3408 |
|
|
|
3409 |
|
|
// ----------------------------------------------------------------------------
|
3410 |
|
|
// Parsing support. Adding the appropriate parsers is straightforward.
|
3411 |
|
|
|
3412 |
|
|
void
|
3413 |
|
|
CdlValuableBody::add_property_parsers(std::vector<CdlInterpreterCommandEntry>& parsers)
|
3414 |
|
|
{
|
3415 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::add_property_parsers");
|
3416 |
|
|
|
3417 |
|
|
static CdlInterpreterCommandEntry commands[] =
|
3418 |
|
|
{
|
3419 |
|
|
CdlInterpreterCommandEntry("active_if", &parse_active_if ),
|
3420 |
|
|
CdlInterpreterCommandEntry("calculated", &parse_calculated ),
|
3421 |
|
|
CdlInterpreterCommandEntry("check_proc", &parse_check_proc ),
|
3422 |
|
|
CdlInterpreterCommandEntry("default_value", &parse_default_value),
|
3423 |
|
|
CdlInterpreterCommandEntry("dialog", &parse_dialog ),
|
3424 |
|
|
CdlInterpreterCommandEntry("entry_proc", &parse_entry_proc ),
|
3425 |
|
|
CdlInterpreterCommandEntry("flavor", &parse_flavor ),
|
3426 |
|
|
CdlInterpreterCommandEntry("group", &parse_group ),
|
3427 |
|
|
CdlInterpreterCommandEntry("implements", &parse_implements ),
|
3428 |
|
|
CdlInterpreterCommandEntry("legal_values", &parse_legal_values ),
|
3429 |
|
|
CdlInterpreterCommandEntry("requires", &parse_requires ),
|
3430 |
|
|
CdlInterpreterCommandEntry("wizard", &parse_wizard ),
|
3431 |
|
|
CdlInterpreterCommandEntry("", 0 )
|
3432 |
|
|
};
|
3433 |
|
|
|
3434 |
|
|
for (int i = 0; commands[i].command != 0; i++) {
|
3435 |
|
|
std::vector<CdlInterpreterCommandEntry>::const_iterator j;
|
3436 |
|
|
for (j = parsers.begin(); j != parsers.end(); j++) {
|
3437 |
|
|
if (commands[i].name == j->name) {
|
3438 |
|
|
if (commands[i].command != j->command) {
|
3439 |
|
|
CYG_FAIL("Property names are being re-used");
|
3440 |
|
|
}
|
3441 |
|
|
break;
|
3442 |
|
|
}
|
3443 |
|
|
}
|
3444 |
|
|
if (j == parsers.end()) {
|
3445 |
|
|
parsers.push_back(commands[i]);
|
3446 |
|
|
}
|
3447 |
|
|
}
|
3448 |
|
|
CdlNodeBody::add_property_parsers(parsers);
|
3449 |
|
|
|
3450 |
|
|
CYG_REPORT_RETURN();
|
3451 |
|
|
}
|
3452 |
|
|
|
3453 |
|
|
// Validatation is quite a bit more complicated...
|
3454 |
|
|
void
|
3455 |
|
|
CdlValuableBody::check_properties(CdlInterpreter interp)
|
3456 |
|
|
{
|
3457 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::check_properties");
|
3458 |
|
|
CYG_REPORT_FUNCARG2XV(this, interp);
|
3459 |
|
|
CYG_PRECONDITION_THISC();
|
3460 |
|
|
CYG_PRECONDITION_CLASSC(interp);
|
3461 |
|
|
|
3462 |
|
|
// There should be at most one of flavor, entry_proc, check_proc,
|
3463 |
|
|
// default_value, legal_values, dialog, and calculated. There can
|
3464 |
|
|
// be any number of active_if, requires, and implements.
|
3465 |
|
|
// NOTE: should multiple entry_proc's and check_proc's be allowed?
|
3466 |
|
|
// This could prove useful if there are a sensible number
|
3467 |
|
|
// of library check_proc's.
|
3468 |
|
|
if (count_properties(CdlPropertyId_Flavor) > 1) {
|
3469 |
|
|
CdlParse::report_error(interp, "", "There should be at most one flavor property.");
|
3470 |
|
|
}
|
3471 |
|
|
if (count_properties(CdlPropertyId_EntryProc) > 1) {
|
3472 |
|
|
CdlParse::report_error(interp, "", "There should be at most one entry_proc property.");
|
3473 |
|
|
}
|
3474 |
|
|
if (count_properties(CdlPropertyId_CheckProc) > 1) {
|
3475 |
|
|
CdlParse::report_error(interp, "", "There should be at most one check_proc property.");
|
3476 |
|
|
}
|
3477 |
|
|
if (count_properties(CdlPropertyId_DefaultValue) > 1) {
|
3478 |
|
|
CdlParse::report_error(interp, "", "There should be at most one default_value property.");
|
3479 |
|
|
}
|
3480 |
|
|
if (count_properties(CdlPropertyId_LegalValues) > 1) {
|
3481 |
|
|
CdlParse::report_error(interp, "", "There should be at most one legal_values property.");
|
3482 |
|
|
}
|
3483 |
|
|
if (count_properties(CdlPropertyId_Dialog) > 1) {
|
3484 |
|
|
CdlParse::report_error(interp, "", "There should be at most one dialog property.");
|
3485 |
|
|
}
|
3486 |
|
|
if (count_properties(CdlPropertyId_Wizard) > 1) {
|
3487 |
|
|
CdlParse::report_error(interp, "", "There should be at most one wizard property.");
|
3488 |
|
|
}
|
3489 |
|
|
if (count_properties(CdlPropertyId_Calculated) > 1) {
|
3490 |
|
|
CdlParse::report_error(interp, "", "There should be at most one calculated property.");
|
3491 |
|
|
}
|
3492 |
|
|
|
3493 |
|
|
// If there is a flavor property, update the flavor in the base class
|
3494 |
|
|
if (has_property(CdlPropertyId_Flavor)) {
|
3495 |
|
|
CdlProperty_String flavor_property = dynamic_cast<CdlProperty_String>(get_property(CdlPropertyId_Flavor));
|
3496 |
|
|
CYG_ASSERTC(0 != flavor_property);
|
3497 |
|
|
|
3498 |
|
|
std::string flavor_string = flavor_property->get_string();
|
3499 |
|
|
CdlValueFlavor flavor;
|
3500 |
|
|
// The property parsing code should have caught any problems already.
|
3501 |
|
|
if (!Cdl::string_to_flavor(flavor_string, flavor)) {
|
3502 |
|
|
CdlParse::report_error(interp, "", "Invalid flavor " + flavor_string);
|
3503 |
|
|
} else {
|
3504 |
|
|
value.set_flavor(flavor);
|
3505 |
|
|
}
|
3506 |
|
|
|
3507 |
|
|
// If the flavor is "none" then the entity is not modifiable,
|
3508 |
|
|
// and most of the properties do not make sense. However this
|
3509 |
|
|
// is not enforced at parse-time: temporarily switching to
|
3510 |
|
|
// flavor none may make sense during debugging.
|
3511 |
|
|
// FIXME: no longer correct
|
3512 |
|
|
}
|
3513 |
|
|
|
3514 |
|
|
// For boolean entities legal_values does not make much sense.
|
3515 |
|
|
// In theory a legal_values property could be used to restrict
|
3516 |
|
|
// the value to just true or just false, but the same effect
|
3517 |
|
|
// can be achieved more sensibly with a "requires" property.
|
3518 |
|
|
//
|
3519 |
|
|
// check_proc is allowed, this can be used to check programatically
|
3520 |
|
|
// that the current value is legal.
|
3521 |
|
|
if (CdlValueFlavor_Bool == get_flavor()) {
|
3522 |
|
|
if (has_property(CdlPropertyId_LegalValues)) {
|
3523 |
|
|
CdlParse::report_error(interp, "", "The \"legal_values\" property is not applicable to boolean entities.");
|
3524 |
|
|
}
|
3525 |
|
|
}
|
3526 |
|
|
|
3527 |
|
|
// default_value and calculated are mutually exclusive
|
3528 |
|
|
if (has_property(CdlPropertyId_Calculated) && has_property(CdlPropertyId_DefaultValue)) {
|
3529 |
|
|
CdlParse::report_error(interp, "", "The properties \"default_value\" and \"calculated\" cannot be used together.");
|
3530 |
|
|
}
|
3531 |
|
|
|
3532 |
|
|
#if 0
|
3533 |
|
|
// Dialog is not mutually exclusive with entry_proc.
|
3534 |
|
|
// Custom dialogs may not be supported, in which case it is likely that
|
3535 |
|
|
// a text entry widget will be used and an entry_proc may well be
|
3536 |
|
|
// applicable.
|
3537 |
|
|
if (has_property(CdlPropertyId_Dialog) && has_property(CdlPropertyId_EntryProc)) {
|
3538 |
|
|
CdlParse::report_error(interp, "", "The properties \"dialog\" and \"entry_proc\" cannot be used together.");
|
3539 |
|
|
}
|
3540 |
|
|
#endif
|
3541 |
|
|
|
3542 |
|
|
// All of the expressions may be invalid because of unresolved references,
|
3543 |
|
|
// ditto for implements and for dialog.
|
3544 |
|
|
|
3545 |
|
|
CdlNodeBody::check_properties(interp);
|
3546 |
|
|
|
3547 |
|
|
CYG_REPORT_RETURN();
|
3548 |
|
|
}
|
3549 |
|
|
|
3550 |
|
|
//}}}
|
3551 |
|
|
//{{{ CdlValuable persistence support
|
3552 |
|
|
|
3553 |
|
|
// ----------------------------------------------------------------------------
|
3554 |
|
|
void
|
3555 |
|
|
CdlValuableBody::initialize_savefile_support(CdlToplevel toplevel, std::string major_command)
|
3556 |
|
|
{
|
3557 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::initialize_savefile_support");
|
3558 |
|
|
CYG_PRECONDITION_CLASSC(toplevel);
|
3559 |
|
|
CYG_PRECONDITIONC("" != major_command);
|
3560 |
|
|
|
3561 |
|
|
toplevel->add_savefile_subcommand(major_command, "value_source", 0, &savefile_value_source_command);
|
3562 |
|
|
toplevel->add_savefile_subcommand(major_command, "user_value", 0, &savefile_user_value_command);
|
3563 |
|
|
toplevel->add_savefile_subcommand(major_command, "wizard_value", 0, &savefile_wizard_value_command);
|
3564 |
|
|
toplevel->add_savefile_subcommand(major_command, "inferred_value", 0, &savefile_inferred_value_command);
|
3565 |
|
|
|
3566 |
|
|
CYG_REPORT_RETURN();
|
3567 |
|
|
}
|
3568 |
|
|
|
3569 |
|
|
// ----------------------------------------------------------------------------
|
3570 |
|
|
// Is a savefile entry actually needed for this valuable? When performing
|
3571 |
|
|
// a minimal save there is no point in outputting valuables which have
|
3572 |
|
|
// a default value.
|
3573 |
|
|
bool
|
3574 |
|
|
CdlValuableBody::value_savefile_entry_needed() const
|
3575 |
|
|
{
|
3576 |
|
|
CYG_REPORT_FUNCNAMETYPE("CdlValuable::value_savefile_entry_needed", "result %d");
|
3577 |
|
|
CYG_REPORT_FUNCARG1XV(this);
|
3578 |
|
|
CYG_PRECONDITION_THISC();
|
3579 |
|
|
|
3580 |
|
|
bool result = false;
|
3581 |
|
|
|
3582 |
|
|
if (this->is_modifiable()) {
|
3583 |
|
|
if (this->has_source(CdlValueSource_User) ||
|
3584 |
|
|
this->has_source(CdlValueSource_Wizard) ||
|
3585 |
|
|
this->has_source(CdlValueSource_Inferred)) {
|
3586 |
|
|
|
3587 |
|
|
result = true;
|
3588 |
|
|
}
|
3589 |
|
|
}
|
3590 |
|
|
|
3591 |
|
|
CYG_REPORT_RETVAL(result);
|
3592 |
|
|
return result;
|
3593 |
|
|
}
|
3594 |
|
|
|
3595 |
|
|
// ----------------------------------------------------------------------------
|
3596 |
|
|
// This utility is useful for outputting a particular value source
|
3597 |
|
|
|
3598 |
|
|
static std::string one = "1"; // Needed to avoid confusing the compiler
|
3599 |
|
|
static std::string zero = "0";
|
3600 |
|
|
|
3601 |
|
|
static std::string
|
3602 |
|
|
value_to_string(CdlValuable valuable, CdlValueSource source)
|
3603 |
|
|
{
|
3604 |
|
|
CYG_REPORT_FUNCNAME("value_to_string");
|
3605 |
|
|
|
3606 |
|
|
std::string data = "";
|
3607 |
|
|
|
3608 |
|
|
switch(valuable->get_flavor()) {
|
3609 |
|
|
case CdlValueFlavor_Bool :
|
3610 |
|
|
data += (valuable->is_enabled(source) ? one : zero);
|
3611 |
|
|
break;
|
3612 |
|
|
case CdlValueFlavor_BoolData :
|
3613 |
|
|
data += (valuable->is_enabled(source) ? one : zero) + " " +
|
3614 |
|
|
CdlInterpreterBody::quote(valuable->get_value(source));
|
3615 |
|
|
break;
|
3616 |
|
|
case CdlValueFlavor_Data:
|
3617 |
|
|
data += CdlInterpreterBody::quote(valuable->get_value(source));
|
3618 |
|
|
break;
|
3619 |
|
|
default:
|
3620 |
|
|
CYG_FAIL("Invalid value flavor detected");
|
3621 |
|
|
break;
|
3622 |
|
|
}
|
3623 |
|
|
return data;
|
3624 |
|
|
}
|
3625 |
|
|
|
3626 |
|
|
// Another utility to figure out the expected value source, given which
|
3627 |
|
|
// sources are available.
|
3628 |
|
|
static CdlValueSource
|
3629 |
|
|
get_expected_source(CdlValuable valuable)
|
3630 |
|
|
{
|
3631 |
|
|
CYG_REPORT_FUNCNAMETYPE("get_expected_source", "result %d");
|
3632 |
|
|
CYG_REPORT_FUNCARG1XV(valuable);
|
3633 |
|
|
|
3634 |
|
|
CdlValueSource expected_source = CdlValueSource_Default;
|
3635 |
|
|
|
3636 |
|
|
if (valuable->has_source(CdlValueSource_User)) {
|
3637 |
|
|
expected_source = CdlValueSource_User;
|
3638 |
|
|
} else if (valuable->has_source(CdlValueSource_Wizard)) {
|
3639 |
|
|
expected_source = CdlValueSource_Wizard;
|
3640 |
|
|
} else if (valuable->has_source(CdlValueSource_Inferred)) {
|
3641 |
|
|
expected_source = CdlValueSource_Inferred;
|
3642 |
|
|
}
|
3643 |
|
|
|
3644 |
|
|
CYG_REPORT_RETVAL((int) expected_source);
|
3645 |
|
|
return expected_source;
|
3646 |
|
|
}
|
3647 |
|
|
|
3648 |
|
|
// And another utility, to list the valuables listed in an expression.
|
3649 |
|
|
// e.g. for an expression of the form
|
3650 |
|
|
//
|
3651 |
|
|
// requires (AAA + BBB) > CCC
|
3652 |
|
|
//
|
3653 |
|
|
// this would produce:
|
3654 |
|
|
//
|
3655 |
|
|
// AAA == 1
|
3656 |
|
|
// BBB == 2
|
3657 |
|
|
// CCC == 0
|
3658 |
|
|
//
|
3659 |
|
|
// No indentation happens here, instead the calling code is assumed
|
3660 |
|
|
// to use multiline_comment()
|
3661 |
|
|
static std::string
|
3662 |
|
|
follow_expr_references(CdlProperty property, CdlExpression expr)
|
3663 |
|
|
{
|
3664 |
|
|
CYG_REPORT_FUNCNAME("follow_expr_references");
|
3665 |
|
|
CYG_REPORT_FUNCARG1XV(expr);
|
3666 |
|
|
CYG_PRECONDITION_CLASSC(expr);
|
3667 |
|
|
|
3668 |
|
|
std::string data = "";
|
3669 |
|
|
CdlSimpleValue simple_value;
|
3670 |
|
|
std::vector<CdlReference>::const_iterator ref_i;
|
3671 |
|
|
|
3672 |
|
|
for (ref_i = expr->references.begin(); ref_i != expr->references.end(); ref_i++) {
|
3673 |
|
|
const std::string& refname = ref_i->get_destination_name();
|
3674 |
|
|
CdlNode refnode = ref_i->get_destination();
|
3675 |
|
|
CdlValuable refvaluable = 0;
|
3676 |
|
|
if (0 != refnode) {
|
3677 |
|
|
refvaluable = dynamic_cast<CdlValuable>(refnode);
|
3678 |
|
|
}
|
3679 |
|
|
data += refname + " ";
|
3680 |
|
|
if (0 == refvaluable) {
|
3681 |
|
|
data += "(unknown) == 0";
|
3682 |
|
|
} else {
|
3683 |
|
|
CdlEvalContext context(0, refvaluable, property);
|
3684 |
|
|
CdlSimpleValue::eval_valuable(context, refvaluable, simple_value);
|
3685 |
|
|
data += "== " + CdlInterpreterBody::quote(simple_value.get_value());
|
3686 |
|
|
}
|
3687 |
|
|
data += '\n';
|
3688 |
|
|
}
|
3689 |
|
|
|
3690 |
|
|
CYG_REPORT_RETURN();
|
3691 |
|
|
return data;
|
3692 |
|
|
}
|
3693 |
|
|
|
3694 |
|
|
// ----------------------------------------------------------------------------
|
3695 |
|
|
|
3696 |
|
|
void
|
3697 |
|
|
CdlValuableBody::save(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool modifiable, bool minimal)
|
3698 |
|
|
{
|
3699 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::save");
|
3700 |
|
|
CYG_REPORT_FUNCARG5XV(this, interp, chan, indentation, minimal);
|
3701 |
|
|
CYG_PRECONDITION_THISC();
|
3702 |
|
|
CYG_PRECONDITION_CLASSC(interp);
|
3703 |
|
|
|
3704 |
|
|
std::string data = "";
|
3705 |
|
|
std::string indent_string = std::string(indentation, ' ');
|
3706 |
|
|
std::string tmp_value = "";
|
3707 |
|
|
CdlSimpleValue simple_value;
|
3708 |
|
|
|
3709 |
|
|
// If performing a minimal save, the only fields of interest are the
|
3710 |
|
|
// user value, the wizard value, the inferred value, and the value source.
|
3711 |
|
|
// Not all of these need be present.
|
3712 |
|
|
//
|
3713 |
|
|
// Having two places where these fields get output is unfortunate,
|
3714 |
|
|
// but the alternative is an awful lot of "if (minimal)" tests
|
3715 |
|
|
// in the main code.
|
3716 |
|
|
if (minimal) {
|
3717 |
|
|
|
3718 |
|
|
if (modifiable) {
|
3719 |
|
|
if (this->has_source(CdlValueSource_User)) {
|
3720 |
|
|
data += indent_string + "user_value " + value_to_string(this, CdlValueSource_User) + "\n";
|
3721 |
|
|
}
|
3722 |
|
|
if (this->has_source(CdlValueSource_Wizard)) {
|
3723 |
|
|
data += indent_string + "wizard_value " + value_to_string(this, CdlValueSource_Wizard) + "\n";
|
3724 |
|
|
}
|
3725 |
|
|
if (this->has_source(CdlValueSource_Inferred)) {
|
3726 |
|
|
data += indent_string + "inferred_value " + value_to_string(this, CdlValueSource_Inferred) + "\n";
|
3727 |
|
|
}
|
3728 |
|
|
CdlValueSource expected_source = get_expected_source(this);
|
3729 |
|
|
if (expected_source != this->get_source()) {
|
3730 |
|
|
std::string current_source_string;
|
3731 |
|
|
if (!Cdl::source_to_string(this->get_source(), current_source_string)) {
|
3732 |
|
|
CYG_FAIL("Invalid current value source detected");
|
3733 |
|
|
}
|
3734 |
|
|
data += indent_string + "value_source " + current_source_string + "\n";
|
3735 |
|
|
}
|
3736 |
|
|
}
|
3737 |
|
|
|
3738 |
|
|
} else {
|
3739 |
|
|
|
3740 |
|
|
// Right at the start, indicate whether or not this property is active.
|
3741 |
|
|
if (!this->is_active()) {
|
3742 |
|
|
data += indent_string + "# This option is not active\n";
|
3743 |
|
|
// If the entity is inactive because the parent is inactive or disabled,
|
3744 |
|
|
// say so here. This is in addition to any unsatisfied active_if
|
3745 |
|
|
// conditions, which will be reported below.
|
3746 |
|
|
CdlContainer parent = this->get_parent();
|
3747 |
|
|
if (!parent->is_active()) {
|
3748 |
|
|
data += indent_string + "# The parent " + parent->get_name() + " is not active\n";
|
3749 |
|
|
}
|
3750 |
|
|
CdlValuable tmp = dynamic_cast<CdlValuable>(parent);
|
3751 |
|
|
if ((0 != tmp) && !tmp->is_enabled()) {
|
3752 |
|
|
data += indent_string + "# The parent " + parent->get_name() + " is disabled\n";
|
3753 |
|
|
}
|
3754 |
|
|
}
|
3755 |
|
|
if (this->has_active_if_conditions()) {
|
3756 |
|
|
std::vector<CdlProperty_GoalExpression> active_if_conditions;
|
3757 |
|
|
this->get_active_if_conditions(active_if_conditions);
|
3758 |
|
|
std::vector<CdlProperty_GoalExpression>::const_iterator expr_i;
|
3759 |
|
|
for (expr_i = active_if_conditions.begin(); expr_i != active_if_conditions.end(); expr_i++) {
|
3760 |
|
|
data += indent_string + "# ActiveIf constraint: " +
|
3761 |
|
|
CdlInterpreterBody::extend_comment((*expr_i)->get_original_string(), indentation, 4) +
|
3762 |
|
|
'\n';
|
3763 |
|
|
|
3764 |
|
|
CdlExpression expr = (*expr_i)->get_expression();
|
3765 |
|
|
data += CdlInterpreterBody::multiline_comment(follow_expr_references(*expr_i, expr), indentation, 4);
|
3766 |
|
|
CdlEvalContext context(0, this, *expr_i);
|
3767 |
|
|
bool active_if_value = false;
|
3768 |
|
|
try {
|
3769 |
|
|
active_if_value = (*expr_i)->eval(context);
|
3770 |
|
|
} catch(CdlEvalException e) {
|
3771 |
|
|
active_if_value = false;
|
3772 |
|
|
} catch(std::bad_alloc) {
|
3773 |
|
|
throw;
|
3774 |
|
|
}
|
3775 |
|
|
data += indent_string + "# --> " + (active_if_value ? one : zero) + "\n";
|
3776 |
|
|
}
|
3777 |
|
|
}
|
3778 |
|
|
|
3779 |
|
|
// If there has been any information related to the active status,
|
3780 |
|
|
// add a blank line before we start worrying about values.
|
3781 |
|
|
if (0 < data.size()) {
|
3782 |
|
|
data += '\n';
|
3783 |
|
|
}
|
3784 |
|
|
|
3785 |
|
|
if (CdlValueFlavor_None == this->get_flavor()) {
|
3786 |
|
|
data += indent_string + "# There is no associated value.\n";
|
3787 |
|
|
} else if (this->has_property(CdlPropertyId_Calculated)) {
|
3788 |
|
|
CdlProperty_Expression expr = this->get_calculated_expression();
|
3789 |
|
|
data += indent_string + "# Calculated value: " +
|
3790 |
|
|
CdlInterpreterBody::extend_comment(expr->get_original_string(), indentation, 4) + '\n';
|
3791 |
|
|
data += CdlInterpreterBody::multiline_comment(follow_expr_references(expr, expr), indentation, 4);
|
3792 |
|
|
} else if (!modifiable) {
|
3793 |
|
|
data += indent_string + "# This value cannot be modified here.\n";
|
3794 |
|
|
}
|
3795 |
|
|
|
3796 |
|
|
// Output the flavor. This clutters up the savefile a bit.
|
3797 |
|
|
// However it is necessary so that the user can distinguish
|
3798 |
|
|
// between bool, booldata and data items
|
3799 |
|
|
switch(this->get_flavor()) {
|
3800 |
|
|
case CdlValueFlavor_Bool:
|
3801 |
|
|
data += indent_string + "# Flavor: bool\n";
|
3802 |
|
|
break;
|
3803 |
|
|
case CdlValueFlavor_BoolData:
|
3804 |
|
|
data += indent_string + "# Flavor: booldata\n";
|
3805 |
|
|
break;
|
3806 |
|
|
case CdlValueFlavor_Data:
|
3807 |
|
|
data += indent_string + "# Flavor: data\n";
|
3808 |
|
|
break;
|
3809 |
|
|
default:
|
3810 |
|
|
break;
|
3811 |
|
|
}
|
3812 |
|
|
|
3813 |
|
|
// If the value is not modifiable, just list the current value.
|
3814 |
|
|
// This is not in a form that allows users to change it easily.
|
3815 |
|
|
if (!modifiable) {
|
3816 |
|
|
switch(this->get_flavor()) {
|
3817 |
|
|
case CdlValueFlavor_None :
|
3818 |
|
|
break;
|
3819 |
|
|
case CdlValueFlavor_Bool :
|
3820 |
|
|
data += indent_string + "# Current value: " + (this->is_enabled() ? one : zero) + '\n';
|
3821 |
|
|
break;
|
3822 |
|
|
case CdlValueFlavor_BoolData :
|
3823 |
|
|
data += indent_string + "# Current value: " + (this->is_enabled() ? one : zero) + " " +
|
3824 |
|
|
CdlInterpreterBody::extend_comment(this->get_value(), indentation, 4) + '\n';
|
3825 |
|
|
break;
|
3826 |
|
|
case CdlValueFlavor_Data :
|
3827 |
|
|
data += indent_string + "# Current_value: " +
|
3828 |
|
|
CdlInterpreterBody::extend_comment(this->get_value(), indentation, 4) + '\n';
|
3829 |
|
|
break;
|
3830 |
|
|
default:
|
3831 |
|
|
break;
|
3832 |
|
|
}
|
3833 |
|
|
|
3834 |
|
|
} else if (CdlValueFlavor_None != this->get_flavor()) {
|
3835 |
|
|
|
3836 |
|
|
// If there is a user value, output it. Otherwise output
|
3837 |
|
|
// a comment that allows users to edit the user value conveniently.
|
3838 |
|
|
// It is assumed that the user will want a value similar to the
|
3839 |
|
|
// default one, so that is provided as the starting point
|
3840 |
|
|
if (this->has_source(CdlValueSource_User)) {
|
3841 |
|
|
data += indent_string + "user_value " + value_to_string(this, CdlValueSource_User) + "\n";
|
3842 |
|
|
} else {
|
3843 |
|
|
data += indent_string + "# No user value, uncomment the following line to provide one.\n" +
|
3844 |
|
|
indent_string + "# user_value " +
|
3845 |
|
|
CdlInterpreterBody::extend_comment(value_to_string(this, CdlValueSource_Default), indentation, 0) + "\n";
|
3846 |
|
|
}
|
3847 |
|
|
|
3848 |
|
|
// Output a wizard value iff there is one. There is little point
|
3849 |
|
|
// in letting users edit a wizard value, they should be running
|
3850 |
|
|
// the wizard itself.
|
3851 |
|
|
if (this->has_source(CdlValueSource_Wizard)) {
|
3852 |
|
|
data += indent_string + "# The wizard value should not be edited directly.\n" +
|
3853 |
|
|
indent_string + "# Instead the wizard should be run again if necessary.\n";
|
3854 |
|
|
data += indent_string + "wizard_value " + value_to_string(this, CdlValueSource_Wizard) + "\n";
|
3855 |
|
|
}
|
3856 |
|
|
|
3857 |
|
|
// List the inferred value. This needs to be a command,
|
3858 |
|
|
if (this->has_source(CdlValueSource_Inferred)) {
|
3859 |
|
|
data += indent_string + "# The inferred value should not be edited directly.\n";
|
3860 |
|
|
data += indent_string + "inferred_value " + value_to_string(this, CdlValueSource_Inferred) + "\n";
|
3861 |
|
|
}
|
3862 |
|
|
|
3863 |
|
|
// Output the value source iff it is unusual. If the current
|
3864 |
|
|
// source is the highest priority one then there is no point
|
3865 |
|
|
// in outputting a command, but a comment is usual. The value
|
3866 |
|
|
// source needs to come after wizard and inferred values
|
3867 |
|
|
std::string current_source_string;
|
3868 |
|
|
CdlValueSource expected_source = get_expected_source(this);
|
3869 |
|
|
CdlValueSource current_source = this->get_source();
|
3870 |
|
|
if (!Cdl::source_to_string(current_source, current_source_string)) {
|
3871 |
|
|
CYG_FAIL("Invalid current value source detected");
|
3872 |
|
|
}
|
3873 |
|
|
if (this->get_source() == expected_source) {
|
3874 |
|
|
data += indent_string + "# value_source " + current_source_string + "\n";
|
3875 |
|
|
} else {
|
3876 |
|
|
data += indent_string + "value_source " + current_source_string + "\n";
|
3877 |
|
|
}
|
3878 |
|
|
|
3879 |
|
|
// Always output the default value as a comment.
|
3880 |
|
|
data += indent_string + "# Default value: ";
|
3881 |
|
|
|
3882 |
|
|
// If there is no default_value expression or if the expression involves
|
3883 |
|
|
// only constants, just output the current default value. Otherwise
|
3884 |
|
|
// output both the expression and the value
|
3885 |
|
|
CdlProperty prop = this->get_property(CdlPropertyId_DefaultValue);
|
3886 |
|
|
CdlProperty_Expression expr = dynamic_cast<CdlProperty_Expression>(prop);
|
3887 |
|
|
if ((0 == expr) || (0 == expr->references.size())) {
|
3888 |
|
|
// There is no default_value expression, so just output the current value
|
3889 |
|
|
data += CdlInterpreterBody::extend_comment(value_to_string(this, CdlValueSource_Default), indentation, 4)
|
3890 |
|
|
+ "\n";
|
3891 |
|
|
} else {
|
3892 |
|
|
data += CdlInterpreterBody::extend_comment(expr->get_original_string(), indentation, 4) + "\n";
|
3893 |
|
|
data += CdlInterpreterBody::multiline_comment(follow_expr_references(expr, expr), indentation, 4);
|
3894 |
|
|
data += indent_string + "# --> " +
|
3895 |
|
|
CdlInterpreterBody::extend_comment(value_to_string(this, CdlValueSource_Default), indentation, 4) + "\n";
|
3896 |
|
|
}
|
3897 |
|
|
}
|
3898 |
|
|
|
3899 |
|
|
// If there is a legal_values property, add the details.
|
3900 |
|
|
if (this->has_property(CdlPropertyId_LegalValues)) {
|
3901 |
|
|
CdlProperty_ListExpression lexpr = this->get_legal_values();
|
3902 |
|
|
data += indent_string + "# Legal values: " +
|
3903 |
|
|
CdlInterpreterBody::extend_comment(lexpr->get_original_string(), indentation, 4) + '\n';
|
3904 |
|
|
|
3905 |
|
|
std::vector<CdlExpression>::const_iterator expr_i;
|
3906 |
|
|
std::vector<std::pair<CdlExpression,CdlExpression> >::const_iterator ranges_i;
|
3907 |
|
|
for (expr_i = lexpr->data.begin(); expr_i != lexpr->data.end(); expr_i++) {
|
3908 |
|
|
data += CdlInterpreterBody::multiline_comment(follow_expr_references(lexpr, *expr_i), indentation, 4);
|
3909 |
|
|
}
|
3910 |
|
|
for (ranges_i = lexpr->ranges.begin(); ranges_i != lexpr->ranges.end(); ranges_i++) {
|
3911 |
|
|
data += CdlInterpreterBody::multiline_comment(follow_expr_references(lexpr, ranges_i->first), indentation, 4);
|
3912 |
|
|
data += CdlInterpreterBody::multiline_comment(follow_expr_references(lexpr, ranges_i->second), indentation, 4);
|
3913 |
|
|
}
|
3914 |
|
|
}
|
3915 |
|
|
|
3916 |
|
|
// If there is a check_proc property, mention this.
|
3917 |
|
|
if (this->has_property(CdlPropertyId_CheckProc)) {
|
3918 |
|
|
data += indent_string + "# There is a check_proc routine that will check the value.\n";
|
3919 |
|
|
}
|
3920 |
|
|
|
3921 |
|
|
// Output all requires properties
|
3922 |
|
|
if (this->has_property(CdlPropertyId_Requires)) {
|
3923 |
|
|
std::vector<CdlProperty_GoalExpression> requires_goals;
|
3924 |
|
|
this->get_requires_goals(requires_goals);
|
3925 |
|
|
std::vector<CdlProperty_GoalExpression>::const_iterator expr_i;
|
3926 |
|
|
for (expr_i = requires_goals.begin(); expr_i != requires_goals.end(); expr_i++) {
|
3927 |
|
|
data += indent_string + "# Requires: " +
|
3928 |
|
|
CdlInterpreterBody::extend_comment((*expr_i)->get_original_string(), indentation, 4) + "\n";
|
3929 |
|
|
|
3930 |
|
|
CdlExpression expr = (*expr_i)->get_expression();
|
3931 |
|
|
data += CdlInterpreterBody::multiline_comment(follow_expr_references(*expr_i, expr), indentation, 4);
|
3932 |
|
|
CdlEvalContext context(0, this, *expr_i);
|
3933 |
|
|
bool active_if_value = false;
|
3934 |
|
|
try {
|
3935 |
|
|
active_if_value = (*expr_i)->eval(context);
|
3936 |
|
|
} catch(CdlEvalException e) {
|
3937 |
|
|
active_if_value = false;
|
3938 |
|
|
} catch(std::bad_alloc) {
|
3939 |
|
|
throw;
|
3940 |
|
|
}
|
3941 |
|
|
data += indent_string + "# --> " + (active_if_value ? one : zero) + "\n";
|
3942 |
|
|
}
|
3943 |
|
|
}
|
3944 |
|
|
|
3945 |
|
|
// Output all dependencies that other entities may have on this one.
|
3946 |
|
|
const std::vector<CdlReferrer>& referrers = this->get_referrers();
|
3947 |
|
|
if (0 != referrers.size()) {
|
3948 |
|
|
data += '\n' + indent_string + "# The following properties are affected by this value\n";
|
3949 |
|
|
std::vector<CdlReferrer>::const_iterator ref_i;
|
3950 |
|
|
for (ref_i = referrers.begin(); ref_i != referrers.end(); ref_i++) {
|
3951 |
|
|
|
3952 |
|
|
CdlNode source = ref_i->get_source();
|
3953 |
|
|
CdlProperty source_prop = ref_i->get_source_property();
|
3954 |
|
|
std::string prop_id = source_prop->get_property_name();
|
3955 |
|
|
|
3956 |
|
|
if ((prop_id == CdlPropertyId_ActiveIf) ||
|
3957 |
|
|
(prop_id == CdlPropertyId_Calculated) ||
|
3958 |
|
|
(prop_id == CdlPropertyId_DefaultValue) ||
|
3959 |
|
|
(prop_id == CdlPropertyId_LegalValues) ||
|
3960 |
|
|
(prop_id == CdlPropertyId_Requires)) {
|
3961 |
|
|
|
3962 |
|
|
data += indent_string + "# " + source->get_class_name() + " " + source->get_name() + "\n";
|
3963 |
|
|
data += indent_string + "# " + prop_id + ": ";
|
3964 |
|
|
if ((prop_id == CdlPropertyId_Calculated) || (prop_id == CdlPropertyId_DefaultValue)) {
|
3965 |
|
|
CdlProperty_Expression expr = dynamic_cast<CdlProperty_Expression>(source_prop);
|
3966 |
|
|
CYG_ASSERT_CLASSC(expr);
|
3967 |
|
|
data += CdlInterpreterBody::extend_comment(expr->get_original_string(), indentation, 4);
|
3968 |
|
|
} else if (prop_id == CdlPropertyId_LegalValues) {
|
3969 |
|
|
CdlProperty_ListExpression lexpr = dynamic_cast<CdlProperty_ListExpression>(source_prop);
|
3970 |
|
|
CYG_ASSERT_CLASSC(lexpr);
|
3971 |
|
|
data += CdlInterpreterBody::extend_comment(lexpr->get_original_string(), indentation, 4);
|
3972 |
|
|
} else if ((prop_id == CdlPropertyId_ActiveIf) || (prop_id == CdlPropertyId_Requires)) {
|
3973 |
|
|
CdlProperty_GoalExpression gexpr = dynamic_cast<CdlProperty_GoalExpression>(source_prop);
|
3974 |
|
|
CYG_ASSERT_CLASSC(gexpr);
|
3975 |
|
|
data += CdlInterpreterBody::extend_comment(gexpr->get_original_string(), indentation, 4);
|
3976 |
|
|
}
|
3977 |
|
|
data += '\n';
|
3978 |
|
|
}
|
3979 |
|
|
}
|
3980 |
|
|
}
|
3981 |
|
|
}
|
3982 |
|
|
|
3983 |
|
|
interp->write_data(chan, data);
|
3984 |
|
|
|
3985 |
|
|
CYG_REPORT_RETURN();
|
3986 |
|
|
}
|
3987 |
|
|
|
3988 |
|
|
int
|
3989 |
|
|
CdlValuableBody::savefile_value_source_command(CdlInterpreter interp, int argc, const char* argv[])
|
3990 |
|
|
{
|
3991 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::savefile_value_source_command");
|
3992 |
|
|
CYG_REPORT_FUNCARG2XV(interp, argc);
|
3993 |
|
|
CYG_PRECONDITION_CLASSC(interp);
|
3994 |
|
|
|
3995 |
|
|
CdlValuable valuable = dynamic_cast<CdlValuable>(interp->get_node());
|
3996 |
|
|
CYG_ASSERT_CLASSC(valuable);
|
3997 |
|
|
CdlTransaction transaction = interp->get_transaction();
|
3998 |
|
|
CYG_ASSERT_CLASSC(transaction);
|
3999 |
|
|
|
4000 |
|
|
CdlValueSource source = CdlValueSource_Invalid;
|
4001 |
|
|
if ((2 != argc) || !Cdl::string_to_source(argv[1], source) || !valuable->has_source(transaction, source)) {
|
4002 |
|
|
std::string msg = "Invalid value_source command for ";
|
4003 |
|
|
msg += valuable->get_class_name() + " " + valuable->get_name() + "\n";
|
4004 |
|
|
if (CdlValueSource_Invalid == source) {
|
4005 |
|
|
msg += "Expecting one argument, which should \"user\", \"wizard\", \"inferred\" or \"default\"";
|
4006 |
|
|
} else {
|
4007 |
|
|
msg += "The specified value source is not valid.";
|
4008 |
|
|
}
|
4009 |
|
|
CdlParse::report_error(interp, "", msg);
|
4010 |
|
|
} else {
|
4011 |
|
|
valuable->set_source(transaction, source);
|
4012 |
|
|
}
|
4013 |
|
|
|
4014 |
|
|
return TCL_OK;
|
4015 |
|
|
}
|
4016 |
|
|
|
4017 |
|
|
int
|
4018 |
|
|
CdlValuableBody::savefile_xxx_value_command(CdlInterpreter interp, int argc, const char* argv[], CdlValueSource source)
|
4019 |
|
|
{
|
4020 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::savefile_xxx_value_command");
|
4021 |
|
|
CYG_REPORT_FUNCARG3XV(interp, argc, source);
|
4022 |
|
|
CYG_PRECONDITION_CLASSC(interp);
|
4023 |
|
|
|
4024 |
|
|
CdlValuable valuable = dynamic_cast<CdlValuable>(interp->get_node());
|
4025 |
|
|
CYG_ASSERT_CLASSC(valuable);
|
4026 |
|
|
CdlTransaction transact = interp->get_transaction();
|
4027 |
|
|
CYG_ASSERT_CLASSC(transact);
|
4028 |
|
|
|
4029 |
|
|
bool error = false;
|
4030 |
|
|
bool warn = false;
|
4031 |
|
|
std::string msg = "";
|
4032 |
|
|
if (CdlValueFlavor_None == valuable->get_flavor()) {
|
4033 |
|
|
msg = "Options with flavor \"none\" cannot be modified.";
|
4034 |
|
|
error = true;
|
4035 |
|
|
} else if (!valuable->is_modifiable()) {
|
4036 |
|
|
msg = "This option is not user-modifiable.";
|
4037 |
|
|
error = true;
|
4038 |
|
|
} else {
|
4039 |
|
|
switch(valuable->get_flavor()) {
|
4040 |
|
|
case CdlValueFlavor_Bool :
|
4041 |
|
|
if (2 != argc) {
|
4042 |
|
|
msg = "Invalid boolean value, expecting 0 or 1";
|
4043 |
|
|
error = true;
|
4044 |
|
|
} else {
|
4045 |
|
|
bool x;
|
4046 |
|
|
Cdl::string_to_bool(argv[1], x);
|
4047 |
|
|
valuable->set_enabled(transact, x, source);
|
4048 |
|
|
}
|
4049 |
|
|
break;
|
4050 |
|
|
case CdlValueFlavor_Data :
|
4051 |
|
|
if (2 != argc) {
|
4052 |
|
|
msg = "Invalid data value, expecting a single string";
|
4053 |
|
|
error = true;
|
4054 |
|
|
} else {
|
4055 |
|
|
valuable->set_value(transact, argv[1], source);
|
4056 |
|
|
}
|
4057 |
|
|
break;
|
4058 |
|
|
case CdlValueFlavor_BoolData:
|
4059 |
|
|
if (3 != argc) {
|
4060 |
|
|
msg = "Invalid booldata value, expecting a boolean followed by a string";
|
4061 |
|
|
error = true;
|
4062 |
|
|
} else {
|
4063 |
|
|
bool x;
|
4064 |
|
|
Cdl::string_to_bool(argv[1], x);
|
4065 |
|
|
valuable->set_enabled_and_value(transact, x, argv[2], source);
|
4066 |
|
|
}
|
4067 |
|
|
break;
|
4068 |
|
|
default:
|
4069 |
|
|
CYG_FAIL("Invalid value flavor detected");
|
4070 |
|
|
break;
|
4071 |
|
|
}
|
4072 |
|
|
}
|
4073 |
|
|
|
4074 |
|
|
if (error || warn) {
|
4075 |
|
|
msg = std::string("Invalid value command for ") + valuable->get_class_name() + " " + valuable->get_name() + "\n"
|
4076 |
|
|
+ msg;
|
4077 |
|
|
if (error) {
|
4078 |
|
|
CdlParse::report_error(interp, "", msg);
|
4079 |
|
|
} else {
|
4080 |
|
|
CdlParse::report_warning(interp, "", msg);
|
4081 |
|
|
}
|
4082 |
|
|
}
|
4083 |
|
|
|
4084 |
|
|
return TCL_OK;
|
4085 |
|
|
}
|
4086 |
|
|
|
4087 |
|
|
int
|
4088 |
|
|
CdlValuableBody::savefile_user_value_command(CdlInterpreter interp, int argc, const char* argv[])
|
4089 |
|
|
{
|
4090 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::savefile_user_value_command");
|
4091 |
|
|
int result = CdlValuableBody::savefile_xxx_value_command(interp, argc, argv, CdlValueSource_User);
|
4092 |
|
|
CYG_REPORT_RETURN();
|
4093 |
|
|
return result;
|
4094 |
|
|
}
|
4095 |
|
|
|
4096 |
|
|
int
|
4097 |
|
|
CdlValuableBody::savefile_wizard_value_command(CdlInterpreter interp, int argc, const char* argv[])
|
4098 |
|
|
{
|
4099 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::savefile_wizard_value_command");
|
4100 |
|
|
int result = CdlValuableBody::savefile_xxx_value_command(interp, argc, argv, CdlValueSource_Wizard);
|
4101 |
|
|
CYG_REPORT_RETURN();
|
4102 |
|
|
return result;
|
4103 |
|
|
}
|
4104 |
|
|
|
4105 |
|
|
int
|
4106 |
|
|
CdlValuableBody::savefile_inferred_value_command(CdlInterpreter interp, int argc, const char* argv[])
|
4107 |
|
|
{
|
4108 |
|
|
CYG_REPORT_FUNCNAME("CdlValuable::savefile_inferred_value_command");
|
4109 |
|
|
int result = CdlValuableBody::savefile_xxx_value_command(interp, argc, argv, CdlValueSource_Inferred);
|
4110 |
|
|
CYG_REPORT_RETURN();
|
4111 |
|
|
return result;
|
4112 |
|
|
}
|
4113 |
|
|
|
4114 |
|
|
//}}}
|