]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/libcdl/conflict.cxx
Initial revision
[karo-tx-redboot.git] / tools / src / libcdl / conflict.cxx
1 //{{{  Banner                           
2
3 //============================================================================
4 //
5 //      conflict.cxx
6 //
7 //      The CdlConflict class
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/01/28
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. It also brings
59 // in <tcl.h>
60 #include <cdlcore.hxx>
61
62 //}}}
63
64 //{{{  Statics                          
65
66 // ----------------------------------------------------------------------------
67 CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflictBody);
68 CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflict_UnresolvedBody);
69 CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflict_IllegalValueBody);
70 CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflict_EvalExceptionBody);
71 CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflict_RequiresBody);
72 CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflict_DataBody);
73
74 //}}}
75 //{{{  CdlConflict                      
76
77 //{{{  Creation and destruction                 
78
79 // ----------------------------------------------------------------------------
80 // The basic conflicts. Conflicts are created in the context of a transaction.
81 // If the transaction gets committed then they are transferred to a toplevel.
82 // If the transaction gets cancelled then they just disappear.
83 //
84 // A conflict that is only part of a transaction may go away as that
85 // transaction proceeds, in which case it can be deleted immediately.
86 // A conflict that is already part of the toplevel cannot be
87 // destroyed, instead it gets marked in the transaction object. Only
88 // when the transaction is committed does the object get deleted.
89 // In addition within the context of a transaction old conflicts
90 // may hang around for a while.
91 //
92
93 CdlConflictBody::CdlConflictBody(CdlTransaction trans_arg, CdlNode node_arg, CdlProperty property_arg, bool structural_arg)
94 {
95     CYG_REPORT_FUNCNAME("CdlConflict:: constructor");
96     CYG_REPORT_FUNCARG4XV(this, trans_arg, node_arg, property_arg);
97     CYG_PRECONDITION_CLASSC(trans_arg);
98     CYG_PRECONDITION_CLASSC(node_arg);
99     CYG_PRECONDITION_CLASSC(property_arg);
100
101     node        = node_arg;
102     property    = property_arg;
103     transaction = trans_arg;
104     structural  = structural_arg;
105     no_solution = false;
106     // The vectors take care of themselves
107     enabled     = true;
108     reason      = "";
109
110     transaction->dirty = true;
111     if (structural_arg) {
112         transaction->new_structural_conflicts.push_back(this);
113     } else {
114         transaction->new_conflicts.push_back(this);
115     }
116     
117     cdlconflictbody_cookie      = CdlConflictBody_Magic;
118     CYGDBG_MEMLEAK_CONSTRUCTOR();
119
120     CYG_POSTCONDITION_THISC();
121     CYG_REPORT_RETURN();
122 }
123
124
125 // ----------------------------------------------------------------------------
126 // The destructor can get invoked during a transaction commit, in the
127 // case of a global conflict, or from inside clear() for a per-transaction
128 // conflict. In all cases the calling code is responsible for removing
129 // the conflict from any STL containers.
130
131 CdlConflictBody::~CdlConflictBody()
132 {
133     CYG_REPORT_FUNCNAME("CdlConflict:: destructor");
134     CYG_REPORT_FUNCARG1XV(this);
135     CYG_PRECONDITION_THISC();
136
137     cdlconflictbody_cookie      = CdlConflictBody_Invalid;
138     reason                      = "";
139     enabled                     = false;
140     no_solution                 = false;
141     solution.clear();
142     solution_references.clear();
143     structural                  = false;
144     transaction                 = 0;
145     property                    = 0;
146     node                        = 0;
147     CYGDBG_MEMLEAK_DESTRUCTOR();
148     
149     CYG_REPORT_RETURN();
150 }
151
152 //}}}
153 //{{{  Solution support                         
154
155 // ----------------------------------------------------------------------------
156 bool
157 CdlConflictBody::has_known_solution() const
158 {
159     CYG_REPORT_FUNCNAMETYPE("CdlConflict::has_solution", "result %d");
160     CYG_REPORT_FUNCARG1XV(this);
161     CYG_PRECONDITION_THISC();
162
163     bool result = (0 != solution.size());
164     
165     CYG_REPORT_RETVAL(result);
166     return result;
167 }
168
169 bool
170 CdlConflictBody::has_no_solution() const
171 {
172     CYG_REPORT_FUNCNAMETYPE("CdlConflict::has_no_solution", "result %d");
173     CYG_REPORT_FUNCARG1XV(this);
174     CYG_PRECONDITION_THISC();
175
176     bool result = no_solution;
177     
178     CYG_REPORT_RETVAL(result);
179     return result;
180 }
181
182 const std::vector<std::pair<CdlValuable, CdlValue> >&
183 CdlConflictBody::get_solution() const
184 {
185     CYG_REPORT_FUNCNAME("CdlConflict::get_solution");
186     CYG_REPORT_FUNCARG1XV(this);
187     CYG_PRECONDITION_THISC();
188
189     CYG_REPORT_RETURN();
190     return solution;
191 }
192
193 const std::set<CdlValuable>&
194 CdlConflictBody::get_solution_references() const
195 {
196     CYG_REPORT_FUNCNAME("CdlConflict::get_solution_references");
197     CYG_REPORT_FUNCARG1XV(this);
198     CYG_PRECONDITION_THISC();
199
200     CYG_REPORT_RETURN();
201     return solution_references;
202 }
203
204 // ----------------------------------------------------------------------------
205 // Try to resolve a conflict. If the conflict was created in a transaction,
206 // use that transaction. More commonly the conflict will be global and
207 // a new transaction will have to be created specially for it. Either
208 // way the conflict may cease to exist.
209 void
210 CdlConflictBody::resolve()
211 {
212     CYG_REPORT_FUNCNAME("CdlConflict::resolve");
213     CYG_REPORT_FUNCARG1XV(this);
214     CYG_PRECONDITION_THISC();
215     CYG_PRECONDITIONC(0 == transaction);
216
217     if (this->resolution_implemented()) {
218         CdlTransaction transact = CdlTransactionBody::make(this->get_node()->get_toplevel());
219         transact->resolve(this);
220         transact->body();
221         delete transact;
222     }
223     
224     CYG_REPORT_RETURN();
225 }
226
227 // ----------------------------------------------------------------------------
228 // A valuable has just been changed. If this value was relevant to the
229 // current solution (or lack thereof) then an update is necessary.
230 void
231 CdlConflictBody::update_solution_validity(CdlValuable valuable)
232 {
233     CYG_REPORT_FUNCNAME("CdlConflict::update_solution_validity");
234     CYG_REPORT_FUNCARG2XV(this, valuable);
235     CYG_PRECONDITION_THISC();
236
237     if (solution_references.find(valuable) != solution_references.end()) {
238         no_solution = false;
239         solution.clear();
240         solution_references.clear();
241     }
242
243     CYG_REPORT_RETURN();
244 }
245
246 // ----------------------------------------------------------------------------
247 // Default implementations of the inference engine do not do a lot...
248 bool
249 CdlConflictBody::inner_resolve(CdlTransaction trans_arg, int level)
250 {
251     CYG_REPORT_FUNCNAMETYPE("CdlConflict::inner_resolve", "result false");
252     CYG_REPORT_FUNCARG3XV(this, trans_arg, level);
253     CYG_PRECONDITION_THISC();
254     CYG_PRECONDITION_CLASSC(trans_arg);
255
256     // Setting the no_solution flag while keeping a clear
257     // solution_accessed vector means that the no_solution flag should
258     // always remain set, and hence no further inference attempts will be made.
259     no_solution = true;
260     
261     CYG_REPORT_RETURN();
262     return false;
263 }
264
265 bool
266 CdlConflictBody::resolution_implemented() const
267 {
268     CYG_REPORT_FUNCNAMETYPE("CdlConflict::resolution_implemented", "result %d");
269     CYG_REPORT_FUNCARG1XV(this);
270     CYG_PRECONDITION_THISC();
271
272     CYG_REPORT_RETVAL(false);
273     return false;
274 }
275
276 // ----------------------------------------------------------------------------
277 // Clearing a solution. This is needed if the inference engine has
278 // failed to find a complete solution, because in attempting this the
279 // solution_references vector will have been filled in anyway. It may
280 // have some other uses as well.
281 void
282 CdlConflictBody::clear_solution()
283 {
284     CYG_REPORT_FUNCNAME("CdlConflict::clear_solution");
285     CYG_REPORT_FUNCARG1XV(this);
286     CYG_PRECONDITION_THISC();
287
288     no_solution = false;
289     solution.clear();
290     solution_references.clear();
291
292     CYG_REPORT_RETURN();
293 }
294
295 //}}}
296 //{{{  Basics                                   
297
298 // ----------------------------------------------------------------------------
299
300 CdlNode
301 CdlConflictBody::get_node() const
302 {
303     CYG_REPORT_FUNCNAMETYPE("CdlConflict::get_node", "result %p");
304     CYG_REPORT_FUNCARG1XV(this);
305     CYG_PRECONDITION_THISC();
306
307     CdlNode result = node;
308     CYG_REPORT_RETVAL(result);
309     return result;
310 }
311
312 CdlProperty
313 CdlConflictBody::get_property() const
314 {
315     CYG_REPORT_FUNCNAMETYPE("CdlConflict::get_property", "result %p");
316     CYG_REPORT_FUNCARG1XV(this);
317     CYG_PRECONDITION_THISC();
318
319     CdlProperty result  = property;
320     CYG_REPORT_RETVAL(result);
321     return result;
322 }
323
324 bool
325 CdlConflictBody::is_structural() const
326 {
327     CYG_REPORT_FUNCNAMETYPE("CdlConflict::is_structural", "result %d");
328     CYG_REPORT_FUNCARG1XV(this);
329     CYG_PRECONDITION_THISC();
330
331     bool result = structural;
332     CYG_REPORT_RETVAL(result);
333     return result;
334 }
335
336 CdlTransaction
337 CdlConflictBody::get_transaction() const
338 {
339     CYG_REPORT_FUNCNAMETYPE("CdlConflict::get_transaction", "result %p");
340     CYG_REPORT_FUNCARG1XV(this);
341     CYG_PRECONDITION_THISC();
342
343     CdlTransaction result = transaction;
344     CYG_REPORT_RETVAL(result);
345     return result;
346 }
347
348 // FIXME: these are not currently implemented. It would be necessary
349 // to store the information in the savefile, which requires an
350 // unambiguous way of identifying a conflict that is likely to
351 // survice package version changes.
352
353 bool
354 CdlConflictBody::is_enabled() const
355 {
356     CYG_REPORT_FUNCNAMETYPE("CdlConflict::is_enabled", "result %d");
357     CYG_REPORT_FUNCARG1XV(this);
358     CYG_PRECONDITION_THISC();
359
360     bool result = enabled;
361     CYG_REPORT_RETVAL(result);
362     return result;
363 }
364
365 std::string
366 CdlConflictBody::get_disabled_reason() const
367 {
368     CYG_REPORT_FUNCNAME("CdlConflict::get_disabled_reason");
369     CYG_REPORT_FUNCARG1XV(this);
370     CYG_PRECONDITION_THISC();
371
372     // Possibly there should be a check that the conflict is currently
373     // disabled, but it might be useful. 
374     CYG_REPORT_RETURN();
375     return reason;
376 }
377
378 void
379 CdlConflictBody::disable(std::string reason_arg)
380 {
381     CYG_REPORT_FUNCNAME("CdlConflict::disable");
382     CYG_REPORT_FUNCARG1XV(this);
383     CYG_PRECONDITION_THISC();
384
385     reason      = reason_arg;
386     enabled     = false;
387
388     CYG_REPORT_RETURN();
389 }
390
391 void
392 CdlConflictBody::enable()
393 {
394     CYG_REPORT_FUNCNAME("CdlConflict::enable");
395     CYG_REPORT_FUNCARG1XV(this);
396     CYG_PRECONDITION_THISC();
397
398     enabled     = true;
399     // Leave "reason" alone, it may still be useful
400     
401     CYG_REPORT_RETURN();
402 }
403
404 //}}}
405 //{{{  check_this()                             
406
407 // ----------------------------------------------------------------------------
408 bool
409 CdlConflictBody::check_this(cyg_assert_class_zeal zeal) const
410 {
411     if (CdlConflictBody_Magic != cdlconflictbody_cookie) {
412         return false;
413     }
414     CYGDBG_MEMLEAK_CHECKTHIS();
415     if ((0 == node) || (0 == property)) {
416         return false;
417     }
418     switch(zeal) {
419       case cyg_system_test :
420       case cyg_extreme :
421       {
422           if (!node->check_this(cyg_quick)) {
423               return false;
424           }
425           // Accessing the properties would involve a function call.
426           
427           if (0 != transaction) {
428               if (!transaction->check_this(cyg_quick)) {
429                   return false;
430               }
431               if (structural) {
432                   // The conflict should exist in the new_structural_conflicts vector
433                   // deleted_structural_conflicts is for toplevel ones.
434                   if (std::find(transaction->new_structural_conflicts.begin(),
435                                 transaction->new_structural_conflicts.end(), this) ==
436                       transaction->new_structural_conflicts.end()) {
437                       return false;
438                   }
439               } else {
440                   // The conflict may appear on the new_conflicts list
441                   // or in the resolved_conflicts vector.
442                   if (std::find(transaction->new_conflicts.begin(), transaction->new_conflicts.end(), this) ==
443                       transaction->new_conflicts.end()) {
444
445                       if (std::find(transaction->resolved_conflicts.begin(), transaction->resolved_conflicts.end(), this) ==
446                           transaction->resolved_conflicts.end()) {
447
448                           return false;
449                       }
450                   }
451               }
452           }
453           // Checking the toplevel lists would be good, but involves a
454           // further function call and hence nested assertions.
455       }
456       case cyg_thorough :
457       {
458           if (!node->check_this(cyg_quick)) {
459               return false;
460           }
461           if (!property->check_this(cyg_quick)) {
462               return false;
463           }
464       }
465       case cyg_quick :
466       {
467           if (no_solution && (0 != solution.size())) {
468               return false;
469           }
470       }
471       case cyg_trivial :
472       case cyg_none :
473       default:
474           break;
475     }
476     
477     return true;
478 }
479
480 //}}}
481
482 //}}}
483 //{{{  CdlConflict_Unresolved           
484
485 // ----------------------------------------------------------------------------
486 // Unresolved references. Usually unresolved references occur inside
487 // expressions, but other properties that may be affected are parent,
488 // dialog and wizard.
489 //
490 // It is possible for a single expression to have multiple unresolved
491 // references, each of which will result in a separate conflict
492 // object. It is also possible for an expression to refer to the same
493 // unknown entity twice or more, in which case there would also be
494 // separate conflict objects. Unresolved references may also result in
495 // eval exceptions and in failed requires statements. Trying to cope
496 // with the various combinations as a single conflict seems too
497 // error-prone.
498
499 void
500 CdlConflict_UnresolvedBody::make(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg, std::string name_arg)
501 {
502     CdlConflict_Unresolved tmp = new CdlConflict_UnresolvedBody(trans, node_arg, prop_arg, name_arg);
503     CYG_UNUSED_PARAM(CdlConflict_Unresolved, tmp);
504 }
505
506 CdlConflict_UnresolvedBody::CdlConflict_UnresolvedBody(CdlTransaction trans_arg, CdlNode node_arg, CdlProperty prop_arg,
507                                                        std::string target_name_arg)
508     : CdlConflictBody(trans_arg, node_arg, prop_arg, true)
509 {
510     CYG_REPORT_FUNCNAME("CdlConflict_Unresolved:: constructor");
511     CYG_REPORT_FUNCARG1XV(this);
512     CYG_PRECONDITIONC("" != target_name_arg);
513
514     target_name = target_name_arg;
515     cdlconflict_unresolvedbody_cookie = CdlConflict_UnresolvedBody_Magic;
516     CYGDBG_MEMLEAK_CONSTRUCTOR();
517     
518     CYG_POSTCONDITION_THISC();
519     CYG_REPORT_RETURN();
520 }
521
522 CdlConflict_UnresolvedBody::~CdlConflict_UnresolvedBody()
523 {
524     CYG_REPORT_FUNCNAME("CdlConflict_Unresolved:: destructor");
525     CYG_REPORT_FUNCARG1XV(this);
526     CYG_PRECONDITION_THISC();
527
528     cdlconflict_unresolvedbody_cookie = CdlConflict_UnresolvedBody_Invalid;
529     target_name = "";
530     CYGDBG_MEMLEAK_DESTRUCTOR();
531
532     CYG_REPORT_RETURN();
533 }
534
535 std::string
536 CdlConflict_UnresolvedBody::get_target_name() const
537 {
538     CYG_REPORT_FUNCNAME("CdlConflict_Unresolved::get_target_name");
539     CYG_REPORT_FUNCARG1XV(this);
540     CYG_PRECONDITION_THISC();
541
542     CYG_REPORT_RETURN();
543     return target_name;
544 }
545
546 // For now, just report the node and property name, a brief text, and the
547 // entity being referenced. 
548 //
549 // Eventually we can do clever things like looking up the name in a
550 // database.
551
552 std::string
553 CdlConflict_UnresolvedBody::get_explanation() const
554 {
555     CYG_REPORT_FUNCNAME("CdlConflict_Unresolved::get_explanation");
556     CYG_REPORT_FUNCARG1XV(this);
557     CYG_PRECONDITION_THISC();
558
559     std::string result;
560     result = node->get_name() + ", property " + property->get_property_name() +
561         ":\nReference to unknown object " + target_name;
562
563     CYG_REPORT_RETURN();
564     return result;
565 }
566
567 bool
568 CdlConflict_UnresolvedBody::check_this(cyg_assert_class_zeal zeal) const
569 {
570     if (CdlConflict_UnresolvedBody_Magic != cdlconflict_unresolvedbody_cookie) {
571         return false;
572     }
573     CYGDBG_MEMLEAK_CHECKTHIS();
574
575     // There is not a lot of checking that can be done on the name.
576     
577     return CdlConflictBody::check_this(zeal);
578 }
579
580 bool
581 CdlConflict_UnresolvedBody::test(CdlConflict conf)
582 {
583     CYG_REPORT_FUNCNAMETYPE("CdlConflict_Unresolved::test", "result %d");
584     CYG_REPORT_FUNCARG1XV(conf);
585     CYG_PRECONDITION_CLASSC(conf);
586
587     bool result = false;
588     CdlConflict_Unresolved tmp = dynamic_cast<CdlConflict_Unresolved>(conf);
589     if (0 != tmp) {
590         result = true;
591     }
592
593     CYG_REPORT_RETVAL(result);
594     return result;
595 }
596
597 //}}}
598 //{{{  CdlConflict_IllegalValue         
599
600 // ----------------------------------------------------------------------------
601 // A valuable object has an illegal value. This can happen because the
602 // current value is not within the legal_values list, or because of a
603 // failure of check_proc or entry_proc. In the latter two cases the
604 // Tcl code should supply an explanation as to why the value is illegal.
605 //
606 // Note: if future variants of CDL implement some concept of a value
607 // that does not match the CdlValuable class then that will need a
608 // separate CdlConflict derived class.
609
610 void
611 CdlConflict_IllegalValueBody::make(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg)
612 {
613     CdlConflict_IllegalValue tmp = new CdlConflict_IllegalValueBody(trans, node_arg, prop_arg);
614     CYG_UNUSED_PARAM(CdlConflict_IllegalValue, tmp);
615 }
616
617 CdlConflict_IllegalValueBody::CdlConflict_IllegalValueBody(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg)
618     : CdlConflictBody(trans, node_arg, prop_arg, false)
619 {
620     CYG_REPORT_FUNCNAME("CdlConflict_IllegalValue:: constructor");
621     CYG_REPORT_FUNCARG1XV(this);
622     CYG_PRECONDITIONC(0 != dynamic_cast<CdlValuable>(node_arg));
623
624     explanation = "";
625     cdlconflict_illegalvaluebody_cookie = CdlConflict_IllegalValueBody_Magic;
626     CYGDBG_MEMLEAK_CONSTRUCTOR();
627
628     CYG_POSTCONDITION_THISC();
629     CYG_REPORT_RETURN();
630 }
631
632 CdlConflict_IllegalValueBody::~CdlConflict_IllegalValueBody()
633 {
634     CYG_REPORT_FUNCNAME("CdlConflict_IllegalValue:: destructor");
635     CYG_REPORT_FUNCARG1XV(this);
636     CYG_PRECONDITION_THISC();
637
638     cdlconflict_illegalvaluebody_cookie = CdlConflict_IllegalValueBody_Invalid;
639     explanation = "";
640     CYGDBG_MEMLEAK_DESTRUCTOR();
641
642     CYG_REPORT_RETURN();
643 }
644
645 // ----------------------------------------------------------------------------
646 // If the property is legal_values then it should be a list expression
647 // property. Display the current value and the original expression.
648 //
649 // If the property is check_proc or entry_proc, the Tcl code should
650 // have produced an explanation string and stored it in the conflict
651 // object.
652 std::string
653 CdlConflict_IllegalValueBody::get_explanation() const
654 {
655     CYG_REPORT_FUNCNAME("CdlConflict_IllegalValue::get_explanation()");
656     CYG_REPORT_FUNCARG1XV(this);
657     CYG_PRECONDITION_THISC();
658
659     CdlConstValuable valuable = dynamic_cast<CdlConstValuable>(node);
660     CYG_ASSERTC(0 != valuable);
661
662     std::string result = "";
663
664     // FIXME: analyse the current value and flavor a bit more
665     result += "Illegal current value " + valuable->get_value() + "\n";
666
667     if (CdlPropertyId_LegalValues == property->get_property_name()) {
668         
669         CdlConstProperty_ListExpression expr = dynamic_cast<CdlConstProperty_ListExpression>(property);
670         CYG_ASSERTC(0 != expr);
671         result += "Legal values are: " + expr->get_original_string();
672         
673     } else if (explanation != "") {
674         
675         result += explanation;
676     } else {
677
678         CYG_FAIL("Inexplicable illegal value");
679     }
680
681     CYG_REPORT_RETURN();
682     return result;
683 }
684
685 void
686 CdlConflict_IllegalValueBody::set_explanation(std::string explanation_arg)
687 {
688     CYG_REPORT_FUNCNAME("CdlConflict_IllegalValue::set_explanation");
689     CYG_REPORT_FUNCARG1XV(this);
690     CYG_PRECONDITION_THISC();
691
692     explanation = explanation_arg;
693
694     CYG_REPORT_RETURN();
695 }
696
697 // ----------------------------------------------------------------------------
698 // Inference is implemented. The actual inference code is in infer.cxx
699 bool
700 CdlConflict_IllegalValueBody::resolution_implemented() const
701 {
702     CYG_REPORT_FUNCNAME("CdlConflict_IllegalValue::resolution_implemented");
703     CYG_REPORT_FUNCARG1XV(this);
704     CYG_PRECONDITION_THISC();
705
706     CYG_REPORT_RETURN();
707     return true;
708 }
709
710 // ----------------------------------------------------------------------------
711 bool
712 CdlConflict_IllegalValueBody::check_this(cyg_assert_class_zeal zeal) const
713 {
714     if (CdlConflict_IllegalValueBody_Magic != cdlconflict_illegalvaluebody_cookie) {
715         return false;
716     }
717     CYGDBG_MEMLEAK_CHECKTHIS();
718
719     return CdlConflictBody::check_this(zeal);
720 }
721
722 bool
723 CdlConflict_IllegalValueBody::test(CdlConflict conf)
724 {
725     CYG_REPORT_FUNCNAMETYPE("CdlConflict_IllegalValue::test", "result %d");
726     CYG_REPORT_FUNCARG1XV(conf);
727     CYG_PRECONDITION_CLASSC(conf);
728
729     bool result = false;
730     CdlConflict_IllegalValue tmp = dynamic_cast<CdlConflict_IllegalValue>(conf);
731     if (0 != tmp) {
732         result = true;
733     }
734
735     CYG_REPORT_RETVAL(result);
736     return result;
737 }
738
739 //}}}
740 //{{{  CdlConflict_EvalException        
741
742 // ----------------------------------------------------------------------------
743 // Run-time expression failures are possible because of division by
744 // zero, if for no other reason. The evaluation code should have
745 // stored a suitable diagnostic with the conflict. This is not part
746 // of the constructor, allowing the conflict object to be re-used
747 // if the detailed reason changes
748
749 void
750 CdlConflict_EvalExceptionBody::make(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg, std::string msg_arg)
751 {
752     CdlConflict_EvalException tmp = new CdlConflict_EvalExceptionBody(trans, node_arg, prop_arg, msg_arg);
753     CYG_UNUSED_PARAM(CdlConflict_EvalException, tmp);
754 }
755
756 CdlConflict_EvalExceptionBody::CdlConflict_EvalExceptionBody(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg,
757                                                              std::string msg_arg)
758     : CdlConflictBody(trans, node_arg, prop_arg, false)
759 {
760     CYG_REPORT_FUNCNAME("CdlConflict_EvalException");
761     CYG_REPORT_FUNCARG1XV(this);
762
763     explanation = msg_arg;
764     cdlconflict_evalexceptionbody_cookie = CdlConflict_EvalExceptionBody_Magic;
765     CYGDBG_MEMLEAK_CONSTRUCTOR();
766
767     CYG_POSTCONDITION_THISC();
768     CYG_REPORT_RETURN();
769 }
770
771 CdlConflict_EvalExceptionBody::~CdlConflict_EvalExceptionBody()
772 {
773     CYG_REPORT_FUNCNAME("CdlConflict_EvalException");
774     CYG_REPORT_FUNCARG1XV(this);
775     CYG_PRECONDITION_THISC();
776
777     cdlconflict_evalexceptionbody_cookie = CdlConflict_EvalExceptionBody_Invalid;
778     explanation = "";
779     CYGDBG_MEMLEAK_DESTRUCTOR();
780
781     CYG_REPORT_RETURN();
782 }
783
784 // If there has been an eval exception then the property must be an
785 // ordinary expression, a list expression, or a goal expression
786 std::string
787 CdlConflict_EvalExceptionBody::get_explanation() const
788 {
789     CYG_REPORT_FUNCNAME("CdlConflict_EvalException::get_explanation");
790     CYG_REPORT_FUNCARG1XV(this);
791     CYG_PRECONDITION_THISC();
792
793     std::string result = node->get_name() + ", property " + property->get_property_name() + "\n";
794     result += "Error while evaluation expression: ";
795     if ("" != explanation) {
796         result += explanation;
797     }
798     result += "\n";
799
800     if (CdlConstProperty_Expression expr = dynamic_cast<CdlConstProperty_Expression>(property)) {
801         
802         result += "Expression: " + expr->get_original_string();
803         
804     } else if (CdlConstProperty_ListExpression lexpr = dynamic_cast<CdlConstProperty_ListExpression>(property)) {
805
806         result += "List expression: " + lexpr->get_original_string();
807         
808     } else if (CdlConstProperty_GoalExpression gexpr = dynamic_cast<CdlConstProperty_GoalExpression>(property)) {
809
810         result += "Goal expression: " + gexpr->get_original_string();
811         
812     } else {
813         CYG_FAIL("Unknown expression type");
814     }
815
816     CYG_REPORT_RETURN();
817     return result;
818 }
819
820 void
821 CdlConflict_EvalExceptionBody::set_explanation(std::string explanation_arg)
822 {
823     CYG_REPORT_FUNCNAME("CdlConflict_EvalException::set_explanation");
824     CYG_REPORT_FUNCARG1XV(this);
825     CYG_PRECONDITION_THISC();
826
827     explanation = explanation_arg;
828
829     CYG_REPORT_RETURN();
830 }
831
832 bool
833 CdlConflict_EvalExceptionBody::check_this(cyg_assert_class_zeal zeal) const
834 {
835     if (CdlConflict_EvalExceptionBody_Magic != cdlconflict_evalexceptionbody_cookie) {
836         return false;
837     }
838     CYGDBG_MEMLEAK_CHECKTHIS();
839     return CdlConflictBody::check_this(zeal);
840 }
841
842 bool
843 CdlConflict_EvalExceptionBody::test(CdlConflict conf)
844 {
845     CYG_REPORT_FUNCNAMETYPE("CdlConflict_EvalException::test", "result %d");
846     CYG_REPORT_FUNCARG1XV(conf);
847     CYG_PRECONDITION_CLASSC(conf);
848
849     bool result = false;
850     CdlConflict_EvalException tmp = dynamic_cast<CdlConflict_EvalException>(conf);
851     if (0 != tmp) {
852         result = true;
853     }
854
855     CYG_REPORT_RETVAL(result);
856     return result;
857 }
858
859 //}}}
860 //{{{  CdlConflict_Requires             
861
862 // ----------------------------------------------------------------------------
863 // A requires constraint is not satisfied. Producing a decent diagnostic
864 // here requires a detailed understanding of goal expressions. For now
865 // there is no extra data associated with goal expressions.
866
867 void
868 CdlConflict_RequiresBody::make(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg)
869 {
870     CdlConflict_Requires tmp = new CdlConflict_RequiresBody(trans, node_arg, prop_arg);
871     CYG_UNUSED_PARAM(CdlConflict_Requires, tmp);
872 }
873
874 CdlConflict_RequiresBody::CdlConflict_RequiresBody(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg)
875     : CdlConflictBody(trans, node_arg, prop_arg, false)
876 {
877     CYG_REPORT_FUNCNAME("CdlConflict_Requires:: constructor");
878     CYG_REPORT_FUNCARG1XV(this);
879     CYG_PRECONDITIONC(0 != dynamic_cast<CdlProperty_GoalExpression>(prop_arg));
880
881     cdlconflict_requiresbody_cookie = CdlConflict_RequiresBody_Magic;
882     CYGDBG_MEMLEAK_CONSTRUCTOR();
883
884     CYG_POSTCONDITION_THISC();
885     CYG_REPORT_RETURN();
886 }
887
888 CdlConflict_RequiresBody::~CdlConflict_RequiresBody()
889 {
890     CYG_REPORT_FUNCNAME("CdlConflict_Requires:: destructor");
891     CYG_REPORT_FUNCARG1XV(this);
892     CYG_PRECONDITION_THISC();
893
894     cdlconflict_requiresbody_cookie = CdlConflict_RequiresBody_Invalid;
895     CYGDBG_MEMLEAK_DESTRUCTOR();
896
897     CYG_REPORT_RETURN();
898 }
899
900 // FIXME: implement properly
901 std::string
902 CdlConflict_RequiresBody::get_explanation() const
903 {
904     CYG_REPORT_FUNCNAME("CdlConflict::get_explanation");
905     CYG_REPORT_FUNCARG1XV(this);
906     CYG_PRECONDITION_THISC();
907
908     CdlConstProperty_GoalExpression gexpr = dynamic_cast<CdlConstProperty_GoalExpression>(property);
909     CYG_ASSERTC(0 != gexpr);
910     
911     std::string result = "";
912     result += "\"requires\" constraint not satisfied: " + gexpr->get_original_string();
913
914     CYG_REPORT_RETURN();
915     return result;
916 }
917
918 // Inference is implemented, see infer.cxx
919 bool
920 CdlConflict_RequiresBody::resolution_implemented() const
921 {
922     CYG_REPORT_FUNCNAME("CdlConflict_Requires");
923     CYG_REPORT_FUNCARG1XV(this);
924     CYG_PRECONDITION_THISC();
925
926     CYG_REPORT_RETURN();
927     return true;
928 }
929
930 bool
931 CdlConflict_RequiresBody::check_this(cyg_assert_class_zeal zeal) const
932 {
933     if (CdlConflict_RequiresBody_Magic != cdlconflict_requiresbody_cookie) {
934         return false;
935     }
936     CYGDBG_MEMLEAK_CHECKTHIS();
937     return CdlConflictBody::check_this(zeal);
938 }
939
940 bool
941 CdlConflict_RequiresBody::test(CdlConflict conf)
942 {
943     CYG_REPORT_FUNCNAMETYPE("CdlConflict_Requires::test", "result %d");
944     CYG_REPORT_FUNCARG1XV(conf);
945     CYG_PRECONDITION_CLASSC(conf);
946
947     bool result = false;
948     CdlConflict_Requires tmp = dynamic_cast<CdlConflict_Requires>(conf);
949     if (0 != tmp) {
950         result = true;
951     }
952
953     CYG_REPORT_RETVAL(result);
954     return result;
955 }
956
957 //}}}
958 //{{{  CdlConflict_Data                 
959
960 // ----------------------------------------------------------------------------
961 // There is some strange problem in the configuration data, for example
962 // a parent property that is resolved but the target is not a container.
963
964 void
965 CdlConflict_DataBody::make(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg, std::string message_arg)
966 {
967     CdlConflict_Data tmp = new CdlConflict_DataBody(trans, node_arg, prop_arg, message_arg);
968     CYG_UNUSED_PARAM(CdlConflict_Data, tmp);
969 }
970
971 CdlConflict_DataBody::CdlConflict_DataBody(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg,
972                                            std::string message_arg)
973     : CdlConflictBody(trans, node_arg, prop_arg, true)
974 {
975     CYG_REPORT_FUNCNAME("CdlConflict_Data:: constructor");
976     CYG_REPORT_FUNCARG1XV(this);
977     CYG_PRECONDITIONC("" != message_arg);
978
979     message = message_arg;
980     cdlconflict_databody_cookie = CdlConflict_DataBody_Magic;
981     CYGDBG_MEMLEAK_CONSTRUCTOR();
982
983     CYG_POSTCONDITION_THISC();
984     CYG_REPORT_RETURN();
985 }
986
987 CdlConflict_DataBody::~CdlConflict_DataBody()
988 {
989     CYG_REPORT_FUNCNAME("CdlConflict_ata: destructor");
990     CYG_REPORT_FUNCARG1XV(this);
991     CYG_PRECONDITION_THISC();
992
993     cdlconflict_databody_cookie = CdlConflict_DataBody_Invalid;
994     CYGDBG_MEMLEAK_DESTRUCTOR();
995
996     CYG_REPORT_RETURN();
997 }
998
999 std::string
1000 CdlConflict_DataBody::get_explanation() const
1001 {
1002     CYG_REPORT_FUNCNAME("CdlConflict_Data::get_explanation");
1003     CYG_REPORT_FUNCARG1XV(this);
1004     CYG_PRECONDITION_THISC();
1005
1006     std::string result = message;
1007
1008     CYG_REPORT_RETURN();
1009     return result;
1010 }
1011
1012 bool
1013 CdlConflict_DataBody::check_this(cyg_assert_class_zeal zeal) const
1014 {
1015     if (CdlConflict_DataBody_Magic != cdlconflict_databody_cookie) {
1016         return false;
1017     }
1018     CYGDBG_MEMLEAK_CHECKTHIS();
1019     return CdlConflictBody::check_this(zeal);
1020 }
1021
1022 bool
1023 CdlConflict_DataBody::test(CdlConflict conf)
1024 {
1025     CYG_REPORT_FUNCNAMETYPE("CdlConflict_Data::test", "result %d");
1026     CYG_REPORT_FUNCARG1XV(conf);
1027     CYG_PRECONDITION_CLASSC(conf);
1028
1029     bool result = false;
1030     CdlConflict_Data tmp = dynamic_cast<CdlConflict_Data>(conf);
1031     if (0 != tmp) {
1032         result = true;
1033     }
1034
1035     CYG_REPORT_RETVAL(result);
1036     return result;
1037 }
1038
1039 //}}}