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