]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/libcdl/refer.cxx
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / tools / src / libcdl / refer.cxx
1 //{{{  Banner                           
2
3 //============================================================================
4 //
5 //      refer.cxx
6 //
7 //      Implementation of the CdlReference and CdlReferrer 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/02/01
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(CdlReference);
67 CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlReferrer);
68
69 //}}}
70 //{{{  CdlReference class               
71
72 // ----------------------------------------------------------------------------
73 // The default constructor. This should not normally get invoked, instead
74 // a string argument should be supplied. However it is occasionally useful
75 // to construct a reference and then set the name later.
76
77 CdlReference::CdlReference()
78 {
79     CYG_REPORT_FUNCNAME("CdlReference:: default constructor");
80     CYG_REPORT_FUNCARG1XV(this);
81
82     dest_name           = "";
83     dest                = 0;
84     cdlreference_cookie = CdlReference_Magic;
85     CYGDBG_MEMLEAK_CONSTRUCTOR();
86
87     CYG_POSTCONDITION_THISC();
88     CYG_REPORT_RETURN();
89 }
90
91 // This constructor typically gets used when parsing a property.
92 // The object may be created either on the stack or in the heap,
93 // depending on the requirements of the property. During a later
94 // phase in the parsing process the object may get bound.
95 CdlReference::CdlReference(const std::string dest_arg)
96 {
97     CYG_REPORT_FUNCNAME("CdlReference:: constructor");
98     CYG_REPORT_FUNCARG1("this %p", this);
99     
100     dest_name           = dest_arg;
101     dest                = 0;
102     cdlreference_cookie = CdlReference_Magic;
103     CYGDBG_MEMLEAK_CONSTRUCTOR();
104     
105     CYG_POSTCONDITION_THISC();
106     CYG_REPORT_RETURN();
107 }
108
109 // For some properties, notably LocalReference ones, it is convenient
110 // to create a temporary reference object on the stack and then
111 // derive the property from the temporary. This requires the
112 // copy constructor. When this operation is used the object
113 // should still be unbound.
114 CdlReference::CdlReference(const CdlReference& orig)
115 {
116     CYG_REPORT_FUNCNAME("CdlReference:: copy constructor");
117     CYG_REPORT_FUNCARG2("this %p, orig %p", this, &orig);
118     CYG_INVARIANT_CLASSC(CdlReference, orig);
119     CYG_PRECONDITIONC(0 == orig.dest);
120
121     dest_name           = orig.dest_name;
122     dest                = 0;
123     cdlreference_cookie = CdlReference_Magic;
124     CYGDBG_MEMLEAK_CONSTRUCTOR();
125     
126     CYG_POSTCONDITION_THISC();
127     CYG_REPORT_RETURN();
128 }
129
130 // The assignment operator may be needed for similar reasons.
131 CdlReference&
132 CdlReference::operator=(const CdlReference& orig)
133 {
134     CYG_REPORT_FUNCNAME("CdlReference:: assignment operator");
135     CYG_REPORT_FUNCARG2("this %p, orig %p", this, &orig);
136     CYG_INVARIANT_CLASSC(CdlReference, orig);
137     CYG_PRECONDITIONC(0 == orig.dest);
138
139     if (this != &orig) {
140         dest_name               = orig.dest_name;
141         dest                    = 0;
142         cdlreference_cookie     = CdlReference_Magic;
143     }
144
145     CYG_POSTCONDITION_THISC();
146     CYG_REPORT_RETURN();
147     return *this;
148 }
149     
150 // The destructor should only get invoked when a package is unloaded.
151 // All appropriate clean-ups should have happened already, in particular
152 // the reference should not currently be bound.
153 CdlReference::~CdlReference()
154 {
155     CYG_REPORT_FUNCNAME("CdlReference:: destructor");
156     CYG_REPORT_FUNCARG1("this %p", this);
157     CYG_PRECONDITION_THISC();
158     CYG_PRECONDITIONC(0 == dest);
159
160     cdlreference_cookie = CdlReference_Invalid;
161     dest_name           = "";
162     CYGDBG_MEMLEAK_DESTRUCTOR();
163     
164     CYG_REPORT_RETURN();
165 }
166
167 // ----------------------------------------------------------------------------
168 // Accessing the fields.
169
170 void
171 CdlReference::set_destination_name(const std::string name)
172 {
173     CYG_REPORT_FUNCNAME("CdlReference::set_destination_name");
174     CYG_REPORT_FUNCARG1XV(this);
175     CYG_PRECONDITION_THISC();
176     CYG_PRECONDITIONC((0 == dest) && ("" == dest_name));
177
178     dest_name = name;
179
180     CYG_REPORT_RETURN();
181 }
182
183 const std::string&
184 CdlReference::get_destination_name(void) const
185 {
186     CYG_REPORT_FUNCNAME("CdlReference::get_destination_name");
187     CYG_REPORT_FUNCARG1("this %p", this);
188     CYG_PRECONDITION_THISC();
189
190     CYG_REPORT_RETURN();
191     return dest_name;
192 }
193
194 CdlNode
195 CdlReference::get_destination() const
196 {
197     CYG_REPORT_FUNCNAMETYPE("CdlReference::get_destination", "result %p");
198     CYG_REPORT_FUNCARG1XV(this);
199     CYG_PRECONDITION_THISC();
200
201     CdlNode result = dest;
202     CYG_REPORT_RETVAL(result);
203     return result;
204 }
205
206 bool
207 CdlReference::check_this(cyg_assert_class_zeal zeal) const
208 {
209     if (CdlReference_Magic != cdlreference_cookie) {
210         return false;
211     }
212     CYGDBG_MEMLEAK_CHECKTHIS();
213     switch(zeal) {
214       case cyg_system_test:
215       case cyg_extreme:
216           // There is not enough information in the reference
217           // object itself to allow for a check for a corresponding
218           // referrer object. If more debugability is needed
219           // then extra data will have to be stored.
220           //
221           // However, it is possible to do a basic check of dest itself.
222           if (0 != dest) {
223               if (!dest->check_this(cyg_quick)) {
224                   return false;
225               }
226           }
227       case cyg_thorough:
228           if (0 != dest) {
229               if (dest_name != dest->get_name()) {
230                   return false;
231               }
232           }
233       case cyg_quick:
234       case cyg_trivial:
235       case cyg_none   :
236       default         :
237           break;
238     }
239     return true;
240 }
241
242 // ----------------------------------------------------------------------------
243 // Binding. This is simply a case of filling in some fields in the reference
244 // object and pushing a new referrer object. Binding generally happens as
245 // a result of calling reference update handlers when a package gets loaded.
246
247 void
248 CdlReference::bind(CdlNode src_arg, CdlProperty src_prop_arg, CdlNode dest_arg)
249 {
250     CYG_REPORT_FUNCNAME("CdlReference::bind");
251     CYG_REPORT_FUNCARG4XV(this, src_arg, src_prop_arg, dest_arg);
252     CYG_INVARIANT_THISC(CdlReference);
253     CYG_PRECONDITION_CLASSC(src_arg);
254     CYG_PRECONDITION_CLASSC(src_prop_arg);
255     CYG_PRECONDITION_CLASSC(dest_arg);
256
257     CYG_ASSERTC(dest_name == dest_arg->get_name());
258
259     CdlReferrer local_copy;
260     local_copy.source           = src_arg;
261     local_copy.source_property  = src_prop_arg;
262
263     dest_arg->referrers.push_back(local_copy);
264     dest = dest_arg;
265
266     CYG_REPORT_RETURN();
267 }
268
269 // Unbinding involves finding and removing the appropriate referrer object (there
270 // may be several, but each will result in a separate unbind() call.)
271 void
272 CdlReference::unbind(CdlNode src_arg, CdlProperty src_prop_arg)
273 {
274     CYG_REPORT_FUNCNAME("CdlReference::unbind");
275     CYG_REPORT_FUNCARG3XV(this, src_arg, src_prop_arg);
276     CYG_PRECONDITION_THISC();
277     CYG_PRECONDITION_CLASSC(src_arg);
278     CYG_PRECONDITION_CLASSC(src_prop_arg);
279
280     if (0 != dest) {
281         std::vector<CdlReferrer>::iterator ref_i;
282         for (ref_i = dest->referrers.begin(); ref_i != dest->referrers.end(); ref_i++) {
283             if ((ref_i->source == src_arg) && (ref_i->source_property == src_prop_arg)) {
284                 dest->referrers.erase(ref_i);
285                 break;
286             }
287         }
288     }
289
290     dest = 0;
291
292     CYG_REPORT_RETURN();
293 }
294
295 //}}}
296 //{{{  CdlReferrer class                
297
298 // ----------------------------------------------------------------------------
299 // The constructors etc. should only get invoked from
300 // CdlReference::bind() and unbind(). However because Referrer objects
301 // get held in  STL vectors/lists/whatever it is hard to know exactly
302 // what will happen when, so assertions are a bit thin on the ground.
303
304 CdlReferrer::CdlReferrer()
305 {
306     CYG_REPORT_FUNCNAME("CdlReferrer:: default constructor");
307     CYG_REPORT_FUNCARG1XV(this);
308
309     source              = 0;
310     source_property     = 0;
311     cdlreferrer_cookie  = CdlReferrer_Magic;
312     CYGDBG_MEMLEAK_CONSTRUCTOR();
313     
314     CYG_POSTCONDITION_THISC();
315     CYG_REPORT_RETURN();
316 }
317
318 CdlReferrer::CdlReferrer(const CdlReferrer& original)
319 {
320     CYG_REPORT_FUNCNAME("CdlReferrer:: copy constructor");
321     CYG_REPORT_FUNCARG2XV(this, &original);
322     CYG_PRECONDITION_CLASSOC(original);
323
324     source              = original.source;
325     source_property     = original.source_property;
326     cdlreferrer_cookie  = CdlReferrer_Magic;
327     CYGDBG_MEMLEAK_CONSTRUCTOR();
328
329     CYG_POSTCONDITION_THISC();
330     CYG_REPORT_RETURN();
331 }
332
333 CdlReferrer&
334 CdlReferrer::operator=(const CdlReferrer& original)
335 {
336     CYG_REPORT_FUNCNAME("CdlReferrer:: assignment operator");
337     CYG_REPORT_FUNCARG2XV(this, &original);
338     CYG_PRECONDITION_CLASSOC(original);
339
340     if (this != &original) {
341         source                  = original.source;
342         source_property         = original.source_property;
343         cdlreferrer_cookie      = CdlReferrer_Magic;
344     }
345
346     CYG_POSTCONDITION_THISC();
347     CYG_REPORT_RETURN();
348     return *this;
349 }
350
351 CdlReferrer::~CdlReferrer()
352 {
353     CYG_REPORT_FUNCNAME("CdlReferrer:: destructor");
354     CYG_REPORT_FUNCARG1XV(this);
355     CYG_PRECONDITION_THISC();
356
357     cdlreferrer_cookie  = CdlReferrer_Magic;
358     source              = 0;
359     source_property     = 0;
360     CYGDBG_MEMLEAK_DESTRUCTOR();
361
362     CYG_REPORT_RETURN();
363 }
364
365 // ----------------------------------------------------------------------------
366 // This routine is the main reason for having reference and referrer
367 // objects around in the first place. It allows changes to an entity
368 // to be propagated back to anything else interested in the entity.
369
370 void
371 CdlReferrer::update(CdlTransaction transact, CdlNode dest_arg, CdlUpdate change)
372 {
373     CYG_REPORT_FUNCNAME("CdlReferrer::update");
374     CYG_REPORT_FUNCARG4XV(this, transact, dest_arg, change);
375     CYG_PRECONDITION_THISC();
376
377     source_property->update(transact, source, dest_arg, change);
378
379     CYG_REPORT_RETURN();
380 }
381
382 CdlNode
383 CdlReferrer::get_source() const
384 {
385     CYG_REPORT_FUNCNAMETYPE("CdlReferrer::get_source", "result %p");
386     CYG_REPORT_FUNCARG1XV(this);
387     CYG_PRECONDITION_THISC();
388
389     CdlNode result = source;
390     CYG_REPORT_RETVAL(result);
391     return result;
392 }
393
394 CdlProperty
395 CdlReferrer::get_source_property() const
396 {
397     CYG_REPORT_FUNCNAMETYPE("CdlReferrer::get_source_property", "result %p");
398     CYG_REPORT_FUNCARG1XV(this);
399     CYG_PRECONDITION_THISC();
400
401     CdlProperty result = source_property;
402     CYG_REPORT_RETVAL(result);
403     return result;
404 }
405
406 bool
407 CdlReferrer::check_this(cyg_assert_class_zeal zeal) const
408 {
409     if (CdlReferrer_Magic != cdlreferrer_cookie) {
410         return false;
411     }
412     CYGDBG_MEMLEAK_CHECKTHIS();
413     switch(zeal) {
414       case cyg_system_test :
415       case cyg_extreme:
416       case cyg_thorough:
417           if (0 != source) {
418               if (!source->check_this(cyg_quick)) {
419                   return false;
420               }
421           }
422           if (0 != source_property) {
423               if (!source_property->check_this(cyg_quick)) {
424                   return false;
425               }
426           }
427       case cyg_quick:
428       case cyg_trivial:
429       case cyg_none:
430         break;
431     }
432     return true;
433 }
434
435 //}}}