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 ///////////////////////////////////////////////////////////////////////////////
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();
102 void Module_List::post_init_modules()
104 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
105 list_iter
= list_iter
->list_next
) list_iter
->post_init_called
= FALSE
;
106 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
107 list_iter
= list_iter
->list_next
) list_iter
->post_init_module();
110 void Module_List::start_function(const char *module_name
,
111 const char *function_name
, Text_Buf
& function_arguments
)
113 TTCN_Module
*module_ptr
= lookup_module(module_name
);
114 if (module_ptr
== NULL
) {
115 // the START message must be dropped here
116 function_arguments
.cut_message();
117 TTCN_error("Internal error: Module %s does not exist.", module_name
);
118 } else if (module_ptr
->start_func
== NULL
) {
119 // the START message must be dropped here
120 function_arguments
.cut_message();
121 TTCN_error("Internal error: Module %s does not have startable "
122 "functions.", module_name
);
123 } else if (!module_ptr
->start_func(function_name
, function_arguments
)) {
124 // the START message must be dropped here
125 function_arguments
.cut_message();
126 TTCN_error("Internal error: Startable function %s does not exist in "
127 "module %s.", function_name
, module_name
);
131 void Module_List::initialize_component(const char *module_name
,
132 const char *component_type
, boolean init_base_comps
)
134 TTCN_Module
*module_ptr
= lookup_module(module_name
);
135 if (module_ptr
== NULL
)
136 TTCN_error("Internal error: Module %s does not exist.", module_name
);
137 else if (module_ptr
->initialize_component_func
== NULL
)
138 TTCN_error("Internal error: Module %s does not have component types.",
140 else if (!module_ptr
->initialize_component_func(component_type
,
142 TTCN_error("Internal error: Component type %s does not exist in "
143 "module %s.", component_type
, module_name
);
146 void Module_List::set_param(Module_Param
& param
)
148 // The first segment in the parameter name can either be the module name,
149 // or the module parameter name - both must be checked
150 const char* const first_name
= param
.get_id()->get_current_name();
151 const char* second_name
= NULL
;
152 boolean param_found
= FALSE
;
154 // Check if the first name segment is an existing module name
155 TTCN_Module
*module_ptr
= lookup_module(first_name
);
156 if (module_ptr
!= NULL
&& module_ptr
->set_param_func
!= NULL
&& param
.get_id()->next_name()) {
157 param_found
= module_ptr
->set_param_func(param
);
159 second_name
= param
.get_id()->get_current_name(); // for error messages
163 // If not found, check if the first name segment was the module parameter name
164 // (even if it matched a module name)
166 param
.get_id()->next_name(-1); // set the position back to the first segment
167 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
168 list_iter
= list_iter
->list_next
) {
169 if (list_iter
->set_param_func
!= NULL
&&
170 list_iter
->set_param_func(param
)) {
176 // Still not found -> error
178 if (module_ptr
== NULL
) {
179 param
.error("Module parameter cannot be set, because module `%s' does not exist, "
180 "and no parameter with name `%s' exists in any module.",
181 first_name
, first_name
);
182 } else if (module_ptr
->set_param_func
== NULL
) {
183 param
.error("Module parameter cannot be set, because module `%s' does not have "
184 "parameters, and no parameter with name `%s' exists in other modules.",
185 first_name
, first_name
);
187 param
.error("Module parameter cannot be set, because no parameter with name `%s' "
188 "exists in module `%s', and no parameter with name `%s' exists in any module.",
189 second_name
, first_name
, first_name
);
194 void Module_List::log_param()
196 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
197 list_iter
= list_iter
->list_next
) {
198 if (list_iter
->log_param_func
!= NULL
) {
199 TTCN_Logger::begin_event(TTCN_Logger::EXECUTOR_CONFIGDATA
);
200 TTCN_Logger::log_event("Module %s has the following parameters: "
201 "{ ", list_iter
->module_name
);
202 list_iter
->log_param_func();
203 TTCN_Logger::log_event_str(" }");
204 TTCN_Logger::end_event();
209 void Module_List::execute_control(const char *module_name
)
211 TTCN_Module
*module_ptr
= lookup_module(module_name
);
212 if (module_ptr
!= NULL
) {
213 if (module_ptr
->control_func
!= NULL
) {
215 module_ptr
->control_func();
216 } catch (const TC_Error
& tc_error
) {
217 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
218 "Unrecoverable error in control part of module %s. Execution aborted.",
220 } catch (const TC_End
& tc_end
) {
221 TTCN_Logger::log(TTCN_Logger::FUNCTION_UNQUALIFIED
,
222 "Control part of module %s was stopped.", module_name
);
224 } else TTCN_error("Module %s does not have control part.", module_name
);
225 } else TTCN_error("Module %s does not exist.", module_name
);
228 void Module_List::execute_testcase(const char *module_name
,
229 const char *testcase_name
)
231 TTCN_Module
*module_ptr
= lookup_module(module_name
);
232 if (module_ptr
!= NULL
) module_ptr
->execute_testcase(testcase_name
);
233 else TTCN_error("Module %s does not exist.", module_name
);
236 void Module_List::execute_all_testcases(const char *module_name
)
238 TTCN_Module
*module_ptr
= lookup_module(module_name
);
239 if (module_ptr
!= NULL
) module_ptr
->execute_all_testcases();
240 else TTCN_error("Module %s does not exist.", module_name
);
243 void Module_List::print_version()
246 "Module name Language Compilation time MD5 checksum "
248 "-------------------------------------------------------------------"
249 "--------------------\n", stderr
);
250 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
251 list_iter
= list_iter
->list_next
) list_iter
->print_version();
252 fputs("-------------------------------------------------------------------"
253 "--------------------\n", stderr
);
256 void Module_List::send_versions() {
258 std::set
<ModuleVersion
> versions
;
259 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
260 list_iter
= list_iter
->list_next
) {
261 ModuleVersion
* version
= list_iter
->get_version();
262 if (version
->hasProductNumber()) {
263 versions
.insert(*version
);
268 std::stringstream stream
;
270 for (std::set
<ModuleVersion
>::iterator it
= versions
.begin(); it
!= versions
.end(); ++it
) {
271 if (it
== versions
.begin()) {
272 stream
<< "&products=" << it
->toString();
274 stream
<< "," << it
->toString();
278 HttpSender
* sender
= new HttpSender
;
279 UsageData::getInstance().sendDataThreaded(stream
.str().c_str(), sender
);
284 void Module_List::list_testcases()
286 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
287 list_iter
= list_iter
->list_next
) list_iter
->list_testcases();
290 void Module_List::push_version(Text_Buf
& text_buf
)
293 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
294 list_iter
= list_iter
->list_next
) n_modules
++;
295 text_buf
.push_int(n_modules
);
296 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
297 list_iter
= list_iter
->list_next
) {
298 text_buf
.push_string(list_iter
->module_name
);
299 if (list_iter
->md5_checksum
!= NULL
) {
300 text_buf
.push_int(16);
301 text_buf
.push_raw(16, list_iter
->md5_checksum
);
302 } else text_buf
.push_int((RInt
)0);
306 void Module_List::encode_function(Text_Buf
& text_buf
,
307 genericfunc_t function_address
)
309 if (function_address
== NULL
)
310 TTCN_error("Text encoder: Encoding an unbound function reference.");
311 else if (function_address
== fat_null
) text_buf
.push_string("");
313 const char *module_name
, *function_name
;
314 if (lookup_function_by_address(function_address
, module_name
,
316 text_buf
.push_string(module_name
);
317 text_buf
.push_string(function_name
);
318 } else TTCN_error("Text encoder: Encoding function reference %p, "
319 "which does not point to a valid function.",
320 (void*)(unsigned long)function_address
);
324 void Module_List::decode_function(Text_Buf
& text_buf
,
325 genericfunc_t
*function_addr_ptr
)
327 char *module_name
= text_buf
.pull_string();
328 if (module_name
[0] != '\0') {
329 TTCN_Module
* module_ptr
= lookup_module(module_name
);
330 if (module_ptr
== NULL
) {
332 TTCN_error("Text decoder: Module %s does not exist when trying "
333 "to decode a function reference.", module_name
);
335 // to prevent from memory leaks
336 delete [] module_name
;
340 char *function_name
= text_buf
.pull_string();
341 genericfunc_t function_address
=
342 module_ptr
->get_function_address_by_name(function_name
);
343 if (function_address
!= NULL
) *function_addr_ptr
= function_address
;
346 TTCN_error("Text decoder: Reference to non-existent function "
347 "%s.%s was received.", module_name
, function_name
);
349 // to prevent from memory leaks
350 delete [] module_name
;
351 delete [] function_name
;
355 delete [] function_name
;
356 } else *function_addr_ptr
= fat_null
;
357 delete [] module_name
;
360 void Module_List::log_function(genericfunc_t function_address
)
362 if (function_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
363 else if (function_address
== fat_null
) TTCN_Logger::log_event_str("null");
365 const char *module_name
, *function_name
;
366 if (lookup_function_by_address(function_address
, module_name
,
367 function_name
)) TTCN_Logger::log_event("refers(%s.%s)",
368 module_name
, function_name
);
369 else TTCN_Logger::log_event("<invalid function reference: %p>",
370 (void*)(unsigned long)function_address
);
374 void Module_List::encode_altstep(Text_Buf
& text_buf
,
375 genericfunc_t altstep_address
)
377 if (altstep_address
== NULL
)
378 TTCN_error("Text encoder: Encoding an unbound altstep reference.");
379 else if (altstep_address
== fat_null
) text_buf
.push_string("");
381 const char *module_name
, *altstep_name
;
382 if (lookup_altstep_by_address(altstep_address
, module_name
,
384 text_buf
.push_string(module_name
);
385 text_buf
.push_string(altstep_name
);
386 } else TTCN_error("Text encoder: Encoding altstep reference %p, "
387 "which does not point to a valid altstep.",
388 (void*)(unsigned long)altstep_address
);
392 void Module_List::decode_altstep(Text_Buf
& text_buf
,
393 genericfunc_t
*altstep_addr_ptr
)
395 char *module_name
= text_buf
.pull_string();
396 if (module_name
[0] != '\0') {
397 TTCN_Module
* module_ptr
= lookup_module(module_name
);
398 if (module_ptr
== NULL
) {
400 TTCN_error("Text decoder: Module %s does not exist when trying "
401 "to decode an altstep reference.", module_name
);
403 // to prevent from memory leaks
404 delete [] module_name
;
408 char *altstep_name
= text_buf
.pull_string();
409 genericfunc_t altstep_address
=
410 module_ptr
->get_altstep_address_by_name(altstep_name
);
411 if (altstep_address
!= NULL
) *altstep_addr_ptr
= altstep_address
;
414 TTCN_error("Text decoder: Reference to non-existent altstep "
415 "%s.%s was received.", module_name
, altstep_name
);
417 // to prevent from memory leaks
418 delete [] module_name
;
419 delete [] altstep_name
;
423 delete [] altstep_name
;
424 } else *altstep_addr_ptr
= fat_null
;
425 delete [] module_name
;
428 void Module_List::log_altstep(genericfunc_t altstep_address
)
430 if (altstep_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
431 else if (altstep_address
== fat_null
) TTCN_Logger::log_event_str("null");
433 const char *module_name
, *altstep_name
;
434 if (lookup_altstep_by_address(altstep_address
, module_name
,
435 altstep_name
)) TTCN_Logger::log_event("refers(%s.%s)",
436 module_name
, altstep_name
);
437 else TTCN_Logger::log_event("<invalid altstep reference: %p>",
438 (void*)(unsigned long)altstep_address
);
442 // called by testcase_name::encode_text in the generated code
443 void Module_List::encode_testcase(Text_Buf
& text_buf
,
444 genericfunc_t testcase_address
)
446 if (testcase_address
== NULL
)
447 TTCN_error("Text encoder: Encoding an unbound testcase reference.");
448 else if (testcase_address
== fat_null
) text_buf
.push_string("");
450 const char *module_name
, *testcase_name
;
451 if (lookup_testcase_by_address(testcase_address
, module_name
,
453 text_buf
.push_string(module_name
);
454 text_buf
.push_string(testcase_name
);
455 } else TTCN_error("Text encoder: Encoding testcase reference %p, "
456 "which does not point to a valid testcase.",
457 (void*)(unsigned long)testcase_address
);
461 // called by testcase_name::decode_text in the generated code
462 void Module_List::decode_testcase(Text_Buf
& text_buf
,
463 genericfunc_t
*testcase_addr_ptr
)
465 char *module_name
= text_buf
.pull_string();
466 if (module_name
[0] != '\0') {
467 TTCN_Module
* module_ptr
= lookup_module(module_name
);
468 if (module_ptr
== NULL
) {
470 TTCN_error("Text decoder: Module %s does not exist when trying "
471 "to decode a testcase reference.", module_name
);
473 // to prevent from memory leaks
474 delete [] module_name
;
478 char *testcase_name
= text_buf
.pull_string();
479 genericfunc_t testcase_address
=
480 module_ptr
->get_testcase_address_by_name(testcase_name
);
481 if (testcase_address
!= NULL
) *testcase_addr_ptr
= testcase_address
;
484 TTCN_error("Text decoder: Reference to non-existent testcase "
485 "%s.%s was received.", module_name
, testcase_name
);
487 // to prevent from memory leaks
488 delete [] module_name
;
489 delete [] testcase_name
;
493 delete [] testcase_name
;
494 } else *testcase_addr_ptr
= fat_null
;
495 delete [] module_name
;
498 void Module_List::log_testcase(genericfunc_t testcase_address
)
500 if (testcase_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
501 else if (testcase_address
== fat_null
) TTCN_Logger::log_event_str("null");
503 const char *module_name
, *testcase_name
;
504 if (lookup_testcase_by_address(testcase_address
, module_name
,
505 testcase_name
)) TTCN_Logger::log_event("refers(%s.%s)",
506 module_name
, testcase_name
);
507 else TTCN_Logger::log_event("<invalid testcase reference: %p>",
508 (void*)(unsigned long)testcase_address
);
512 genericfunc_t
Module_List::get_fat_null()
517 genericfunc_t
Module_List::lookup_start_by_function_address(
518 genericfunc_t function_address
)
520 if (function_address
== NULL
) TTCN_error("Performing a start test "
521 "component operation with an unbound function reference.");
522 else if (function_address
== fat_null
) TTCN_error("Start test component "
523 "operation cannot be performed with a null function reference.");
524 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
525 list_iter
= list_iter
->list_next
) {
526 genericfunc_t function_start
=
527 list_iter
->get_function_start_by_address(function_address
);
528 if (function_start
!= NULL
) return function_start
;
530 TTCN_error("Function reference %p in start test component operation does "
531 "not point to a valid function.",
532 (void*)(unsigned long)function_address
);
537 genericfunc_t
Module_List::lookup_standalone_address_by_altstep_address(
538 genericfunc_t altstep_address
)
540 if (altstep_address
== NULL
) TTCN_error("Performing an invoke operation "
541 "on an unbound altstep reference.");
542 else if (altstep_address
== fat_null
) TTCN_error("Invoke operation "
543 "cannot be performed on a null altstep reference.");
544 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
545 list_iter
= list_iter
->list_next
) {
546 genericfunc_t standalone_address
, activate_address
;
547 if (list_iter
->get_altstep_data_by_address(altstep_address
,
548 standalone_address
, activate_address
)) {
549 if (standalone_address
== NULL
)
550 TTCN_error("Internal error: Altstep reference %p cannot be "
551 "instantiated as a stand-alone alt statement.",
552 (void*)(unsigned long)altstep_address
);
553 return standalone_address
;
556 TTCN_error("Altstep reference %p in invoke operation does not point to a "
557 "valid altstep.", (void*)(unsigned long)altstep_address
);
562 genericfunc_t
Module_List::lookup_activate_address_by_altstep_address(
563 genericfunc_t altstep_address
)
565 if (altstep_address
== NULL
) TTCN_error("Performing an activate operation "
566 "on an unbound altstep reference.");
567 else if (altstep_address
== fat_null
) TTCN_error("Activate operation "
568 "cannot be performed on a null altstep reference.");
569 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
570 list_iter
= list_iter
->list_next
) {
571 genericfunc_t standalone_address
, activate_address
;
572 if (list_iter
->get_altstep_data_by_address(altstep_address
,
573 standalone_address
, activate_address
)) {
574 if (activate_address
== NULL
)
575 TTCN_error("Internal error: Altstep reference %p cannot be "
576 "activated as a default.",
577 (void*)(unsigned long)altstep_address
);
578 return activate_address
;
581 TTCN_error("Altstep reference %p in activate operation does not point to "
582 "a valid altstep.", (void*)(unsigned long)altstep_address
);
587 boolean
Module_List::lookup_function_by_address(genericfunc_t function_address
,
588 const char*& module_name
, const char*& function_name
)
590 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
591 list_iter
= list_iter
->list_next
) {
593 list_iter
->get_function_name_by_address(function_address
);
594 if (function_name
!= NULL
) {
595 module_name
= list_iter
->module_name
;
602 boolean
Module_List::lookup_altstep_by_address(genericfunc_t altstep_address
,
603 const char*& module_name
, const char*& altstep_name
)
605 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
606 list_iter
= list_iter
->list_next
) {
607 altstep_name
= list_iter
->get_altstep_name_by_address(altstep_address
);
608 if (altstep_name
!= NULL
) {
609 module_name
= list_iter
->module_name
;
616 boolean
Module_List::lookup_testcase_by_address(genericfunc_t testcase_address
,
617 const char*& module_name
, const char*& testcase_name
)
619 for(TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
620 list_iter
= list_iter
->list_next
) {
622 list_iter
->get_testcase_name_by_address(testcase_address
);
623 if (testcase_name
!= NULL
) {
624 module_name
= list_iter
->module_name
;
631 // ======================= TTCN_Module =======================
633 struct TTCN_Module::function_list_item
{
634 const char *function_name
;
635 genericfunc_t function_address
;
636 genericfunc_t start_address
;
637 function_list_item
*next_function
;
640 struct TTCN_Module::altstep_list_item
{
641 const char *altstep_name
;
642 genericfunc_t altstep_address
; //instance
643 genericfunc_t activate_address
;
644 genericfunc_t standalone_address
;
645 altstep_list_item
*next_altstep
;
648 struct TTCN_Module::testcase_list_item
{
649 const char *testcase_name
;
652 testcase_t testcase_function
;
653 genericfunc_t testcase_address
;
655 testcase_list_item
*next_testcase
;
658 /** Constructor for TTCN modules */
659 TTCN_Module::TTCN_Module(const char *par_module_name
,
660 const char *par_compilation_date
,
661 const char *par_compilation_time
,
662 const unsigned char *par_md5_checksum
,
663 init_func_t par_pre_init_func
,
664 const char* par_product_number
,
665 unsigned int par_suffix
,
666 unsigned int par_release
,
667 unsigned int par_patch
,
668 unsigned int par_build
,
669 const char* par_extra
,
670 size_t par_num_namespace
,
671 const namespace_t
*par_namespaces
,
672 init_func_t par_post_init_func
,
673 set_param_func_t par_set_param_func
,
674 log_param_func_t par_log_param_func
,
675 initialize_component_func_t par_initialize_component_func
,
676 start_func_t par_start_func
,
677 control_func_t par_control_func
)
678 : list_prev(NULL
), list_next(NULL
)
679 , module_type(TTCN3_MODULE
)
680 , module_name(par_module_name
)
681 , compilation_date(par_compilation_date
)
682 , compilation_time(par_compilation_time
)
683 , md5_checksum(par_md5_checksum
)
684 , product_number(par_product_number
)
686 , release(par_release
)
690 , num_namespaces(par_num_namespace
)
691 , xer_namespaces(par_namespaces
)
692 , pre_init_func(par_pre_init_func
)
693 , post_init_func(par_post_init_func
)
694 , pre_init_called(FALSE
)
695 , post_init_called(FALSE
)
696 , set_param_func(par_set_param_func
)
697 , log_param_func(par_log_param_func
)
698 , initialize_component_func(par_initialize_component_func
)
699 , start_func(par_start_func
)
700 , control_func(par_control_func
)
701 , function_head(NULL
)
702 , function_tail(NULL
)
705 , testcase_head(NULL
)
706 , testcase_tail(NULL
)
708 Module_List::add_module(this);
711 /** Constructor for ASN.1 modules */
712 TTCN_Module::TTCN_Module(const char *par_module_name
,
713 const char *par_compilation_date
,
714 const char *par_compilation_time
,
715 const unsigned char par_md5_checksum
[16],
716 init_func_t par_init_func
)
717 : list_prev(NULL
), list_next(NULL
)
718 , module_type(ASN1_MODULE
)
719 , module_name(par_module_name
)
720 , compilation_date(par_compilation_date
)
721 , compilation_time(par_compilation_time
)
722 , md5_checksum(par_md5_checksum
)
723 , product_number(NULL
)
730 , xer_namespaces(NULL
) // no EXER, no namespaces for ASN.1
731 , pre_init_func(par_init_func
)
732 , post_init_func(NULL
)
733 , pre_init_called(FALSE
)
734 , post_init_called(FALSE
)
735 , set_param_func(NULL
)
736 , log_param_func(NULL
)
737 , initialize_component_func(NULL
)
740 , function_head(NULL
)
741 , function_tail(NULL
)
744 , testcase_head(NULL
)
745 , testcase_tail(NULL
)
747 Module_List::add_module(this);
750 /** Constructor for C++ modules (?) */
751 TTCN_Module::TTCN_Module(const char *par_module_name
,
752 const char *par_compilation_date
,
753 const char *par_compilation_time
,
754 init_func_t par_init_func
)
755 : list_prev(NULL
), list_next(NULL
)
756 , module_type(CPLUSPLUS_MODULE
)
757 , module_name(par_module_name
? par_module_name
: "<unknown>")
758 , compilation_date(par_compilation_date
? par_compilation_date
: "<unknown>")
759 , compilation_time(par_compilation_time
? par_compilation_time
: "<unknown>")
761 , product_number(NULL
)
768 , xer_namespaces(NULL
)
769 , pre_init_func(par_init_func
)
770 , post_init_func(NULL
)
771 , pre_init_called(FALSE
)
772 , post_init_called(FALSE
)
773 , set_param_func(NULL
)
774 , log_param_func(NULL
)
775 , initialize_component_func(NULL
)
778 , function_head(NULL
)
779 , function_tail(NULL
)
782 , testcase_head(NULL
)
783 , testcase_tail(NULL
)
785 Module_List::add_module(this);
788 TTCN_Module::~TTCN_Module()
790 Module_List::remove_module(this);
791 while (function_head
!= NULL
) {
792 function_list_item
*tmp_ptr
=function_head
->next_function
;
793 delete function_head
;
794 function_head
= tmp_ptr
;
796 while (altstep_head
!= NULL
) {
797 altstep_list_item
*tmp_ptr
=altstep_head
->next_altstep
;
799 altstep_head
= tmp_ptr
;
801 while (testcase_head
!= NULL
) {
802 testcase_list_item
*tmp_ptr
= testcase_head
->next_testcase
;
803 delete testcase_head
;
804 testcase_head
= tmp_ptr
;
808 void TTCN_Module::pre_init_module()
810 if (pre_init_called
) return;
811 pre_init_called
= TRUE
;
812 if (pre_init_func
== NULL
) return;
816 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
817 "An error occurred while initializing the constants of module %s.",
823 void TTCN_Module::post_init_module()
825 if (post_init_called
) return;
826 post_init_called
= TRUE
;
827 TTCN_Logger::log_module_init(module_name
);
828 if (post_init_func
!= NULL
) post_init_func();
829 TTCN_Logger::log_module_init(module_name
, true);
832 void TTCN_Module::add_function(const char *function_name
,
833 genericfunc_t function_address
, genericfunc_t start_address
)
835 function_list_item
*new_item
= new function_list_item
;
836 new_item
->function_name
= function_name
;
837 new_item
->function_address
= function_address
;
838 new_item
->start_address
= start_address
;
839 new_item
->next_function
= NULL
;
840 if(function_head
== NULL
) function_head
= new_item
;
841 else function_tail
->next_function
= new_item
;
842 function_tail
= new_item
;
845 void TTCN_Module::add_altstep(const char *altstep_name
,
846 genericfunc_t altstep_address
, genericfunc_t activate_address
,
847 genericfunc_t standalone_address
)
849 altstep_list_item
*new_item
= new altstep_list_item
;
850 new_item
->altstep_name
= altstep_name
;
851 new_item
->altstep_address
= altstep_address
;
852 new_item
->activate_address
= activate_address
;
853 new_item
->standalone_address
= standalone_address
;
854 new_item
->next_altstep
= NULL
;
855 if(altstep_head
== NULL
) altstep_head
= new_item
;
856 else altstep_tail
->next_altstep
= new_item
;
857 altstep_tail
= new_item
;
860 void TTCN_Module::add_testcase_nonpard(const char *testcase_name
,
861 testcase_t testcase_function
)
863 testcase_list_item
*new_item
= new testcase_list_item
;
864 new_item
->testcase_name
= testcase_name
;
865 new_item
->is_pard
= FALSE
;
866 new_item
->testcase_function
= testcase_function
;
867 new_item
->next_testcase
= NULL
;
868 if (testcase_head
== NULL
) testcase_head
= new_item
;
869 else testcase_tail
->next_testcase
= new_item
;
870 testcase_tail
= new_item
;
873 void TTCN_Module::add_testcase_pard(const char *testcase_name
,
874 genericfunc_t testcase_address
)
876 testcase_list_item
*new_item
= new testcase_list_item
;
877 new_item
->testcase_name
= testcase_name
;
878 new_item
->is_pard
= TRUE
;
879 new_item
->testcase_address
= testcase_address
;
880 new_item
->next_testcase
= NULL
;
881 if(testcase_head
== NULL
) testcase_head
= new_item
;
882 else testcase_tail
->next_testcase
= new_item
;
883 testcase_tail
= new_item
;
886 void TTCN_Module::execute_testcase(const char *testcase_name
)
888 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
889 list_iter
= list_iter
->next_testcase
) {
890 if (!strcmp(list_iter
->testcase_name
, testcase_name
)) {
891 if (list_iter
->is_pard
) {
892 // Testcase has parameters. However, there might be a chance...
893 // Move to the next one (if any) and check that it has the same name.
894 list_iter
= list_iter
->next_testcase
;
895 if (list_iter
== NULL
896 || strcmp(list_iter
->testcase_name
, testcase_name
)) {
897 TTCN_error("Test case %s in module %s "
898 "cannot be executed individually (without control part) "
899 "because it has parameters.", testcase_name
, module_name
);
900 continue; // not reached
902 // else it has the same name, fall through
905 list_iter
->testcase_function(FALSE
, 0.0);
909 TTCN_error("Test case %s does not exist in module %s.", testcase_name
,
913 void TTCN_Module::execute_all_testcases()
915 boolean found
= FALSE
;
916 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
917 list_iter
= list_iter
->next_testcase
) {
918 if (!list_iter
->is_pard
) {
919 list_iter
->testcase_function(FALSE
, 0.0);
924 if (testcase_head
!= NULL
) TTCN_warning("Module %s does not contain "
925 "non-parameterized test cases, which can be executed individually "
926 "without control part.", module_name
);
927 else TTCN_warning("Module %s does not contain test cases.",
932 const char *TTCN_Module::get_function_name_by_address(
933 genericfunc_t function_address
)
935 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
936 list_iter
= list_iter
->next_function
)
937 if (list_iter
->function_address
== function_address
)
938 return list_iter
->function_name
;
942 genericfunc_t
TTCN_Module::get_function_address_by_name(const char *func_name
)
944 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
945 list_iter
= list_iter
->next_function
)
946 if (!strcmp(list_iter
->function_name
, func_name
))
947 return list_iter
->function_address
;
951 genericfunc_t
TTCN_Module::get_function_start_by_address(
952 genericfunc_t function_address
)
954 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
955 list_iter
= list_iter
->next_function
) {
956 if (list_iter
->function_address
== function_address
) {
957 if (list_iter
->start_address
!= NULL
)
958 return list_iter
->start_address
;
959 else TTCN_error("Function %s.%s cannot be started on a parallel "
960 "test component.", module_name
, list_iter
->function_name
);
966 const char *TTCN_Module::get_altstep_name_by_address(
967 genericfunc_t altstep_address
)
969 for(altstep_list_item
*list_iter
= altstep_head
; list_iter
!= NULL
;
970 list_iter
= list_iter
->next_altstep
) {
971 if (list_iter
->altstep_address
== altstep_address
)
972 return list_iter
->altstep_name
;
977 genericfunc_t
TTCN_Module::get_altstep_address_by_name(const char* altstep_name
)
979 for(altstep_list_item
*list_iter
= altstep_head
; list_iter
!= NULL
;
980 list_iter
= list_iter
->next_altstep
) {
981 if (!strcmp(list_iter
->altstep_name
, altstep_name
))
982 return list_iter
->altstep_address
;
987 boolean
TTCN_Module::get_altstep_data_by_address(genericfunc_t altstep_address
,
988 genericfunc_t
& standalone_address
, genericfunc_t
& activate_address
)
990 for(altstep_list_item
* list_iter
= altstep_head
; list_iter
!= NULL
;
991 list_iter
= list_iter
->next_altstep
) {
992 if (list_iter
->altstep_address
== altstep_address
) {
993 standalone_address
= list_iter
->standalone_address
;
994 activate_address
= list_iter
->activate_address
;
1001 const char *TTCN_Module::get_testcase_name_by_address(
1002 genericfunc_t testcase_address
)
1004 for(testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1005 list_iter
= list_iter
->next_testcase
) {
1006 if (list_iter
->is_pard
) {
1007 if (list_iter
->testcase_address
== testcase_address
)
1008 return list_iter
->testcase_name
;
1010 if ((genericfunc_t
)list_iter
->testcase_function
== testcase_address
)
1011 return list_iter
->testcase_name
;
1017 genericfunc_t
TTCN_Module::get_testcase_address_by_name(const char *testcase_name
)
1019 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1020 list_iter
= list_iter
->next_testcase
) {
1021 if (!strcmp(list_iter
->testcase_name
, testcase_name
)) {
1022 if (!list_iter
->is_pard
) return list_iter
->testcase_address
;
1023 else return (genericfunc_t
)list_iter
->testcase_function
;
1029 ModuleVersion
* TTCN_Module::get_version() const {
1030 return new ModuleVersion(product_number
, suffix
, release
, patch
, build
, extra
);
1033 void TTCN_Module::print_version()
1035 const char *type_str
;
1036 switch (module_type
) {
1038 type_str
= "TTCN-3";
1043 case CPLUSPLUS_MODULE
:
1050 fprintf(stderr
, "%-18s %-6s ", module_name
, type_str
);
1051 if (compilation_date
!= NULL
&& compilation_time
!= NULL
) {
1052 fprintf(stderr
, "%s %s", compilation_date
, compilation_time
);
1054 fputs("<unknown> ", stderr
);
1056 if (md5_checksum
!= NULL
) {
1058 for (int i
= 0; i
< 16; i
++) fprintf(stderr
, "%02x", md5_checksum
[i
]);
1060 // else it's likely not a TTCN module, so no version info
1062 putc(' ', stderr
); // separator for the version number
1063 if (product_number
!= NULL
) {
1064 fprintf(stderr
, "%s", product_number
);
1066 fprintf(stderr
, "/%d", suffix
);
1070 // release can be between 0 and 999999 inclusive
1071 // patch can go from 0 to 26 (English alphabet) - 6 (IOPQRW forbidden)
1072 // build can be between 0 and 99 inclusive
1073 if (release
<= 999999 && patch
<= ('Z'-'A'-6) && build
<= 99) {
1074 char *build_str
= buildstr(build
);
1075 if (build_str
== 0) TTCN_error("TTCN_Module::print_version()");
1076 if (extra
!= NULL
) {
1077 build_str
= mputprintf(build_str
, "%s", extra
);
1079 fprintf(stderr
, "R%u%c%-4s", release
, eri(patch
), build_str
);
1085 void TTCN_Module::list_testcases()
1087 if (control_func
!= NULL
) printf("%s.control\n", module_name
);
1088 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1089 list_iter
= list_iter
->next_testcase
)
1090 if(!list_iter
->is_pard
)
1091 printf("%s.%s\n", module_name
, list_iter
->testcase_name
);
1094 const namespace_t
*TTCN_Module::get_ns(size_t p_index
) const
1096 if (p_index
== (size_t)-1) return NULL
;
1097 if (p_index
>= num_namespaces
) TTCN_error(
1098 "Index overflow for namespaces, %lu instead of %lu",
1099 (unsigned long)p_index
, (unsigned long)num_namespaces
);
1101 return xer_namespaces
+ p_index
;
1104 const namespace_t
*TTCN_Module::get_controlns() const
1106 if (xer_namespaces
==NULL
) {
1107 TTCN_error("No namespaces for module %s", module_name
);
1109 if (xer_namespaces
[num_namespaces
].px
== NULL
1110 ||xer_namespaces
[num_namespaces
].px
[0] == '\0') {
1111 TTCN_error("No control namespace for module %s", module_name
);
1113 return xer_namespaces
+num_namespaces
;