1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 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 ///////////////////////////////////////////////////////////////////////////////
10 #include "../common/memory.h"
12 #include "Component.hh"
14 #include "Parameters.h"
15 #include "Param_Types.hh"
17 #include "Optional.hh"
19 #include "../common/dbgnew.hh"
21 COMPONENT::COMPONENT()
23 component_value
= UNBOUND_COMPREF
;
26 COMPONENT::COMPONENT(component other_value
)
28 component_value
= other_value
;
31 COMPONENT::COMPONENT(const COMPONENT
& other_value
)
32 : Base_Type(other_value
)
34 if (other_value
.component_value
== UNBOUND_COMPREF
)
35 TTCN_error("Copying an unbound component reference.");
36 component_value
= other_value
.component_value
;
39 COMPONENT
& COMPONENT::operator=(component other_value
)
41 component_value
= other_value
;
45 COMPONENT
& COMPONENT::operator=(const COMPONENT
& other_value
)
47 if (other_value
.component_value
== UNBOUND_COMPREF
)
48 TTCN_error("Assignment of an unbound component reference.");
49 component_value
= other_value
.component_value
;
53 boolean
COMPONENT::operator==(component other_value
) const
55 if (component_value
== UNBOUND_COMPREF
) TTCN_error("The left operand of "
56 "comparison is an unbound component reference.");
57 return component_value
== other_value
;
60 boolean
COMPONENT::operator==(const COMPONENT
& other_value
) const
62 if (component_value
== UNBOUND_COMPREF
) TTCN_error("The left operand of "
63 "comparison is an unbound component reference.");
64 if (other_value
.component_value
== UNBOUND_COMPREF
) TTCN_error("The right "
65 "operand of comparison is an unbound component reference.");
66 return component_value
== other_value
.component_value
;
69 COMPONENT::operator component() const
71 if (component_value
== UNBOUND_COMPREF
) TTCN_error("Using the value of an "
72 "unbound component reference.");
73 return component_value
;
76 void COMPONENT::log() const
78 if (component_value
!= UNBOUND_COMPREF
)
79 log_component_reference(component_value
);
80 else TTCN_Logger::log_event_unbound();
83 alt_status
COMPONENT::done() const
85 if (component_value
== UNBOUND_COMPREF
) TTCN_error("Performing done "
86 "operation on an unbound component reference.");
87 return TTCN_Runtime::component_done(component_value
);
90 alt_status
COMPONENT::killed() const
92 if (component_value
== UNBOUND_COMPREF
) TTCN_error("Performing killed "
93 "operation on an unbound component reference.");
94 return TTCN_Runtime::component_killed(component_value
);
97 boolean
COMPONENT::running() const
99 if (component_value
== UNBOUND_COMPREF
) TTCN_error("Performing running "
100 "operation on an unbound component reference.");
101 return TTCN_Runtime::component_running(component_value
);
104 boolean
COMPONENT::alive() const
106 if (component_value
== UNBOUND_COMPREF
) TTCN_error("Performing alive "
107 "operation on an unbound component reference.");
108 return TTCN_Runtime::component_alive(component_value
);
111 void COMPONENT::stop() const
113 if (component_value
== UNBOUND_COMPREF
) TTCN_error("Performing stop "
114 "operation on an unbound component reference.");
115 TTCN_Runtime::stop_component(component_value
);
118 void COMPONENT::kill() const
120 if (component_value
== UNBOUND_COMPREF
) TTCN_error("Performing kill "
121 "operation on an unbound component reference.");
122 TTCN_Runtime::kill_component(component_value
);
125 void COMPONENT::set_param(Module_Param
& param
) {
126 param
.basic_check(Module_Param::BC_VALUE
, "component reference (integer or null) value");
127 if (Ttcn_String_Parsing::happening()) {
128 // accept all component values in case it's a string2ttcn operation
129 switch (param
.get_type()) {
130 case Module_Param::MP_Integer
:
131 component_value
= (component
)param
.get_integer()->get_val();
133 case Module_Param::MP_Ttcn_Null
:
134 component_value
= NULL_COMPREF
;
136 case Module_Param::MP_Ttcn_mtc
:
137 component_value
= MTC_COMPREF
;
139 case Module_Param::MP_Ttcn_system
:
140 component_value
= SYSTEM_COMPREF
;
143 param
.type_error("component reference (integer or null) value");
147 // only accept the null value if it's a module parameter
148 if (Module_Param::MP_Ttcn_Null
!= param
.get_type()) {
149 param
.error("Only the 'null' value is allowed for module parameters of type 'component'.");
151 component_value
= NULL_COMPREF
;
155 void COMPONENT::encode_text(Text_Buf
& text_buf
) const
157 if (component_value
== UNBOUND_COMPREF
) TTCN_error("Text encoder: Encoding "
158 "an unbound component reference.");
159 text_buf
.push_int((int)component_value
);
160 switch (component_value
) {
166 text_buf
.push_string(get_component_name(component_value
));
171 void COMPONENT::decode_text(Text_Buf
& text_buf
)
173 component_value
= (component
)text_buf
.pull_int().get_val();
174 switch (component_value
) {
180 char *component_name
= text_buf
.pull_string();
181 register_component_name(component_value
, component_name
);
182 delete [] component_name
;
187 boolean
operator==(component component_value
, const COMPONENT
& other_value
)
189 if (other_value
.component_value
== UNBOUND_COMPREF
) TTCN_error("The right "
190 "operand of comparison is an unbound component reference.");
191 return component_value
== other_value
.component_value
;
194 unsigned int COMPONENT::n_component_names
= 0;
195 struct COMPONENT::component_name_struct
{
196 component component_reference
;
197 char *component_name
;
198 } *COMPONENT::component_names
= NULL
;
200 void COMPONENT::register_component_name(component component_reference
,
201 const char *component_name
)
203 if (self
.component_value
== component_reference
) {
204 // the own name of the component will not be registered,
205 // but check whether we got the right string
206 const char *local_name
= TTCN_Runtime::get_component_name();
207 if (component_name
== NULL
|| component_name
[0] == '\0') {
208 if (local_name
!= NULL
) {
209 TTCN_error("Internal error: Trying to register the component "
210 "reference of this PTC without any name, but this "
211 "component has name %s.", local_name
);
214 if (local_name
== NULL
) {
215 TTCN_error("Internal error: Trying to register the component "
216 "reference of this PTC with name %s, but this component "
217 "does not have name.", component_name
);
218 } else if (strcmp(component_name
, local_name
)) {
219 TTCN_error("Internal error: Trying to register the component "
220 "reference of this PTC with name %s, but this component "
221 "has name %s.", component_name
, local_name
);
226 unsigned int min
= 0;
227 if (n_component_names
> 0) {
228 // perform a binary search to find the place for the component reference
229 unsigned int max
= n_component_names
- 1;
231 unsigned int mid
= min
+ (max
- min
) / 2;
232 if (component_names
[mid
].component_reference
< component_reference
)
234 else if (component_names
[mid
].component_reference
==
235 component_reference
) {
240 if (component_names
[min
].component_reference
== component_reference
) {
241 // the component reference is already registered
242 const char *stored_name
= component_names
[min
].component_name
;
243 if (component_name
== NULL
|| component_name
[0] == '\0') {
244 if (stored_name
!= NULL
) {
245 TTCN_error("Internal error: Trying to register component "
246 "reference %d without any name, but this component "
247 "reference is already registered with name %s.",
248 component_reference
, stored_name
);
251 if (stored_name
== NULL
) {
252 TTCN_error("Internal error: Trying to register component "
253 "reference %d with name %s, but this component "
254 "reference is already registered without name.",
255 component_reference
, component_name
);
256 } else if (strcmp(component_name
, stored_name
)) {
257 TTCN_error("Internal error: Trying to register component "
258 "reference %d with name %s, but this component "
259 "reference is already registered with a different "
260 "name (%s).", component_reference
, component_name
,
266 if (component_names
[min
].component_reference
< component_reference
)
268 // the component reference will be inserted before the index "min"
270 (component_name_struct
*)Realloc(component_names
,
271 (n_component_names
+ 1) * sizeof(*component_names
));
272 memmove(component_names
+ min
+ 1, component_names
+ min
,
273 (n_component_names
- min
) * sizeof(*component_names
));
276 // this is the first component reference to be registered
278 (component_name_struct
*)Malloc(sizeof(*component_names
));
280 component_names
[min
].component_reference
= component_reference
;
281 if (component_name
== NULL
|| component_name
[0] == '\0')
282 component_names
[min
].component_name
= NULL
;
283 else component_names
[min
].component_name
= mcopystr(component_name
);
287 const char *COMPONENT::get_component_name(component component_reference
)
289 if (self
.component_value
== component_reference
) {
290 // the own name of the PTC is not registered
291 return TTCN_Runtime::get_component_name();
292 } else if (n_component_names
> 0) {
293 unsigned int min
= 0, max
= n_component_names
- 1;
295 unsigned int mid
= min
+ (max
- min
) / 2;
296 if (component_names
[mid
].component_reference
< component_reference
)
298 else if (component_names
[mid
].component_reference
==
300 return component_names
[mid
].component_name
;
303 if (component_names
[min
].component_reference
!= component_reference
)
304 TTCN_error("Internal error: Trying to get the name of PTC with "
305 "component reference %d, but the name of the component "
306 "is not registered.", component_reference
);
307 return component_names
[min
].component_name
;
309 TTCN_error("Internal error: Trying to get the name of PTC with "
310 "component reference %d, but there are no component names "
311 "registered.", component_reference
);
316 void COMPONENT::clear_component_names()
318 for (unsigned int i
= 0; i
< n_component_names
; i
++)
319 Free(component_names
[i
].component_name
);
320 Free(component_names
);
321 n_component_names
= 0;
322 component_names
= NULL
;
325 void COMPONENT::log_component_reference(component component_reference
)
327 switch (component_reference
) {
329 TTCN_Logger::log_event_str("null");
332 TTCN_Logger::log_event_str("mtc");
335 TTCN_Logger::log_event_str("system");
338 const char *component_name
= get_component_name(component_reference
);
339 if (component_name
!= NULL
) TTCN_Logger::log_event("%s(%d)",
340 component_name
, component_reference
);
341 else TTCN_Logger::log_event("%d", component_reference
);
346 // get_component_string is suspiciously similar to log_component_reference.
347 // It would be trivially easy to implement log_... with get_...
348 // but it would involve a runtime penalty, because get_component_string
349 // returns a newly allocated string which must be freed, whereas log_...
350 // uses fixed strings. So the current implementation pays for speed with size.
351 // Perhaps log_component_reference will go away one day.
352 char *COMPONENT::get_component_string(component component_reference
)
354 switch (component_reference
) {
356 return mcopystr("null");
358 return mcopystr("mtc");
360 return mcopystr("system");
361 case CONTROL_COMPREF
:
362 return mcopystr("control");
364 const char *component_name
= get_component_name(component_reference
);
365 if (component_name
!= NULL
) return mprintf("%s(%d)",
366 component_name
, component_reference
);
367 else return mprintf("%d", component_reference
);
373 void COMPONENT_template::clean_up()
375 if (template_selection
== VALUE_LIST
376 ||template_selection
== COMPLEMENTED_LIST
)
377 delete [] value_list
.list_value
;
378 template_selection
= UNINITIALIZED_TEMPLATE
;
381 void COMPONENT_template::copy_template(const COMPONENT_template
& other_value
)
383 switch (other_value
.template_selection
) {
385 single_value
= other_value
.single_value
;
392 case COMPLEMENTED_LIST
:
393 value_list
.n_values
= other_value
.value_list
.n_values
;
394 value_list
.list_value
= new COMPONENT_template
[value_list
.n_values
];
395 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
396 value_list
.list_value
[i
].copy_template(
397 other_value
.value_list
.list_value
[i
]);
400 TTCN_error("Copying an uninitialized/unsupported component reference "
403 set_selection(other_value
);
406 COMPONENT_template::COMPONENT_template()
411 COMPONENT_template::COMPONENT_template(template_sel other_value
)
412 : Base_Template(other_value
)
414 check_single_selection(other_value
);
417 COMPONENT_template::COMPONENT_template(component other_value
)
418 : Base_Template(SPECIFIC_VALUE
)
420 single_value
= other_value
;
423 COMPONENT_template::COMPONENT_template(const COMPONENT
& other_value
)
424 : Base_Template(SPECIFIC_VALUE
)
426 if (other_value
.component_value
== UNBOUND_COMPREF
)
427 TTCN_error("Creating a template from an unbound component reference.");
428 single_value
= other_value
.component_value
;
431 COMPONENT_template::COMPONENT_template(const OPTIONAL
<COMPONENT
>& other_value
)
433 switch (other_value
.get_selection()) {
434 case OPTIONAL_PRESENT
:
435 set_selection(SPECIFIC_VALUE
);
436 single_value
= (component
)(const COMPONENT
&)other_value
;
439 set_selection(OMIT_VALUE
);
442 TTCN_error("Creating a component reference template from an unbound "
447 COMPONENT_template::COMPONENT_template(const COMPONENT_template
& other_value
)
450 copy_template(other_value
);
453 COMPONENT_template::~COMPONENT_template()
458 COMPONENT_template
& COMPONENT_template::operator=(template_sel other_value
)
460 check_single_selection(other_value
);
462 set_selection(other_value
);
466 COMPONENT_template
& COMPONENT_template::operator=(component other_value
)
469 set_selection(SPECIFIC_VALUE
);
470 single_value
= other_value
;
474 COMPONENT_template
& COMPONENT_template::operator=(const COMPONENT
& other_value
)
476 if (other_value
.component_value
== UNBOUND_COMPREF
)
477 TTCN_error("Assignment of an unbound component reference to a "
479 return *this = other_value
.component_value
;
482 COMPONENT_template
& COMPONENT_template::operator=
483 (const OPTIONAL
<COMPONENT
>& other_value
)
486 switch (other_value
.get_selection()) {
487 case OPTIONAL_PRESENT
:
488 set_selection(SPECIFIC_VALUE
);
489 single_value
= (component
)(const COMPONENT
&)other_value
;
492 set_selection(OMIT_VALUE
);
495 TTCN_error("Assignment of an unbound optional field to a component "
496 "reference template.");
501 COMPONENT_template
& COMPONENT_template::operator=
502 (const COMPONENT_template
& other_value
)
504 if (&other_value
!= this) {
506 copy_template(other_value
);
511 boolean
COMPONENT_template::match(component other_value
) const
513 switch (template_selection
) {
515 return single_value
== other_value
;
522 case COMPLEMENTED_LIST
:
523 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
524 if (value_list
.list_value
[i
].match(other_value
))
525 return template_selection
== VALUE_LIST
;
526 return template_selection
== COMPLEMENTED_LIST
;
528 TTCN_error("Matching an uninitialized/unsupported component reference "
534 boolean
COMPONENT_template::match(const COMPONENT
& other_value
) const
536 if (other_value
.component_value
== UNBOUND_COMPREF
)
537 TTCN_error("Matching an unbound component reference with a template.");
538 return match(other_value
.component_value
);
541 component
COMPONENT_template::valueof() const
543 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
544 TTCN_error("Performing a valueof or send operation on a non-specific "
545 "component reference template.");
549 void COMPONENT_template::set_type(template_sel template_type
,
550 unsigned int list_length
)
552 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
553 TTCN_error("Setting an invalid list type for a component reference "
556 set_selection(template_type
);
557 value_list
.n_values
= list_length
;
558 value_list
.list_value
= new COMPONENT_template
[list_length
];
561 COMPONENT_template
& COMPONENT_template::list_item(unsigned int list_index
)
563 if (template_selection
!= VALUE_LIST
&&
564 template_selection
!= COMPLEMENTED_LIST
)
565 TTCN_error("Accessing a list element of a non-list component "
566 "reference template.");
567 if (list_index
>= value_list
.n_values
)
568 TTCN_error("Index overflow in a component reference value list "
570 return value_list
.list_value
[list_index
];
573 void COMPONENT_template::log() const
575 switch (template_selection
) {
577 switch (single_value
) {
579 TTCN_Logger::log_event_str("null");
582 TTCN_Logger::log_event_str("mtc");
585 TTCN_Logger::log_event_str("system");
588 TTCN_Logger::log_event("%d", single_value
);
592 case COMPLEMENTED_LIST
:
593 TTCN_Logger::log_event_str("complement ");
596 TTCN_Logger::log_char('(');
597 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
598 if (i
> 0) TTCN_Logger::log_event_str(", ");
599 value_list
.list_value
[i
].log();
601 TTCN_Logger::log_char(')');
610 void COMPONENT_template::log_match(const COMPONENT
& match_value
) const
612 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
613 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
614 TTCN_Logger::print_logmatch_buffer();
615 TTCN_Logger::log_event_str(" := ");
618 TTCN_Logger::log_event_str(" with ");
620 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
621 else TTCN_Logger::log_event_str(" unmatched");
624 void COMPONENT_template::set_param(Module_Param
& param
) {
625 param
.basic_check(Module_Param::BC_TEMPLATE
, "component reference (integer or null) template");
626 switch (param
.get_type()) {
627 case Module_Param::MP_Omit
:
630 case Module_Param::MP_Any
:
633 case Module_Param::MP_AnyOrNone
:
636 case Module_Param::MP_List_Template
:
637 case Module_Param::MP_ComplementList_Template
:
638 set_type(param
.get_type()==Module_Param::MP_List_Template
? VALUE_LIST
: COMPLEMENTED_LIST
, param
.get_size());
639 for (size_t i
=0; i
<param
.get_size(); i
++) {
640 list_item(i
).set_param(*param
.get_elem(i
));
643 case Module_Param::MP_Integer
:
644 *this = (component
)param
.get_integer()->get_val();
646 case Module_Param::MP_Ttcn_Null
:
647 *this = NULL_COMPREF
;
649 case Module_Param::MP_Ttcn_mtc
:
652 case Module_Param::MP_Ttcn_system
:
653 *this = SYSTEM_COMPREF
;
656 param
.type_error("component reference (integer or null) template");
658 is_ifpresent
= param
.get_ifpresent();
661 void COMPONENT_template::encode_text(Text_Buf
& text_buf
) const
663 encode_text_base(text_buf
);
664 switch (template_selection
) {
670 text_buf
.push_int(single_value
);
672 case COMPLEMENTED_LIST
:
674 text_buf
.push_int(value_list
.n_values
);
675 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
676 value_list
.list_value
[i
].encode_text(text_buf
);
679 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
680 "component reference template.");
684 void COMPONENT_template::decode_text(Text_Buf
& text_buf
)
687 decode_text_base(text_buf
);
688 switch (template_selection
) {
694 single_value
= (component
)text_buf
.pull_int().get_val();
696 case COMPLEMENTED_LIST
:
698 value_list
.n_values
= text_buf
.pull_int().get_val();
699 value_list
.list_value
= new COMPONENT_template
[value_list
.n_values
];
700 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
701 value_list
.list_value
[i
].decode_text(text_buf
);
704 TTCN_error("Text decoder: An unknown/unsupported selection was "
705 "received for a component reference template.");
709 boolean
COMPONENT_template::is_present() const
711 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
712 return !match_omit();
715 boolean
COMPONENT_template::match_omit() const
717 if (is_ifpresent
) return TRUE
;
718 switch (template_selection
) {
723 case COMPLEMENTED_LIST
:
724 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
725 if (value_list
.list_value
[i
].match_omit())
726 return template_selection
==VALUE_LIST
;
727 return template_selection
==COMPLEMENTED_LIST
;
734 #ifndef TITAN_RUNTIME_2
735 void COMPONENT_template::check_restriction(template_res t_res
, const char* t_name
) const
737 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
738 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
740 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
743 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
744 template_selection
==SPECIFIC_VALUE
)) return;
747 if (!match_omit()) return;
752 TTCN_error("Restriction `%s' on template of type %s violated.",
753 get_res_name(t_res
), t_name
? t_name
: "component reference");
757 const COMPONENT_template
any_compref_value(ANY_VALUE
);
758 const COMPONENT_template
& any_compref
= any_compref_value
;