1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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 ///////////////////////////////////////////////////////////////////////////////
12 #include "Module_list.hh"
17 #include "Param_Types.hh"
18 #include "Basetype.hh"
21 #include "../common/ModuleVersion.hh"
23 #include "../common/usage_stats.hh"
26 #include "../common/dbgnew.hh"
32 TTCN_Module
*Module_List::list_head
= NULL
, *Module_List::list_tail
= NULL
;
36 void Module_List::add_module(TTCN_Module
*module_ptr
)
38 if (module_ptr
->list_next
== NULL
&& module_ptr
!= list_tail
) {
39 TTCN_Module
*list_iter
= list_head
;
40 while (list_iter
!= NULL
) {
41 if (strcmp(list_iter
->module_name
, module_ptr
->module_name
) > 0)
43 list_iter
= list_iter
->list_next
;
45 if (list_iter
!= NULL
) {
46 // inserting before list_iter
47 module_ptr
->list_prev
= list_iter
->list_prev
;
48 if (list_iter
->list_prev
!= NULL
)
49 list_iter
->list_prev
->list_next
= module_ptr
;
50 list_iter
->list_prev
= module_ptr
;
52 // inserting at the end of list
53 module_ptr
->list_prev
= list_tail
;
54 if (list_tail
!= NULL
) list_tail
->list_next
= module_ptr
;
55 list_tail
= module_ptr
;
57 module_ptr
->list_next
= list_iter
;
58 if (list_iter
== list_head
) list_head
= module_ptr
;
62 void Module_List::remove_module(TTCN_Module
*module_ptr
)
64 if (module_ptr
->list_prev
== NULL
) list_head
= module_ptr
->list_next
;
65 else module_ptr
->list_prev
->list_next
= module_ptr
->list_next
;
66 if (module_ptr
->list_next
== NULL
) list_tail
= module_ptr
->list_prev
;
67 else module_ptr
->list_next
->list_prev
= module_ptr
->list_prev
;
69 module_ptr
->list_prev
= NULL
;
70 module_ptr
->list_next
= NULL
;
73 TTCN_Module
*Module_List::lookup_module(const char *module_name
)
75 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
76 list_iter
= list_iter
->list_next
)
77 if (!strcmp(list_iter
->module_name
, module_name
)) return list_iter
;
81 TTCN_Module
*Module_List::single_control_part()
83 TTCN_Module
*retval
= 0;
84 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
85 list_iter
= list_iter
->list_next
)
86 if (list_iter
->control_func
!= 0) {
87 if (retval
!= 0) return 0; // more than one control part => fail
88 else retval
= list_iter
;
94 void Module_List::pre_init_modules()
96 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
97 list_iter
= list_iter
->list_next
) list_iter
->pre_init_module();
100 void Module_List::post_init_modules()
102 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
103 list_iter
= list_iter
->list_next
) list_iter
->post_init_called
= FALSE
;
104 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
105 list_iter
= list_iter
->list_next
) list_iter
->post_init_module();
108 void Module_List::start_function(const char *module_name
,
109 const char *function_name
, Text_Buf
& function_arguments
)
111 TTCN_Module
*module_ptr
= lookup_module(module_name
);
112 if (module_ptr
== NULL
) {
113 // the START message must be dropped here
114 function_arguments
.cut_message();
115 TTCN_error("Internal error: Module %s does not exist.", module_name
);
116 } else if (module_ptr
->start_func
== NULL
) {
117 // the START message must be dropped here
118 function_arguments
.cut_message();
119 TTCN_error("Internal error: Module %s does not have startable "
120 "functions.", module_name
);
121 } else if (!module_ptr
->start_func(function_name
, function_arguments
)) {
122 // the START message must be dropped here
123 function_arguments
.cut_message();
124 TTCN_error("Internal error: Startable function %s does not exist in "
125 "module %s.", function_name
, module_name
);
129 void Module_List::initialize_component(const char *module_name
,
130 const char *component_type
, boolean init_base_comps
)
132 TTCN_Module
*module_ptr
= lookup_module(module_name
);
133 if (module_ptr
== NULL
)
134 TTCN_error("Internal error: Module %s does not exist.", module_name
);
135 else if (module_ptr
->initialize_component_func
== NULL
)
136 TTCN_error("Internal error: Module %s does not have component types.",
138 else if (!module_ptr
->initialize_component_func(component_type
,
140 TTCN_error("Internal error: Component type %s does not exist in "
141 "module %s.", component_type
, module_name
);
144 void Module_List::set_param(Module_Param
& param
)
146 // The first segment in the parameter name can either be the module name,
147 // or the module parameter name - both must be checked
148 const char* const first_name
= param
.get_id()->get_current_name();
149 const char* second_name
= NULL
;
150 boolean param_found
= FALSE
;
152 // Check if the first name segment is an existing module name
153 TTCN_Module
*module_ptr
= lookup_module(first_name
);
154 if (module_ptr
!= NULL
&& module_ptr
->set_param_func
!= NULL
&& param
.get_id()->next_name()) {
155 param_found
= module_ptr
->set_param_func(param
);
157 second_name
= param
.get_id()->get_current_name(); // for error messages
161 // If not found, check if the first name segment was the module parameter name
162 // (even if it matched a module name)
164 param
.get_id()->next_name(-1); // set the position back to the first segment
165 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
166 list_iter
= list_iter
->list_next
) {
167 if (list_iter
->set_param_func
!= NULL
&&
168 list_iter
->set_param_func(param
)) {
174 // Still not found -> error
176 if (module_ptr
== NULL
) {
177 param
.error("Module parameter cannot be set, because module `%s' does not exist, "
178 "and no parameter with name `%s' exists in any module.",
179 first_name
, first_name
);
180 } else if (module_ptr
->set_param_func
== NULL
) {
181 param
.error("Module parameter cannot be set, because module `%s' does not have "
182 "parameters, and no parameter with name `%s' exists in other modules.",
183 first_name
, first_name
);
185 param
.error("Module parameter cannot be set, because no parameter with name `%s' "
186 "exists in module `%s', and no parameter with name `%s' exists in any module.",
187 second_name
, first_name
, first_name
);
192 Module_Param
* Module_List::get_param(Module_Param_Name
& param_name
)
194 // The first segment in the parameter name can either be the module name,
195 // or the module parameter name - both must be checked
196 const char* const first_name
= param_name
.get_current_name();
197 const char* second_name
= NULL
;
198 Module_Param
* param
= NULL
;
200 // Check if the first name segment is an existing module name
201 TTCN_Module
*module_ptr
= lookup_module(first_name
);
202 if (module_ptr
!= NULL
&& module_ptr
->get_param_func
!= NULL
&& param_name
.next_name()) {
203 param
= module_ptr
->get_param_func(param_name
);
205 second_name
= param_name
.get_current_name(); // for error messages
209 // If not found, check if the first name segment was the module parameter name
210 // (even if it matched a module name)
212 param_name
.next_name(-1); // set the position back to the first segment
213 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
214 list_iter
= list_iter
->list_next
) {
215 if (list_iter
->get_param_func
!= NULL
) {
216 param
= list_iter
->get_param_func(param_name
);
224 // Still not found -> error
226 if (module_ptr
== NULL
) {
227 TTCN_error("Referenced module parameter cannot be found. Module `%s' does not exist, "
228 "and no parameter with name `%s' exists in any module.",
229 first_name
, first_name
);
230 } else if (module_ptr
->get_param_func
== NULL
) {
231 TTCN_error("Referenced module parameter cannot be found. Module `%s' does not have "
232 "parameters, and no parameter with name `%s' exists in other modules.",
233 first_name
, first_name
);
235 TTCN_error("Referenced module parameter cannot be found. No parameter with name `%s' "
236 "exists in module `%s', and no parameter with name `%s' exists in any module.",
237 second_name
, first_name
, first_name
);
240 else if (param
->get_type() == Module_Param::MP_Unbound
) {
242 TTCN_error("Referenced module parameter '%s' is unbound.", param_name
.get_str());
248 void Module_List::log_param()
250 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
251 list_iter
= list_iter
->list_next
) {
252 if (list_iter
->log_param_func
!= NULL
) {
253 TTCN_Logger::begin_event(TTCN_Logger::EXECUTOR_CONFIGDATA
);
254 TTCN_Logger::log_event("Module %s has the following parameters: "
255 "{ ", list_iter
->module_name
);
256 list_iter
->log_param_func();
257 TTCN_Logger::log_event_str(" }");
258 TTCN_Logger::end_event();
263 void Module_List::execute_control(const char *module_name
)
265 TTCN_Module
*module_ptr
= lookup_module(module_name
);
266 if (module_ptr
!= NULL
) {
267 if (module_ptr
->control_func
!= NULL
) {
269 module_ptr
->control_func();
270 } catch (const TC_Error
& tc_error
) {
271 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
272 "Unrecoverable error in control part of module %s. Execution aborted.",
274 } catch (const TC_End
& tc_end
) {
275 TTCN_Logger::log(TTCN_Logger::FUNCTION_UNQUALIFIED
,
276 "Control part of module %s was stopped.", module_name
);
278 } else TTCN_error("Module %s does not have control part.", module_name
);
279 } else TTCN_error("Module %s does not exist.", module_name
);
282 void Module_List::execute_testcase(const char *module_name
,
283 const char *testcase_name
)
285 TTCN_Module
*module_ptr
= lookup_module(module_name
);
286 if (module_ptr
!= NULL
) module_ptr
->execute_testcase(testcase_name
);
287 else TTCN_error("Module %s does not exist.", module_name
);
290 void Module_List::execute_all_testcases(const char *module_name
)
292 TTCN_Module
*module_ptr
= lookup_module(module_name
);
293 if (module_ptr
!= NULL
) module_ptr
->execute_all_testcases();
294 else TTCN_error("Module %s does not exist.", module_name
);
297 void Module_List::print_version()
300 "Module name Language Compilation time MD5 checksum "
302 "-------------------------------------------------------------------"
303 "--------------------\n", stderr
);
304 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
305 list_iter
= list_iter
->list_next
) list_iter
->print_version();
306 fputs("-------------------------------------------------------------------"
307 "--------------------\n", stderr
);
310 void Module_List::send_versions() {
312 std::set
<ModuleVersion
> versions
;
313 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
314 list_iter
= list_iter
->list_next
) {
315 ModuleVersion
* version
= list_iter
->get_version();
316 if (version
->hasProductNumber()) {
317 versions
.insert(*version
);
322 std::stringstream stream
;
324 for (std::set
<ModuleVersion
>::iterator it
= versions
.begin(); it
!= versions
.end(); ++it
) {
325 if (it
== versions
.begin()) {
326 stream
<< "&products=" << it
->toString();
328 stream
<< "," << it
->toString();
332 HttpSender
* sender
= new HttpSender
;
333 UsageData::getInstance().sendDataThreaded(stream
.str().c_str(), sender
);
338 void Module_List::list_testcases()
340 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
341 list_iter
= list_iter
->list_next
) list_iter
->list_testcases();
344 void Module_List::push_version(Text_Buf
& text_buf
)
347 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
348 list_iter
= list_iter
->list_next
) n_modules
++;
349 text_buf
.push_int(n_modules
);
350 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
351 list_iter
= list_iter
->list_next
) {
352 text_buf
.push_string(list_iter
->module_name
);
353 if (list_iter
->md5_checksum
!= NULL
) {
354 text_buf
.push_int(16);
355 text_buf
.push_raw(16, list_iter
->md5_checksum
);
356 } else text_buf
.push_int((RInt
)0);
360 void Module_List::encode_function(Text_Buf
& text_buf
,
361 genericfunc_t function_address
)
363 if (function_address
== NULL
)
364 TTCN_error("Text encoder: Encoding an unbound function reference.");
365 else if (function_address
== fat_null
) text_buf
.push_string("");
367 const char *module_name
, *function_name
;
368 if (lookup_function_by_address(function_address
, module_name
,
370 text_buf
.push_string(module_name
);
371 text_buf
.push_string(function_name
);
372 } else TTCN_error("Text encoder: Encoding function reference %p, "
373 "which does not point to a valid function.",
374 (void*)(unsigned long)function_address
);
378 void Module_List::decode_function(Text_Buf
& text_buf
,
379 genericfunc_t
*function_addr_ptr
)
381 char *module_name
= text_buf
.pull_string();
382 if (module_name
[0] != '\0') {
383 TTCN_Module
* module_ptr
= lookup_module(module_name
);
384 if (module_ptr
== NULL
) {
386 TTCN_error("Text decoder: Module %s does not exist when trying "
387 "to decode a function reference.", module_name
);
389 // to prevent from memory leaks
390 delete [] module_name
;
394 char *function_name
= text_buf
.pull_string();
395 genericfunc_t function_address
=
396 module_ptr
->get_function_address_by_name(function_name
);
397 if (function_address
!= NULL
) *function_addr_ptr
= function_address
;
400 TTCN_error("Text decoder: Reference to non-existent function "
401 "%s.%s was received.", module_name
, function_name
);
403 // to prevent from memory leaks
404 delete [] module_name
;
405 delete [] function_name
;
409 delete [] function_name
;
410 } else *function_addr_ptr
= fat_null
;
411 delete [] module_name
;
414 void Module_List::log_function(genericfunc_t function_address
)
416 if (function_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
417 else if (function_address
== fat_null
) TTCN_Logger::log_event_str("null");
419 const char *module_name
, *function_name
;
420 if (lookup_function_by_address(function_address
, module_name
,
421 function_name
)) TTCN_Logger::log_event("refers(%s.%s)",
422 module_name
, function_name
);
423 else TTCN_Logger::log_event("<invalid function reference: %p>",
424 (void*)(unsigned long)function_address
);
428 void Module_List::encode_altstep(Text_Buf
& text_buf
,
429 genericfunc_t altstep_address
)
431 if (altstep_address
== NULL
)
432 TTCN_error("Text encoder: Encoding an unbound altstep reference.");
433 else if (altstep_address
== fat_null
) text_buf
.push_string("");
435 const char *module_name
, *altstep_name
;
436 if (lookup_altstep_by_address(altstep_address
, module_name
,
438 text_buf
.push_string(module_name
);
439 text_buf
.push_string(altstep_name
);
440 } else TTCN_error("Text encoder: Encoding altstep reference %p, "
441 "which does not point to a valid altstep.",
442 (void*)(unsigned long)altstep_address
);
446 void Module_List::decode_altstep(Text_Buf
& text_buf
,
447 genericfunc_t
*altstep_addr_ptr
)
449 char *module_name
= text_buf
.pull_string();
450 if (module_name
[0] != '\0') {
451 TTCN_Module
* module_ptr
= lookup_module(module_name
);
452 if (module_ptr
== NULL
) {
454 TTCN_error("Text decoder: Module %s does not exist when trying "
455 "to decode an altstep reference.", module_name
);
457 // to prevent from memory leaks
458 delete [] module_name
;
462 char *altstep_name
= text_buf
.pull_string();
463 genericfunc_t altstep_address
=
464 module_ptr
->get_altstep_address_by_name(altstep_name
);
465 if (altstep_address
!= NULL
) *altstep_addr_ptr
= altstep_address
;
468 TTCN_error("Text decoder: Reference to non-existent altstep "
469 "%s.%s was received.", module_name
, altstep_name
);
471 // to prevent from memory leaks
472 delete [] module_name
;
473 delete [] altstep_name
;
477 delete [] altstep_name
;
478 } else *altstep_addr_ptr
= fat_null
;
479 delete [] module_name
;
482 void Module_List::log_altstep(genericfunc_t altstep_address
)
484 if (altstep_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
485 else if (altstep_address
== fat_null
) TTCN_Logger::log_event_str("null");
487 const char *module_name
, *altstep_name
;
488 if (lookup_altstep_by_address(altstep_address
, module_name
,
489 altstep_name
)) TTCN_Logger::log_event("refers(%s.%s)",
490 module_name
, altstep_name
);
491 else TTCN_Logger::log_event("<invalid altstep reference: %p>",
492 (void*)(unsigned long)altstep_address
);
496 // called by testcase_name::encode_text in the generated code
497 void Module_List::encode_testcase(Text_Buf
& text_buf
,
498 genericfunc_t testcase_address
)
500 if (testcase_address
== NULL
)
501 TTCN_error("Text encoder: Encoding an unbound testcase reference.");
502 else if (testcase_address
== fat_null
) text_buf
.push_string("");
504 const char *module_name
, *testcase_name
;
505 if (lookup_testcase_by_address(testcase_address
, module_name
,
507 text_buf
.push_string(module_name
);
508 text_buf
.push_string(testcase_name
);
509 } else TTCN_error("Text encoder: Encoding testcase reference %p, "
510 "which does not point to a valid testcase.",
511 (void*)(unsigned long)testcase_address
);
515 // called by testcase_name::decode_text in the generated code
516 void Module_List::decode_testcase(Text_Buf
& text_buf
,
517 genericfunc_t
*testcase_addr_ptr
)
519 char *module_name
= text_buf
.pull_string();
520 if (module_name
[0] != '\0') {
521 TTCN_Module
* module_ptr
= lookup_module(module_name
);
522 if (module_ptr
== NULL
) {
524 TTCN_error("Text decoder: Module %s does not exist when trying "
525 "to decode a testcase reference.", module_name
);
527 // to prevent from memory leaks
528 delete [] module_name
;
532 char *testcase_name
= text_buf
.pull_string();
533 genericfunc_t testcase_address
=
534 module_ptr
->get_testcase_address_by_name(testcase_name
);
535 if (testcase_address
!= NULL
) *testcase_addr_ptr
= testcase_address
;
538 TTCN_error("Text decoder: Reference to non-existent testcase "
539 "%s.%s was received.", module_name
, testcase_name
);
541 // to prevent from memory leaks
542 delete [] module_name
;
543 delete [] testcase_name
;
547 delete [] testcase_name
;
548 } else *testcase_addr_ptr
= fat_null
;
549 delete [] module_name
;
552 void Module_List::log_testcase(genericfunc_t testcase_address
)
554 if (testcase_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
555 else if (testcase_address
== fat_null
) TTCN_Logger::log_event_str("null");
557 const char *module_name
, *testcase_name
;
558 if (lookup_testcase_by_address(testcase_address
, module_name
,
559 testcase_name
)) TTCN_Logger::log_event("refers(%s.%s)",
560 module_name
, testcase_name
);
561 else TTCN_Logger::log_event("<invalid testcase reference: %p>",
562 (void*)(unsigned long)testcase_address
);
566 genericfunc_t
Module_List::get_fat_null()
571 genericfunc_t
Module_List::lookup_start_by_function_address(
572 genericfunc_t function_address
)
574 if (function_address
== NULL
) TTCN_error("Performing a start test "
575 "component operation with an unbound function reference.");
576 else if (function_address
== fat_null
) TTCN_error("Start test component "
577 "operation cannot be performed with a null function reference.");
578 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
579 list_iter
= list_iter
->list_next
) {
580 genericfunc_t function_start
=
581 list_iter
->get_function_start_by_address(function_address
);
582 if (function_start
!= NULL
) return function_start
;
584 TTCN_error("Function reference %p in start test component operation does "
585 "not point to a valid function.",
586 (void*)(unsigned long)function_address
);
591 genericfunc_t
Module_List::lookup_standalone_address_by_altstep_address(
592 genericfunc_t altstep_address
)
594 if (altstep_address
== NULL
) TTCN_error("Performing an invoke operation "
595 "on an unbound altstep reference.");
596 else if (altstep_address
== fat_null
) TTCN_error("Invoke operation "
597 "cannot be performed on a null altstep reference.");
598 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
599 list_iter
= list_iter
->list_next
) {
600 genericfunc_t standalone_address
, activate_address
;
601 if (list_iter
->get_altstep_data_by_address(altstep_address
,
602 standalone_address
, activate_address
)) {
603 if (standalone_address
== NULL
)
604 TTCN_error("Internal error: Altstep reference %p cannot be "
605 "instantiated as a stand-alone alt statement.",
606 (void*)(unsigned long)altstep_address
);
607 return standalone_address
;
610 TTCN_error("Altstep reference %p in invoke operation does not point to a "
611 "valid altstep.", (void*)(unsigned long)altstep_address
);
616 genericfunc_t
Module_List::lookup_activate_address_by_altstep_address(
617 genericfunc_t altstep_address
)
619 if (altstep_address
== NULL
) TTCN_error("Performing an activate operation "
620 "on an unbound altstep reference.");
621 else if (altstep_address
== fat_null
) TTCN_error("Activate operation "
622 "cannot be performed on a null altstep reference.");
623 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
624 list_iter
= list_iter
->list_next
) {
625 genericfunc_t standalone_address
, activate_address
;
626 if (list_iter
->get_altstep_data_by_address(altstep_address
,
627 standalone_address
, activate_address
)) {
628 if (activate_address
== NULL
)
629 TTCN_error("Internal error: Altstep reference %p cannot be "
630 "activated as a default.",
631 (void*)(unsigned long)altstep_address
);
632 return activate_address
;
635 TTCN_error("Altstep reference %p in activate operation does not point to "
636 "a valid altstep.", (void*)(unsigned long)altstep_address
);
641 boolean
Module_List::lookup_function_by_address(genericfunc_t function_address
,
642 const char*& module_name
, const char*& function_name
)
644 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
645 list_iter
= list_iter
->list_next
) {
647 list_iter
->get_function_name_by_address(function_address
);
648 if (function_name
!= NULL
) {
649 module_name
= list_iter
->module_name
;
656 boolean
Module_List::lookup_altstep_by_address(genericfunc_t altstep_address
,
657 const char*& module_name
, const char*& altstep_name
)
659 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
660 list_iter
= list_iter
->list_next
) {
661 altstep_name
= list_iter
->get_altstep_name_by_address(altstep_address
);
662 if (altstep_name
!= NULL
) {
663 module_name
= list_iter
->module_name
;
670 boolean
Module_List::lookup_testcase_by_address(genericfunc_t testcase_address
,
671 const char*& module_name
, const char*& testcase_name
)
673 for(TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
674 list_iter
= list_iter
->list_next
) {
676 list_iter
->get_testcase_name_by_address(testcase_address
);
677 if (testcase_name
!= NULL
) {
678 module_name
= list_iter
->module_name
;
685 // ======================= TTCN_Module =======================
687 struct TTCN_Module::function_list_item
{
688 const char *function_name
;
689 genericfunc_t function_address
;
690 genericfunc_t start_address
;
691 function_list_item
*next_function
;
694 struct TTCN_Module::altstep_list_item
{
695 const char *altstep_name
;
696 genericfunc_t altstep_address
; //instance
697 genericfunc_t activate_address
;
698 genericfunc_t standalone_address
;
699 altstep_list_item
*next_altstep
;
702 struct TTCN_Module::testcase_list_item
{
703 const char *testcase_name
;
706 testcase_t testcase_function
;
707 genericfunc_t testcase_address
;
709 testcase_list_item
*next_testcase
;
712 /** Constructor for TTCN modules */
713 TTCN_Module::TTCN_Module(const char *par_module_name
,
714 const char *par_compilation_date
,
715 const char *par_compilation_time
,
716 const unsigned char *par_md5_checksum
,
717 init_func_t par_pre_init_func
,
718 const char* par_product_number
,
719 unsigned int par_suffix
,
720 unsigned int par_release
,
721 unsigned int par_patch
,
722 unsigned int par_build
,
723 const char* par_extra
,
724 size_t par_num_namespace
,
725 const namespace_t
*par_namespaces
,
726 init_func_t par_post_init_func
,
727 set_param_func_t par_set_param_func
,
728 get_param_func_t par_get_param_func
,
729 log_param_func_t par_log_param_func
,
730 initialize_component_func_t par_initialize_component_func
,
731 start_func_t par_start_func
,
732 control_func_t par_control_func
)
733 : list_prev(NULL
), list_next(NULL
)
734 , module_type(TTCN3_MODULE
)
735 , module_name(par_module_name
)
736 , compilation_date(par_compilation_date
)
737 , compilation_time(par_compilation_time
)
738 , md5_checksum(par_md5_checksum
)
739 , product_number(par_product_number
)
741 , release(par_release
)
745 , num_namespaces(par_num_namespace
)
746 , xer_namespaces(par_namespaces
)
747 , pre_init_func(par_pre_init_func
)
748 , post_init_func(par_post_init_func
)
749 , pre_init_called(FALSE
)
750 , post_init_called(FALSE
)
751 , set_param_func(par_set_param_func
)
752 , get_param_func(par_get_param_func
)
753 , log_param_func(par_log_param_func
)
754 , initialize_component_func(par_initialize_component_func
)
755 , start_func(par_start_func
)
756 , control_func(par_control_func
)
757 , function_head(NULL
)
758 , function_tail(NULL
)
761 , testcase_head(NULL
)
762 , testcase_tail(NULL
)
764 Module_List::add_module(this);
767 /** Constructor for ASN.1 modules */
768 TTCN_Module::TTCN_Module(const char *par_module_name
,
769 const char *par_compilation_date
,
770 const char *par_compilation_time
,
771 const unsigned char par_md5_checksum
[16],
772 init_func_t par_init_func
)
773 : list_prev(NULL
), list_next(NULL
)
774 , module_type(ASN1_MODULE
)
775 , module_name(par_module_name
)
776 , compilation_date(par_compilation_date
)
777 , compilation_time(par_compilation_time
)
778 , md5_checksum(par_md5_checksum
)
779 , product_number(NULL
)
786 , xer_namespaces(NULL
) // no EXER, no namespaces for ASN.1
787 , pre_init_func(par_init_func
)
788 , post_init_func(NULL
)
789 , pre_init_called(FALSE
)
790 , post_init_called(FALSE
)
791 , set_param_func(NULL
)
792 , get_param_func(NULL
)
793 , log_param_func(NULL
)
794 , initialize_component_func(NULL
)
797 , function_head(NULL
)
798 , function_tail(NULL
)
801 , testcase_head(NULL
)
802 , testcase_tail(NULL
)
804 Module_List::add_module(this);
807 /** Constructor for C++ modules (?) */
808 TTCN_Module::TTCN_Module(const char *par_module_name
,
809 const char *par_compilation_date
,
810 const char *par_compilation_time
,
811 init_func_t par_init_func
)
812 : list_prev(NULL
), list_next(NULL
)
813 , module_type(CPLUSPLUS_MODULE
)
814 , module_name(par_module_name
? par_module_name
: "<unknown>")
815 , compilation_date(par_compilation_date
? par_compilation_date
: "<unknown>")
816 , compilation_time(par_compilation_time
? par_compilation_time
: "<unknown>")
818 , product_number(NULL
)
825 , xer_namespaces(NULL
)
826 , pre_init_func(par_init_func
)
827 , post_init_func(NULL
)
828 , pre_init_called(FALSE
)
829 , post_init_called(FALSE
)
830 , set_param_func(NULL
)
831 , log_param_func(NULL
)
832 , initialize_component_func(NULL
)
835 , function_head(NULL
)
836 , function_tail(NULL
)
839 , testcase_head(NULL
)
840 , testcase_tail(NULL
)
842 Module_List::add_module(this);
845 TTCN_Module::~TTCN_Module()
847 Module_List::remove_module(this);
848 while (function_head
!= NULL
) {
849 function_list_item
*tmp_ptr
=function_head
->next_function
;
850 delete function_head
;
851 function_head
= tmp_ptr
;
853 while (altstep_head
!= NULL
) {
854 altstep_list_item
*tmp_ptr
=altstep_head
->next_altstep
;
856 altstep_head
= tmp_ptr
;
858 while (testcase_head
!= NULL
) {
859 testcase_list_item
*tmp_ptr
= testcase_head
->next_testcase
;
860 delete testcase_head
;
861 testcase_head
= tmp_ptr
;
865 void TTCN_Module::pre_init_module()
867 if (pre_init_called
) return;
868 pre_init_called
= TRUE
;
869 if (pre_init_func
== NULL
) return;
873 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
874 "An error occurred while initializing the constants of module %s.",
880 void TTCN_Module::post_init_module()
882 if (post_init_called
) return;
883 post_init_called
= TRUE
;
884 TTCN_Logger::log_module_init(module_name
);
885 if (post_init_func
!= NULL
) post_init_func();
886 TTCN_Logger::log_module_init(module_name
, true);
889 void TTCN_Module::add_function(const char *function_name
,
890 genericfunc_t function_address
, genericfunc_t start_address
)
892 function_list_item
*new_item
= new function_list_item
;
893 new_item
->function_name
= function_name
;
894 new_item
->function_address
= function_address
;
895 new_item
->start_address
= start_address
;
896 new_item
->next_function
= NULL
;
897 if(function_head
== NULL
) function_head
= new_item
;
898 else function_tail
->next_function
= new_item
;
899 function_tail
= new_item
;
902 void TTCN_Module::add_altstep(const char *altstep_name
,
903 genericfunc_t altstep_address
, genericfunc_t activate_address
,
904 genericfunc_t standalone_address
)
906 altstep_list_item
*new_item
= new altstep_list_item
;
907 new_item
->altstep_name
= altstep_name
;
908 new_item
->altstep_address
= altstep_address
;
909 new_item
->activate_address
= activate_address
;
910 new_item
->standalone_address
= standalone_address
;
911 new_item
->next_altstep
= NULL
;
912 if(altstep_head
== NULL
) altstep_head
= new_item
;
913 else altstep_tail
->next_altstep
= new_item
;
914 altstep_tail
= new_item
;
917 void TTCN_Module::add_testcase_nonpard(const char *testcase_name
,
918 testcase_t testcase_function
)
920 testcase_list_item
*new_item
= new testcase_list_item
;
921 new_item
->testcase_name
= testcase_name
;
922 new_item
->is_pard
= FALSE
;
923 new_item
->testcase_function
= testcase_function
;
924 new_item
->next_testcase
= NULL
;
925 if (testcase_head
== NULL
) testcase_head
= new_item
;
926 else testcase_tail
->next_testcase
= new_item
;
927 testcase_tail
= new_item
;
930 void TTCN_Module::add_testcase_pard(const char *testcase_name
,
931 genericfunc_t testcase_address
)
933 testcase_list_item
*new_item
= new testcase_list_item
;
934 new_item
->testcase_name
= testcase_name
;
935 new_item
->is_pard
= TRUE
;
936 new_item
->testcase_address
= testcase_address
;
937 new_item
->next_testcase
= NULL
;
938 if(testcase_head
== NULL
) testcase_head
= new_item
;
939 else testcase_tail
->next_testcase
= new_item
;
940 testcase_tail
= new_item
;
943 void TTCN_Module::execute_testcase(const char *testcase_name
)
945 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
946 list_iter
= list_iter
->next_testcase
) {
947 if (!strcmp(list_iter
->testcase_name
, testcase_name
)) {
948 if (list_iter
->is_pard
) {
949 // Testcase has parameters. However, there might be a chance...
950 // Move to the next one (if any) and check that it has the same name.
951 list_iter
= list_iter
->next_testcase
;
952 if (list_iter
== NULL
953 || strcmp(list_iter
->testcase_name
, testcase_name
)) {
954 TTCN_error("Test case %s in module %s "
955 "cannot be executed individually (without control part) "
956 "because it has parameters.", testcase_name
, module_name
);
957 continue; // not reached
959 // else it has the same name, fall through
962 list_iter
->testcase_function(FALSE
, 0.0);
966 TTCN_error("Test case %s does not exist in module %s.", testcase_name
,
970 void TTCN_Module::execute_all_testcases()
972 boolean found
= FALSE
;
973 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
974 list_iter
= list_iter
->next_testcase
) {
975 if (!list_iter
->is_pard
) {
976 list_iter
->testcase_function(FALSE
, 0.0);
981 if (testcase_head
!= NULL
) TTCN_warning("Module %s does not contain "
982 "non-parameterized test cases, which can be executed individually "
983 "without control part.", module_name
);
984 else TTCN_warning("Module %s does not contain test cases.",
989 const char *TTCN_Module::get_function_name_by_address(
990 genericfunc_t function_address
)
992 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
993 list_iter
= list_iter
->next_function
)
994 if (list_iter
->function_address
== function_address
)
995 return list_iter
->function_name
;
999 genericfunc_t
TTCN_Module::get_function_address_by_name(const char *func_name
)
1001 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
1002 list_iter
= list_iter
->next_function
)
1003 if (!strcmp(list_iter
->function_name
, func_name
))
1004 return list_iter
->function_address
;
1008 genericfunc_t
TTCN_Module::get_function_start_by_address(
1009 genericfunc_t function_address
)
1011 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
1012 list_iter
= list_iter
->next_function
) {
1013 if (list_iter
->function_address
== function_address
) {
1014 if (list_iter
->start_address
!= NULL
)
1015 return list_iter
->start_address
;
1016 else TTCN_error("Function %s.%s cannot be started on a parallel "
1017 "test component.", module_name
, list_iter
->function_name
);
1023 const char *TTCN_Module::get_altstep_name_by_address(
1024 genericfunc_t altstep_address
)
1026 for(altstep_list_item
*list_iter
= altstep_head
; list_iter
!= NULL
;
1027 list_iter
= list_iter
->next_altstep
) {
1028 if (list_iter
->altstep_address
== altstep_address
)
1029 return list_iter
->altstep_name
;
1034 genericfunc_t
TTCN_Module::get_altstep_address_by_name(const char* altstep_name
)
1036 for(altstep_list_item
*list_iter
= altstep_head
; list_iter
!= NULL
;
1037 list_iter
= list_iter
->next_altstep
) {
1038 if (!strcmp(list_iter
->altstep_name
, altstep_name
))
1039 return list_iter
->altstep_address
;
1044 boolean
TTCN_Module::get_altstep_data_by_address(genericfunc_t altstep_address
,
1045 genericfunc_t
& standalone_address
, genericfunc_t
& activate_address
)
1047 for(altstep_list_item
* list_iter
= altstep_head
; list_iter
!= NULL
;
1048 list_iter
= list_iter
->next_altstep
) {
1049 if (list_iter
->altstep_address
== altstep_address
) {
1050 standalone_address
= list_iter
->standalone_address
;
1051 activate_address
= list_iter
->activate_address
;
1058 const char *TTCN_Module::get_testcase_name_by_address(
1059 genericfunc_t testcase_address
)
1061 for(testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1062 list_iter
= list_iter
->next_testcase
) {
1063 if (list_iter
->is_pard
) {
1064 if (list_iter
->testcase_address
== testcase_address
)
1065 return list_iter
->testcase_name
;
1067 if ((genericfunc_t
)list_iter
->testcase_function
== testcase_address
)
1068 return list_iter
->testcase_name
;
1074 genericfunc_t
TTCN_Module::get_testcase_address_by_name(const char *testcase_name
)
1076 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1077 list_iter
= list_iter
->next_testcase
) {
1078 if (!strcmp(list_iter
->testcase_name
, testcase_name
)) {
1079 if (!list_iter
->is_pard
) return list_iter
->testcase_address
;
1080 else return (genericfunc_t
)list_iter
->testcase_function
;
1086 ModuleVersion
* TTCN_Module::get_version() const {
1087 return new ModuleVersion(product_number
, suffix
, release
, patch
, build
, extra
);
1090 void TTCN_Module::print_version()
1092 const char *type_str
;
1093 switch (module_type
) {
1095 type_str
= "TTCN-3";
1100 case CPLUSPLUS_MODULE
:
1107 fprintf(stderr
, "%-18s %-6s ", module_name
, type_str
);
1108 if (compilation_date
!= NULL
&& compilation_time
!= NULL
) {
1109 fprintf(stderr
, "%s %s", compilation_date
, compilation_time
);
1111 fputs("<unknown> ", stderr
);
1113 if (md5_checksum
!= NULL
) {
1115 for (int i
= 0; i
< 16; i
++) fprintf(stderr
, "%02x", md5_checksum
[i
]);
1117 // else it's likely not a TTCN module, so no version info
1119 putc(' ', stderr
); // separator for the version number
1120 if (product_number
!= NULL
) {
1121 fprintf(stderr
, "%s", product_number
);
1123 fprintf(stderr
, "/%d", suffix
);
1127 // release can be between 0 and 999999 inclusive
1128 // patch can go from 0 to 26 (English alphabet) - 6 (IOPQRW forbidden)
1129 // build can be between 0 and 99 inclusive
1130 if (release
<= 999999 && patch
<= ('Z'-'A'-6) && build
<= 99) {
1131 char *build_str
= buildstr(build
);
1132 if (build_str
== 0) TTCN_error("TTCN_Module::print_version()");
1133 if (extra
!= NULL
) {
1134 build_str
= mputprintf(build_str
, "%s", extra
);
1136 fprintf(stderr
, "R%u%c%-4s", release
, eri(patch
), build_str
);
1142 void TTCN_Module::list_testcases()
1144 if (control_func
!= NULL
) printf("%s.control\n", module_name
);
1145 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1146 list_iter
= list_iter
->next_testcase
)
1147 if(!list_iter
->is_pard
)
1148 printf("%s.%s\n", module_name
, list_iter
->testcase_name
);
1151 const namespace_t
*TTCN_Module::get_ns(size_t p_index
) const
1153 if (p_index
== (size_t)-1) return NULL
;
1154 if (p_index
>= num_namespaces
) TTCN_error(
1155 "Index overflow for namespaces, %lu instead of %lu",
1156 (unsigned long)p_index
, (unsigned long)num_namespaces
);
1158 return xer_namespaces
+ p_index
;
1161 const namespace_t
*TTCN_Module::get_controlns() const
1163 if (xer_namespaces
==NULL
) {
1164 TTCN_error("No namespaces for module %s", module_name
);
1166 if (xer_namespaces
[num_namespaces
].px
== NULL
1167 ||xer_namespaces
[num_namespaces
].px
[0] == '\0') {
1168 TTCN_error("No control namespace for module %s", module_name
);
1170 return xer_namespaces
+num_namespaces
;