Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Baji, Laszlo | |
10 | * Balasko, Jeno | |
11 | * Raduly, Csaba | |
12 | * | |
13 | ******************************************************************************/ | |
970ed795 EL |
14 | #include "CompType.hh" |
15 | ||
16 | #include "ttcn3/AST_ttcn3.hh" | |
17 | #include "ttcn3/Attributes.hh" | |
18 | ||
19 | // implemented in comptype_attrib_la.l | |
20 | extern void parseExtendsCompTypeRefList(Ttcn::AttributeSpec const& attrib, | |
21 | Common::CompTypeRefList*& attr_comp_refs); | |
22 | ||
23 | namespace Common { | |
24 | ||
25 | // ================================= | |
26 | // ===== ComponentTypeBody | |
27 | // ================================= | |
28 | ||
29 | ComponentTypeBody::~ComponentTypeBody() | |
30 | { | |
31 | for(size_t i = 0; i < def_v.size(); i++) delete def_v[i]; | |
32 | def_v.clear(); | |
33 | delete extends_refs; | |
34 | delete attr_extends_refs; | |
35 | all_defs_m.clear(); | |
36 | orig_defs_m.clear(); | |
37 | compatible_m.clear(); | |
38 | } | |
39 | ||
40 | ComponentTypeBody *ComponentTypeBody::clone() const | |
41 | { | |
42 | FATAL_ERROR("ComponentTypeBody::clone()"); | |
43 | } | |
44 | ||
45 | void ComponentTypeBody::set_fullname(const string& p_fullname) | |
46 | { | |
47 | Scope::set_fullname(p_fullname); | |
48 | for(size_t i = 0; i < def_v.size(); i++) { | |
49 | Ttcn::Definition *def = def_v[i]; | |
50 | def->set_fullname(p_fullname + "." + def->get_id().get_dispname()); | |
51 | } | |
52 | if (extends_refs) | |
53 | extends_refs->set_fullname(p_fullname+".<extends>"); | |
54 | if (attr_extends_refs) | |
55 | attr_extends_refs->set_fullname(get_fullname()+".<extends attribute>"); | |
56 | } | |
57 | ||
58 | void ComponentTypeBody::set_my_scope(Scope *p_scope) | |
59 | { | |
60 | set_parent_scope(p_scope); | |
61 | if (extends_refs) extends_refs->set_my_scope(p_scope); | |
62 | if (attr_extends_refs) attr_extends_refs->set_my_scope(p_scope); | |
63 | } | |
64 | ||
65 | void ComponentTypeBody::add_extends(CompTypeRefList *p_crl) | |
66 | { | |
67 | if (extends_refs || !p_crl || check_state!=CHECK_INITIAL) | |
68 | FATAL_ERROR("ComponentTypeBody::add_extends()"); | |
69 | extends_refs = p_crl; | |
70 | } | |
71 | ||
72 | bool ComponentTypeBody::is_compatible(ComponentTypeBody *other) | |
73 | { | |
74 | if (other==this) return true; | |
75 | chk(CHECK_EXTENDS); | |
76 | other->chk(CHECK_EXTENDS); | |
77 | // a component with no definitions is compatible with all components | |
78 | if (def_v.size()==0 && !extends_refs && !attr_extends_refs) return true; | |
79 | return other->compatible_m.has_key(this); | |
80 | } | |
81 | ||
82 | void ComponentTypeBody::add_ass(Ttcn::Definition *p_ass) | |
83 | { | |
84 | if (check_state!=CHECK_INITIAL || !p_ass) | |
85 | FATAL_ERROR("ComponentTypeBody::add_ass()"); | |
86 | p_ass->set_my_scope(this); | |
87 | def_v.add(p_ass); | |
88 | } | |
89 | ||
90 | bool ComponentTypeBody::has_local_ass_withId(const Identifier& p_id) | |
91 | { | |
92 | chk(); | |
93 | return all_defs_m.has_key(p_id.get_name()); | |
94 | } | |
95 | ||
96 | Assignment* ComponentTypeBody::get_local_ass_byId(const Identifier& p_id) | |
97 | { | |
98 | chk(); | |
99 | return all_defs_m[p_id.get_name()]; | |
100 | } | |
101 | ||
102 | size_t ComponentTypeBody::get_nof_asss() | |
103 | { | |
104 | chk(); | |
105 | return all_defs_m.size(); | |
106 | } | |
107 | ||
108 | bool ComponentTypeBody::has_ass_withId(const Identifier& p_id) | |
109 | { | |
110 | if (has_local_ass_withId(p_id)) return true; | |
111 | else if (parent_scope) return parent_scope->has_ass_withId(p_id); | |
112 | else return false; | |
113 | } | |
114 | ||
115 | Assignment* ComponentTypeBody::get_ass_byIndex(size_t p_i) | |
116 | { | |
117 | chk(); | |
118 | return all_defs_m.get_nth_elem(p_i); | |
119 | } | |
120 | ||
121 | bool ComponentTypeBody::is_own_assignment(const Assignment* p_ass) | |
122 | { | |
123 | for(size_t i = 0; i < def_v.size(); i++) { | |
124 | if (def_v[i] == p_ass) return true; | |
125 | } | |
126 | return false; | |
127 | } | |
128 | ||
129 | Assignment* ComponentTypeBody::get_ass_bySRef(Ref_simple *p_ref) | |
130 | { | |
131 | if (!p_ref || !parent_scope) | |
132 | FATAL_ERROR("ComponentTypeBody::get_ass_bySRef()"); | |
133 | if (!p_ref->get_modid()) { | |
134 | const Identifier *id = p_ref->get_id(); | |
135 | if (id && has_local_ass_withId(*id)) { | |
136 | Assignment* ass = get_local_ass_byId(*id); | |
137 | if (!ass) FATAL_ERROR("ComponentTypeBody::get_ass_bySRef()"); | |
138 | ||
139 | for(size_t i = 0; i < def_v.size(); i++) { | |
140 | if (def_v[i] == ass) return ass; | |
141 | } | |
142 | ||
143 | if (ass->get_visibility() == PUBLIC) { | |
144 | return ass; | |
145 | } | |
146 | ||
147 | p_ref->error("The member definition `%s' in component type `%s'" | |
148 | " is not visible in this scope", id->get_dispname().c_str(), | |
149 | comp_id->get_dispname().c_str()); | |
150 | return 0; | |
151 | } | |
152 | } | |
153 | return parent_scope->get_ass_bySRef(p_ref); | |
154 | } | |
155 | ||
156 | void ComponentTypeBody::dump(unsigned level) const | |
157 | { | |
158 | if (extends_refs) { | |
159 | DEBUG(level, "Extends references:"); | |
160 | extends_refs->dump(level+1); | |
161 | } | |
162 | DEBUG(level, "Definitions: (%lu pcs.)", (unsigned long) def_v.size()); | |
163 | for(size_t i = 0; i < def_v.size(); i++) def_v[i]->dump(level + 1); | |
164 | if (attr_extends_refs) { | |
165 | DEBUG(level, "Extends attribute references:"); | |
166 | attr_extends_refs->dump(level+1); | |
167 | } | |
168 | } | |
169 | ||
170 | // read out the contents of the with attribute extension, | |
171 | // parse it to the the attr_extends_refs member variable, | |
172 | // collects all extends components from all attributes along the attrib path | |
173 | void ComponentTypeBody::chk_extends_attr() | |
174 | { | |
175 | if (check_state>=CHECK_WITHATTRIB) return; | |
176 | check_state = CHECK_WITHATTRIB; | |
177 | Ttcn::WithAttribPath* w_attrib_path = my_type->get_attrib_path(); | |
178 | if(w_attrib_path) | |
179 | { | |
180 | vector<Ttcn::SingleWithAttrib> const &real_attribs = | |
181 | w_attrib_path->get_real_attrib(); | |
182 | for (size_t i = 0; i < real_attribs.size(); i++) | |
183 | { | |
184 | Ttcn::SingleWithAttrib *act_attr = real_attribs[i]; | |
185 | if (act_attr->get_attribKeyword()==Ttcn::SingleWithAttrib::AT_EXTENSION) | |
186 | parseExtendsCompTypeRefList(act_attr->get_attribSpec(), | |
187 | attr_extends_refs); | |
188 | } | |
189 | } | |
190 | if (attr_extends_refs) | |
191 | { | |
192 | attr_extends_refs->set_fullname(get_fullname()+".<extends attribute>"); | |
193 | attr_extends_refs->set_my_scope(parent_scope); | |
194 | } | |
195 | } | |
196 | ||
197 | void ComponentTypeBody::chk_recursion(ReferenceChain& refch) | |
198 | { | |
199 | if (refch.add(get_fullname())) { | |
200 | if (extends_refs) extends_refs->chk_recursion(refch); | |
201 | if (attr_extends_refs) attr_extends_refs->chk_recursion(refch); | |
202 | } | |
203 | } | |
204 | ||
205 | // contained components must already be checked, | |
206 | // having valid compatible_m maps | |
207 | void ComponentTypeBody::init_compatibility(CompTypeRefList *crl, | |
208 | bool is_standard_extends) | |
209 | { | |
210 | for (size_t i = 0; i < crl->get_nof_comps(); i++) | |
211 | { | |
212 | ComponentTypeBody *cb = crl->get_nth_comp_body(i); | |
213 | if (!compatible_m.has_key(cb)) | |
214 | compatible_m.add(cb, is_standard_extends ? cb : NULL); | |
215 | // compatible with all components which are compatible with the compatible | |
216 | // component | |
217 | for (size_t j = 0; j < cb->compatible_m.size(); j++) | |
218 | { | |
219 | ComponentTypeBody *ccb = cb->compatible_m.get_nth_key(j); | |
220 | ComponentTypeBody *ccbval = cb->compatible_m.get_nth_elem(j); | |
221 | if (!compatible_m.has_key(ccb)) | |
222 | compatible_m.add(ccb, is_standard_extends ? ccbval : NULL); | |
223 | } | |
224 | } | |
225 | } | |
226 | ||
227 | void ComponentTypeBody::chk_extends() | |
228 | { | |
229 | if (check_state>=CHECK_EXTENDS) return; | |
230 | check_state = CHECK_EXTENDS; | |
231 | // check the references in component extends parts (keyword and attribute) | |
232 | if (extends_refs) extends_refs->chk(CHECK_EXTENDS); | |
233 | if (attr_extends_refs) attr_extends_refs->chk(CHECK_EXTENDS); | |
234 | // check for circular reference chains | |
235 | ReferenceChain refch(this, "While checking component type extensions"); | |
236 | chk_recursion(refch); | |
237 | // build compatibility map for faster is_compatible() and generate_code() | |
238 | // contained components must already have valid compatible_m map | |
239 | // keys used in is_compatible(), values used in generate_code() | |
240 | if (extends_refs) init_compatibility(extends_refs, true); | |
241 | if (attr_extends_refs) init_compatibility(attr_extends_refs, false); | |
242 | } | |
243 | ||
244 | void ComponentTypeBody::collect_defs_from_standard_extends() | |
245 | { | |
246 | Assignments *module_defs = parent_scope->get_scope_asss(); | |
247 | for (size_t i = 0; i < extends_refs->get_nof_comps(); i++) { | |
248 | ComponentTypeBody *parent = extends_refs->get_nth_comp_body(i); | |
249 | // iterate through all definitions of the parent | |
250 | // parent is already checked (has it's inherited defs included) | |
251 | for (size_t j = 0; j < parent->all_defs_m.size(); j++) { | |
252 | Ttcn::Definition *def = parent->all_defs_m.get_nth_elem(j); | |
253 | const Identifier& id = def->get_id(); | |
254 | const string& name = id.get_name(); | |
255 | if (all_defs_m.has_key(name)) { | |
256 | Ttcn::Definition *my_def = all_defs_m[name]; | |
257 | if (my_def != def) { | |
258 | // it is not the same definition inherited on two paths | |
259 | const char *dispname_str = id.get_dispname().c_str(); | |
260 | if (my_def->get_my_scope() == this) { | |
261 | my_def->error("Local definition `%s' collides with definition " | |
262 | "inherited from component type `%s'", dispname_str, | |
263 | def->get_my_scope()->get_fullname().c_str()); | |
264 | def->note("Inherited definition of `%s' is here", dispname_str); | |
265 | } else { | |
266 | error("Definition `%s' inherited from component type `%s' " | |
267 | "collides with definition inherited from `%s'", dispname_str, | |
268 | def->get_my_scope()->get_fullname().c_str(), | |
269 | my_def->get_my_scope()->get_fullname().c_str()); | |
270 | def->note("Definition of `%s' in `%s' is here", dispname_str, | |
271 | def->get_my_scope()->get_fullname().c_str()); | |
272 | my_def->note("Definition of `%s' in `%s' is here", dispname_str, | |
273 | my_def->get_my_scope()->get_fullname().c_str()); | |
274 | } | |
275 | } | |
276 | } else { | |
277 | all_defs_m.add(name, def); | |
278 | if (def->get_my_scope()->get_scope_mod() != | |
279 | module_defs->get_scope_mod()) { | |
280 | // def comes from another module | |
281 | if (module_defs->has_local_ass_withId(id)) { | |
282 | const char *dispname_str = id.get_dispname().c_str(); | |
283 | error("The name of inherited definition `%s' is not unique in " | |
284 | "the scope hierarchy", dispname_str); | |
285 | module_defs->get_local_ass_byId(id)->note("Symbol `%s' is " | |
286 | "already defined here in a higher scope unit", dispname_str); | |
287 | def->note("Definition `%s' inherited from component type `%s' " | |
288 | "is here", dispname_str, | |
289 | def->get_my_scope()->get_fullname().c_str()); | |
290 | } else if (module_defs->is_valid_moduleid(id)) { | |
291 | def->warning("Inherited definition with name `%s' hides a " | |
292 | "module identifier", id.get_dispname().c_str()); | |
293 | } | |
294 | } | |
295 | } | |
296 | } | |
297 | } | |
298 | } | |
299 | ||
300 | void ComponentTypeBody::collect_defs_from_attribute_extends() | |
301 | { | |
302 | for (size_t i = 0; i < attr_extends_refs->get_nof_comps(); i++) { | |
303 | ComponentTypeBody *parent = attr_extends_refs->get_nth_comp_body(i); | |
304 | // iterate through all definitions of the parent | |
305 | // parent is already checked (has it's inherited defs included) | |
306 | for (size_t j = 0; j < parent->all_defs_m.size(); j++) { | |
307 | Ttcn::Definition *def = parent->all_defs_m.get_nth_elem(j); | |
308 | const Identifier& id = def->get_id(); | |
309 | const char *dispname_str = id.get_dispname().c_str(); | |
310 | const string& name = id.get_name(); | |
311 | // the definition to be imported must be already in the all_defs_m map | |
312 | // and must belong to owner (not be inherited) | |
313 | // orig_defs_map contains backed up own definitions | |
314 | if (all_defs_m.has_key(name)) { | |
315 | Ttcn::Definition *my_def = all_defs_m[name]; | |
316 | if (my_def->get_my_scope() == this) { | |
317 | // my_def is a local definition | |
318 | if (orig_defs_m.has_key(name)) FATAL_ERROR( \ | |
319 | "ComponentTypeBody::collect_defs_from_attribute_extends()"); | |
320 | orig_defs_m.add(name, my_def); // backup for init | |
321 | all_defs_m[name] = def; // point to inherited def | |
322 | } else { | |
323 | // my_def comes from another component type | |
324 | // exclude case when the same definition is inherited on different | |
325 | // paths, there must be a local definition | |
326 | if (def!=my_def || !orig_defs_m.has_key(name)) { | |
327 | error("Definition `%s' inherited from component type `%s' " | |
328 | "collides with definition inherited from `%s'", dispname_str, | |
329 | def->get_my_scope()->get_fullname().c_str(), | |
330 | my_def->get_my_scope()->get_fullname().c_str()); | |
331 | def->note("Definition of `%s' in `%s' is here", | |
332 | dispname_str, def->get_my_scope()->get_fullname().c_str()); | |
333 | my_def->note("Definition of `%s' in `%s' is here", | |
334 | dispname_str, my_def->get_my_scope()->get_fullname().c_str()); | |
335 | if (orig_defs_m.has_key(name)) { | |
336 | // the same definition is also present locally | |
337 | orig_defs_m[name]->note("Local definition of `%s' is here", | |
338 | dispname_str); | |
339 | } | |
340 | } | |
341 | } | |
342 | } else { | |
343 | error("Missing local definition of `%s', which was inherited from " | |
344 | "component type `%s'", dispname_str, | |
345 | def->get_my_scope()->get_fullname().c_str()); | |
346 | def->note("Inherited definition of `%s' is here", dispname_str); | |
347 | } | |
348 | } | |
349 | } | |
350 | } | |
351 | ||
352 | void ComponentTypeBody::chk_defs_uniq() | |
353 | { | |
354 | if (check_state>=CHECK_DEFUNIQ) return; | |
355 | check_state = CHECK_DEFUNIQ; | |
356 | if (extends_refs) extends_refs->chk(CHECK_DEFUNIQ); | |
357 | if (attr_extends_refs) attr_extends_refs->chk(CHECK_DEFUNIQ); | |
358 | size_t nof_defs = def_v.size(); | |
359 | if (nof_defs > 0) { | |
360 | Error_Context cntxt(this, "While checking uniqueness of component " | |
361 | "element definitions"); | |
362 | Assignments *module_defs = parent_scope->get_scope_asss(); | |
363 | // add own definitions to all_def_m | |
364 | for (size_t i = 0; i < nof_defs; i++) { | |
365 | Ttcn::Definition *def = def_v[i]; | |
366 | const Identifier& id = def->get_id(); | |
367 | const string& name = id.get_name(); | |
368 | if (all_defs_m.has_key(name)) { | |
369 | const char *dispname_str = id.get_dispname().c_str(); | |
370 | def->error("Duplicate definition with name `%s'", dispname_str); | |
371 | all_defs_m[name]->note("Previous definition of `%s' is here", | |
372 | dispname_str); | |
373 | } else { | |
374 | all_defs_m.add(name, def); | |
375 | if (module_defs->has_local_ass_withId(id)) { | |
376 | const char *dispname_str = id.get_dispname().c_str(); | |
377 | def->error("Component element name `%s' is not unique in the " | |
378 | "scope hierarchy", dispname_str); | |
379 | module_defs->get_local_ass_byId(id)->note("Symbol `%s' is " | |
380 | "already defined here in a higher scope unit", dispname_str); | |
381 | } else if (module_defs->is_valid_moduleid(id)) { | |
382 | def->warning("Definition with name `%s' hides a module identifier", | |
383 | id.get_dispname().c_str()); | |
384 | } | |
385 | } | |
386 | } | |
387 | } | |
388 | if (extends_refs || attr_extends_refs) { | |
389 | // collect all inherited definitions | |
390 | Error_Context cntxt(this, "While checking uniqueness of inherited " | |
391 | "component element definitions"); | |
392 | if (extends_refs) collect_defs_from_standard_extends(); | |
393 | if (attr_extends_refs) collect_defs_from_attribute_extends(); | |
394 | } | |
395 | } | |
396 | ||
397 | void ComponentTypeBody::chk_my_defs() | |
398 | { | |
399 | if (check_state>=CHECK_OWNDEFS) return; | |
400 | check_state = CHECK_OWNDEFS; | |
401 | Error_Context cntxt(this, "In component element definitions"); | |
402 | for (size_t i = 0; i < def_v.size(); i++) def_v[i]->chk(); | |
403 | } | |
404 | ||
405 | void ComponentTypeBody::chk_attr_ext_defs() | |
406 | { | |
407 | if (check_state>=CHECK_EXTDEFS) return; | |
408 | check_state = CHECK_EXTDEFS; | |
409 | size_t nof_inherited_defs = orig_defs_m.size(); | |
410 | if (nof_inherited_defs > 0) { | |
411 | Error_Context cntxt(this, "While checking whether the local and " | |
412 | "inherited component element definitions are identical"); | |
413 | // for definitions inherited with attribute extends check if | |
414 | // local and inherited definitions are identical | |
415 | for (size_t i = 0; i < nof_inherited_defs; i++) { | |
416 | const string& key = orig_defs_m.get_nth_key(i); | |
417 | Ttcn::Definition *original_def = orig_defs_m.get_nth_elem(i); | |
418 | Ttcn::Definition *inherited_def = all_defs_m[key]; | |
419 | if (!original_def->chk_identical(inherited_def)) | |
420 | all_defs_m[key] = original_def; | |
421 | } | |
422 | } | |
423 | } | |
424 | ||
425 | void ComponentTypeBody::chk(check_state_t required_check_state) | |
426 | { | |
427 | if (checking || check_state==CHECK_FINAL) return; | |
428 | checking = true; | |
429 | switch (check_state) | |
430 | { | |
431 | case CHECK_INITIAL: | |
432 | chk_extends_attr(); | |
433 | if (required_check_state==CHECK_WITHATTRIB) break; | |
434 | // no break | |
435 | case CHECK_WITHATTRIB: | |
436 | chk_extends(); | |
437 | if (required_check_state==CHECK_EXTENDS) break; | |
438 | // no break | |
439 | case CHECK_EXTENDS: | |
440 | chk_defs_uniq(); | |
441 | if (required_check_state==CHECK_DEFUNIQ) break; | |
442 | // no break | |
443 | case CHECK_DEFUNIQ: | |
444 | chk_my_defs(); | |
445 | if (required_check_state==CHECK_OWNDEFS) break; | |
446 | // no break | |
447 | case CHECK_OWNDEFS: | |
448 | chk_attr_ext_defs(); | |
449 | if (required_check_state==CHECK_EXTDEFS) break; | |
450 | // no break | |
451 | case CHECK_EXTDEFS: | |
452 | check_state = CHECK_FINAL; | |
453 | // no break | |
454 | case CHECK_FINAL: | |
455 | break; | |
456 | default: | |
457 | FATAL_ERROR("ComponentTypeBody::chk()"); | |
458 | } | |
459 | checking = false; | |
460 | } | |
461 | ||
462 | void ComponentTypeBody::set_genname(const string& prefix) | |
463 | { | |
464 | for (size_t i = 0; i < def_v.size(); i++) { | |
465 | Ttcn::Definition *def = def_v[i]; | |
466 | def->set_genname(prefix + def->get_id().get_name()); | |
467 | } | |
468 | } | |
469 | ||
470 | ||
471 | void ComponentTypeBody::generate_code(output_struct* target) | |
472 | { | |
473 | if (check_state != CHECK_FINAL || !comp_id) | |
474 | FATAL_ERROR("ComponentTypeBody::generate_code()"); | |
475 | // beginning of block in init_comp | |
476 | target->functions.init_comp = mputprintf(target->functions.init_comp, | |
477 | "if (!strcmp(component_type, \"%s\")) {\n", | |
478 | comp_id->get_dispname().c_str()); | |
479 | ||
480 | // call init_comp for all components which are compatible | |
481 | // with this component along standard extends paths | |
482 | if (extends_refs) { | |
483 | bool has_base_comps = false; | |
484 | for (size_t i = 0; i < compatible_m.size(); i++) { | |
485 | ComponentTypeBody *cb = compatible_m.get_nth_elem(i); | |
486 | // recursive initialization is needed if the component type is | |
487 | // inherited using the standard "extends" mechanism and the component | |
488 | // type has its own definitions | |
489 | if (cb && cb->def_v.size() > 0) { | |
490 | if (!has_base_comps) { | |
491 | target->functions.init_comp = mputstr(target->functions.init_comp, | |
492 | "if (init_base_comps) {\n"); | |
493 | has_base_comps = true; | |
494 | } | |
495 | const char *ct_dispname_str = cb->get_id()->get_dispname().c_str(); | |
496 | Module *ct_mod = cb->get_scope_mod_gen(); | |
497 | if (ct_mod == get_scope_mod_gen()) { | |
498 | // the other component type is in the same module | |
499 | // call the initializer function recursively | |
500 | target->functions.init_comp = mputprintf( | |
501 | target->functions.init_comp, "init_comp_type(\"%s\", FALSE);\n", | |
502 | ct_dispname_str); | |
503 | } else { | |
504 | // the other component type is imported from another module | |
505 | // use the module list for initialization | |
506 | target->functions.init_comp = mputprintf( | |
507 | target->functions.init_comp, | |
508 | "Module_List::initialize_component(\"%s\", \"%s\", FALSE);\n", | |
509 | ct_mod->get_modid().get_dispname().c_str(), ct_dispname_str); | |
510 | } | |
511 | } | |
512 | } | |
513 | if (has_base_comps) { | |
514 | // closing of the if() above | |
515 | target->functions.init_comp = mputstr(target->functions.init_comp, | |
516 | "}\n"); | |
517 | } | |
518 | } | |
519 | ||
520 | // code generation for embedded definitions | |
521 | size_t nof_defs = def_v.size(); | |
522 | for (size_t i = 0; i < nof_defs; i++) { | |
523 | Ttcn::Definition *def = def_v[i]; | |
524 | const string& name = def->get_id().get_name(); | |
525 | if (orig_defs_m.has_key(name)) { | |
526 | // def is hidden by an inherited definiton | |
527 | // only an initializer shall be generated | |
528 | target->functions.init_comp = def->generate_code_init_comp( | |
529 | target->functions.init_comp, all_defs_m[name]); | |
530 | } else { | |
531 | // def is a normal (non-inherited) definition | |
532 | def->generate_code(target, true); | |
533 | } | |
534 | } | |
535 | ||
536 | // end of block in init_comp | |
537 | target->functions.init_comp = mputstr(target->functions.init_comp, | |
538 | "return TRUE;\n" | |
539 | "} else "); | |
540 | } | |
541 | ||
542 | char *ComponentTypeBody::generate_code_comptype_name(char *str) | |
543 | { | |
544 | if (!comp_id) | |
545 | FATAL_ERROR("ComponentTypeBody::generate_code_comtype_name()"); | |
546 | return mputprintf(str, "\"%s\", \"%s\"", | |
547 | parent_scope->get_scope_mod_gen()->get_modid().get_dispname().c_str(), | |
548 | comp_id->get_dispname().c_str()); | |
549 | } | |
550 | ||
551 | void ComponentTypeBody::set_parent_path(Ttcn::WithAttribPath* p_path) { | |
552 | for (size_t i = 0; i < def_v.size(); i++) | |
553 | def_v[i]->set_parent_path(p_path); | |
554 | } | |
555 | ||
556 | // ================================= | |
557 | // ===== CompTypeRefList | |
558 | // ================================= | |
559 | ||
560 | CompTypeRefList::~CompTypeRefList() | |
561 | { | |
562 | for (size_t i=0; i<comp_ref_v.size(); i++) delete comp_ref_v[i]; | |
563 | comp_ref_v.clear(); | |
564 | comp_body_m.clear(); | |
565 | comp_body_v.clear(); | |
566 | } | |
567 | ||
568 | CompTypeRefList *CompTypeRefList::clone() const | |
569 | { | |
570 | FATAL_ERROR("CompTypeRefList::clone()"); | |
571 | } | |
572 | ||
573 | void CompTypeRefList::add_ref(Ttcn::Reference *p_ref) | |
574 | { | |
575 | if (!p_ref || checked) FATAL_ERROR("CompTypeRefList::add_ref()"); | |
576 | comp_ref_v.add(p_ref); | |
577 | } | |
578 | ||
579 | void CompTypeRefList::dump(unsigned level) const | |
580 | { | |
581 | for(size_t i = 0; i < comp_ref_v.size(); i++) comp_ref_v[i]->dump(level+1); | |
582 | } | |
583 | ||
584 | void CompTypeRefList::set_fullname(const string& p_fullname) | |
585 | { | |
586 | Node::set_fullname(p_fullname); | |
587 | for (size_t i=0; i<comp_ref_v.size(); i++) | |
588 | comp_ref_v[i]->set_fullname(p_fullname + ".<ref" + Int2string(i+1) + ">"); | |
589 | } | |
590 | ||
591 | void CompTypeRefList::chk_uniq() | |
592 | { | |
593 | if (checked) return; | |
594 | checked = true; | |
595 | for (size_t i = 0; i < comp_ref_v.size(); i++) | |
596 | { | |
597 | Ttcn::Reference *ref = comp_ref_v[i]; | |
598 | Type *type = ref->chk_comptype_ref(); | |
599 | if (type) | |
600 | { | |
601 | // add the component body to the map or error if it's duplicate | |
602 | ComponentTypeBody *cb = type->get_CompBody(); | |
603 | if (cb) | |
604 | { | |
605 | if (comp_body_m.has_key(cb)) | |
606 | { | |
607 | const string& type_name = type->get_typename(); | |
608 | const char *name = type_name.c_str(); | |
609 | ref->error("Duplicate reference to component with name `%s'", name); | |
610 | comp_body_m[cb]->note("Previous reference to `%s' is here", name); | |
611 | } | |
612 | else | |
613 | { | |
614 | // map and vector must always have same content | |
615 | comp_body_m.add(cb, ref); | |
616 | comp_body_v.add(cb); | |
617 | } | |
618 | } | |
619 | } | |
620 | } | |
621 | } | |
622 | ||
623 | void CompTypeRefList::chk(ComponentTypeBody::check_state_t | |
624 | required_check_state) | |
625 | { | |
626 | chk_uniq(); | |
627 | for (size_t i=0; i<comp_body_v.size(); i++) | |
628 | comp_body_v[i]->chk(required_check_state); | |
629 | } | |
630 | ||
631 | void CompTypeRefList::chk_recursion(ReferenceChain& refch) | |
632 | { | |
633 | for (size_t i = 0; i < comp_body_v.size(); i++) { | |
634 | refch.mark_state(); | |
635 | comp_body_v[i]->chk_recursion(refch); | |
636 | refch.prev_state(); | |
637 | } | |
638 | } | |
639 | ||
640 | void CompTypeRefList::set_my_scope(Scope *p_scope) | |
641 | { | |
642 | for (size_t i=0; i<comp_ref_v.size(); i++) | |
643 | comp_ref_v[i]->set_my_scope(p_scope); | |
644 | } | |
645 | ||
646 | size_t CompTypeRefList::get_nof_comps() | |
647 | { | |
648 | if (!checked) chk_uniq(); | |
649 | return comp_body_v.size(); | |
650 | } | |
651 | ||
652 | ComponentTypeBody *CompTypeRefList::get_nth_comp_body(size_t i) | |
653 | { | |
654 | if (!checked) chk_uniq(); | |
655 | return comp_body_v[i]; | |
656 | } | |
657 | ||
658 | Ttcn::Reference *CompTypeRefList::get_nth_comp_ref(size_t i) | |
659 | { | |
660 | if (!checked) chk_uniq(); | |
661 | return comp_body_m[comp_body_v[i]]; | |
662 | } | |
663 | ||
664 | bool CompTypeRefList::has_comp_body(ComponentTypeBody *cb) | |
665 | { | |
666 | if (!checked) chk_uniq(); | |
667 | return comp_body_m.has_key(cb); | |
668 | } | |
669 | ||
670 | } /* namespace Common */ |