1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
18 * Szabo, Janos Zoltan – initial implementation
20 ******************************************************************************/
25 #include "Module_list.hh"
30 #include "Param_Types.hh"
31 #include "Basetype.hh"
34 #include "../common/ModuleVersion.hh"
36 #include "../common/usage_stats.hh"
39 #include "../common/dbgnew.hh"
40 #include "Debugger.hh"
46 TTCN_Module
*Module_List::list_head
= NULL
, *Module_List::list_tail
= NULL
;
50 void Module_List::add_module(TTCN_Module
*module_ptr
)
52 if (module_ptr
->list_next
== NULL
&& module_ptr
!= list_tail
) {
53 TTCN_Module
*list_iter
= list_head
;
54 while (list_iter
!= NULL
) {
55 if (strcmp(list_iter
->module_name
, module_ptr
->module_name
) > 0)
57 list_iter
= list_iter
->list_next
;
59 if (list_iter
!= NULL
) {
60 // inserting before list_iter
61 module_ptr
->list_prev
= list_iter
->list_prev
;
62 if (list_iter
->list_prev
!= NULL
)
63 list_iter
->list_prev
->list_next
= module_ptr
;
64 list_iter
->list_prev
= module_ptr
;
66 // inserting at the end of list
67 module_ptr
->list_prev
= list_tail
;
68 if (list_tail
!= NULL
) list_tail
->list_next
= module_ptr
;
69 list_tail
= module_ptr
;
71 module_ptr
->list_next
= list_iter
;
72 if (list_iter
== list_head
) list_head
= module_ptr
;
76 void Module_List::remove_module(TTCN_Module
*module_ptr
)
78 if (module_ptr
->list_prev
== NULL
) list_head
= module_ptr
->list_next
;
79 else module_ptr
->list_prev
->list_next
= module_ptr
->list_next
;
80 if (module_ptr
->list_next
== NULL
) list_tail
= module_ptr
->list_prev
;
81 else module_ptr
->list_next
->list_prev
= module_ptr
->list_prev
;
83 module_ptr
->list_prev
= NULL
;
84 module_ptr
->list_next
= NULL
;
87 TTCN_Module
*Module_List::lookup_module(const char *module_name
)
89 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
90 list_iter
= list_iter
->list_next
)
91 if (!strcmp(list_iter
->module_name
, module_name
)) return list_iter
;
95 TTCN_Module
*Module_List::single_control_part()
97 TTCN_Module
*retval
= 0;
98 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
99 list_iter
= list_iter
->list_next
)
100 if (list_iter
->control_func
!= 0) {
101 if (retval
!= 0) return 0; // more than one control part => fail
102 else retval
= list_iter
;
108 void Module_List::pre_init_modules()
110 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
111 list_iter
= list_iter
->list_next
) list_iter
->pre_init_module();
114 void Module_List::post_init_modules()
116 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
117 list_iter
= list_iter
->list_next
) list_iter
->post_init_called
= FALSE
;
118 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
119 list_iter
= list_iter
->list_next
) list_iter
->post_init_module();
122 void Module_List::start_function(const char *module_name
,
123 const char *function_name
, Text_Buf
& function_arguments
)
125 TTCN_Module
*module_ptr
= lookup_module(module_name
);
126 if (module_ptr
== NULL
) {
127 // the START message must be dropped here
128 function_arguments
.cut_message();
129 TTCN_error("Internal error: Module %s does not exist.", module_name
);
130 } else if (module_ptr
->start_func
== NULL
) {
131 // the START message must be dropped here
132 function_arguments
.cut_message();
133 TTCN_error("Internal error: Module %s does not have startable "
134 "functions.", module_name
);
135 } else if (!module_ptr
->start_func(function_name
, function_arguments
)) {
136 // the START message must be dropped here
137 function_arguments
.cut_message();
138 TTCN_error("Internal error: Startable function %s does not exist in "
139 "module %s.", function_name
, module_name
);
143 void Module_List::initialize_component(const char *module_name
,
144 const char *component_type
, boolean init_base_comps
)
146 TTCN_Module
*module_ptr
= lookup_module(module_name
);
147 if (module_ptr
== NULL
)
148 TTCN_error("Internal error: Module %s does not exist.", module_name
);
149 else if (module_ptr
->initialize_component_func
== NULL
)
150 TTCN_error("Internal error: Module %s does not have component types.",
152 else if (!module_ptr
->initialize_component_func(component_type
,
154 TTCN_error("Internal error: Component type %s does not exist in "
155 "module %s.", component_type
, module_name
);
158 void Module_List::set_param(Module_Param
& param
)
160 // The first segment in the parameter name can either be the module name,
161 // or the module parameter name - both must be checked
162 const char* const first_name
= param
.get_id()->get_current_name();
163 const char* second_name
= NULL
;
164 boolean param_found
= FALSE
;
166 // Check if the first name segment is an existing module name
167 TTCN_Module
*module_ptr
= lookup_module(first_name
);
168 if (module_ptr
!= NULL
&& module_ptr
->set_param_func
!= NULL
&& param
.get_id()->next_name()) {
169 param_found
= module_ptr
->set_param_func(param
);
171 second_name
= param
.get_id()->get_current_name(); // for error messages
175 // If not found, check if the first name segment was the module parameter name
176 // (even if it matched a module name)
178 param
.get_id()->next_name(-1); // set the position back to the first segment
179 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
180 list_iter
= list_iter
->list_next
) {
181 if (list_iter
->set_param_func
!= NULL
&&
182 list_iter
->set_param_func(param
)) {
188 // Still not found -> error
190 if (module_ptr
== NULL
) {
191 param
.error("Module parameter cannot be set, because module `%s' does not exist, "
192 "and no parameter with name `%s' exists in any module.",
193 first_name
, first_name
);
194 } else if (module_ptr
->set_param_func
== NULL
) {
195 param
.error("Module parameter cannot be set, because module `%s' does not have "
196 "parameters, and no parameter with name `%s' exists in other modules.",
197 first_name
, first_name
);
199 param
.error("Module parameter cannot be set, because no parameter with name `%s' "
200 "exists in module `%s', and no parameter with name `%s' exists in any module.",
201 second_name
, first_name
, first_name
);
206 Module_Param
* Module_List::get_param(Module_Param_Name
& param_name
)
208 // The first segment in the parameter name can either be the module name,
209 // or the module parameter name - both must be checked
210 const char* const first_name
= param_name
.get_current_name();
211 const char* second_name
= NULL
;
212 Module_Param
* param
= NULL
;
214 // Check if the first name segment is an existing module name
215 TTCN_Module
*module_ptr
= lookup_module(first_name
);
216 if (module_ptr
!= NULL
&& module_ptr
->get_param_func
!= NULL
&& param_name
.next_name()) {
217 param
= module_ptr
->get_param_func(param_name
);
219 second_name
= param_name
.get_current_name(); // for error messages
223 // If not found, check if the first name segment was the module parameter name
224 // (even if it matched a module name)
226 param_name
.next_name(-1); // set the position back to the first segment
227 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
228 list_iter
= list_iter
->list_next
) {
229 if (list_iter
->get_param_func
!= NULL
) {
230 param
= list_iter
->get_param_func(param_name
);
238 // Still not found -> error
240 if (module_ptr
== NULL
) {
241 TTCN_error("Referenced module parameter cannot be found. Module `%s' does not exist, "
242 "and no parameter with name `%s' exists in any module.",
243 first_name
, first_name
);
244 } else if (module_ptr
->get_param_func
== NULL
) {
245 TTCN_error("Referenced module parameter cannot be found. Module `%s' does not have "
246 "parameters, and no parameter with name `%s' exists in other modules.",
247 first_name
, first_name
);
249 TTCN_error("Referenced module parameter cannot be found. No parameter with name `%s' "
250 "exists in module `%s', and no parameter with name `%s' exists in any module.",
251 second_name
, first_name
, first_name
);
254 else if (param
->get_type() == Module_Param::MP_Unbound
) {
256 TTCN_error("Referenced module parameter '%s' is unbound.", param_name
.get_str());
262 void Module_List::log_param()
264 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
265 list_iter
= list_iter
->list_next
) {
266 if (list_iter
->log_param_func
!= NULL
) {
267 TTCN_Logger::begin_event(TTCN_Logger::EXECUTOR_CONFIGDATA
);
268 TTCN_Logger::log_event("Module %s has the following parameters: "
269 "{ ", list_iter
->module_name
);
270 list_iter
->log_param_func();
271 TTCN_Logger::log_event_str(" }");
272 TTCN_Logger::end_event();
277 void Module_List::execute_control(const char *module_name
)
279 TTCN_Module
*module_ptr
= lookup_module(module_name
);
280 if (module_ptr
!= NULL
) {
281 if (module_ptr
->control_func
!= NULL
) {
283 module_ptr
->control_func();
284 } catch (const TC_Error
& tc_error
) {
285 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
286 "Unrecoverable error in control part of module %s. Execution aborted.",
288 } catch (const TC_End
& tc_end
) {
289 TTCN_Logger::log(TTCN_Logger::FUNCTION_UNQUALIFIED
,
290 "Control part of module %s was stopped.", module_name
);
292 } else TTCN_error("Module %s does not have control part.", module_name
);
293 } else TTCN_error("Module %s does not exist.", module_name
);
296 void Module_List::execute_testcase(const char *module_name
,
297 const char *testcase_name
)
299 TTCN_Module
*module_ptr
= lookup_module(module_name
);
300 if (module_ptr
!= NULL
) module_ptr
->execute_testcase(testcase_name
);
301 else TTCN_error("Module %s does not exist.", module_name
);
304 void Module_List::execute_all_testcases(const char *module_name
)
306 TTCN_Module
*module_ptr
= lookup_module(module_name
);
307 if (module_ptr
!= NULL
) module_ptr
->execute_all_testcases();
308 else TTCN_error("Module %s does not exist.", module_name
);
311 void Module_List::print_version()
314 "Module name Language Compilation time MD5 checksum "
316 "-------------------------------------------------------------------"
317 "--------------------\n", stderr
);
318 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
319 list_iter
= list_iter
->list_next
) list_iter
->print_version();
320 fputs("-------------------------------------------------------------------"
321 "--------------------\n", stderr
);
324 void Module_List::send_versions() {
326 std::set
<ModuleVersion
> versions
;
327 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
328 list_iter
= list_iter
->list_next
) {
329 ModuleVersion
* version
= list_iter
->get_version();
330 if (version
->hasProductNumber()) {
331 versions
.insert(*version
);
336 std::stringstream stream
;
338 for (std::set
<ModuleVersion
>::iterator it
= versions
.begin(); it
!= versions
.end(); ++it
) {
339 if (it
== versions
.begin()) {
340 stream
<< "&products=" << it
->toString();
342 stream
<< "," << it
->toString();
346 HttpSender
* sender
= new HttpSender
;
347 UsageData::getInstance().sendDataThreaded(stream
.str().c_str(), sender
);
352 void Module_List::list_testcases()
354 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
355 list_iter
= list_iter
->list_next
) list_iter
->list_testcases();
358 void Module_List::push_version(Text_Buf
& text_buf
)
361 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
362 list_iter
= list_iter
->list_next
) n_modules
++;
363 text_buf
.push_int(n_modules
);
364 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
365 list_iter
= list_iter
->list_next
) {
366 text_buf
.push_string(list_iter
->module_name
);
367 if (list_iter
->md5_checksum
!= NULL
) {
368 text_buf
.push_int(16);
369 text_buf
.push_raw(16, list_iter
->md5_checksum
);
370 } else text_buf
.push_int((RInt
)0);
374 void Module_List::encode_function(Text_Buf
& text_buf
,
375 genericfunc_t function_address
)
377 if (function_address
== NULL
)
378 TTCN_error("Text encoder: Encoding an unbound function reference.");
379 else if (function_address
== fat_null
) text_buf
.push_string("");
381 const char *module_name
, *function_name
;
382 if (lookup_function_by_address(function_address
, module_name
,
384 text_buf
.push_string(module_name
);
385 text_buf
.push_string(function_name
);
386 } else TTCN_error("Text encoder: Encoding function reference %p, "
387 "which does not point to a valid function.",
388 (void*)(unsigned long)function_address
);
392 void Module_List::decode_function(Text_Buf
& text_buf
,
393 genericfunc_t
*function_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 a function reference.", module_name
);
403 // to prevent from memory leaks
404 delete [] module_name
;
408 char *function_name
= text_buf
.pull_string();
409 genericfunc_t function_address
=
410 module_ptr
->get_function_address_by_name(function_name
);
411 if (function_address
!= NULL
) *function_addr_ptr
= function_address
;
414 TTCN_error("Text decoder: Reference to non-existent function "
415 "%s.%s was received.", module_name
, function_name
);
417 // to prevent from memory leaks
418 delete [] module_name
;
419 delete [] function_name
;
423 delete [] function_name
;
424 } else *function_addr_ptr
= fat_null
;
425 delete [] module_name
;
428 void Module_List::log_function(genericfunc_t function_address
)
430 if (function_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
431 else if (function_address
== fat_null
) TTCN_Logger::log_event_str("null");
433 const char *module_name
, *function_name
;
434 if (lookup_function_by_address(function_address
, module_name
,
435 function_name
)) TTCN_Logger::log_event("refers(%s.%s)",
436 module_name
, function_name
);
437 else TTCN_Logger::log_event("<invalid function reference: %p>",
438 (void*)(unsigned long)function_address
);
442 void Module_List::encode_altstep(Text_Buf
& text_buf
,
443 genericfunc_t altstep_address
)
445 if (altstep_address
== NULL
)
446 TTCN_error("Text encoder: Encoding an unbound altstep reference.");
447 else if (altstep_address
== fat_null
) text_buf
.push_string("");
449 const char *module_name
, *altstep_name
;
450 if (lookup_altstep_by_address(altstep_address
, module_name
,
452 text_buf
.push_string(module_name
);
453 text_buf
.push_string(altstep_name
);
454 } else TTCN_error("Text encoder: Encoding altstep reference %p, "
455 "which does not point to a valid altstep.",
456 (void*)(unsigned long)altstep_address
);
460 void Module_List::decode_altstep(Text_Buf
& text_buf
,
461 genericfunc_t
*altstep_addr_ptr
)
463 char *module_name
= text_buf
.pull_string();
464 if (module_name
[0] != '\0') {
465 TTCN_Module
* module_ptr
= lookup_module(module_name
);
466 if (module_ptr
== NULL
) {
468 TTCN_error("Text decoder: Module %s does not exist when trying "
469 "to decode an altstep reference.", module_name
);
471 // to prevent from memory leaks
472 delete [] module_name
;
476 char *altstep_name
= text_buf
.pull_string();
477 genericfunc_t altstep_address
=
478 module_ptr
->get_altstep_address_by_name(altstep_name
);
479 if (altstep_address
!= NULL
) *altstep_addr_ptr
= altstep_address
;
482 TTCN_error("Text decoder: Reference to non-existent altstep "
483 "%s.%s was received.", module_name
, altstep_name
);
485 // to prevent from memory leaks
486 delete [] module_name
;
487 delete [] altstep_name
;
491 delete [] altstep_name
;
492 } else *altstep_addr_ptr
= fat_null
;
493 delete [] module_name
;
496 void Module_List::log_altstep(genericfunc_t altstep_address
)
498 if (altstep_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
499 else if (altstep_address
== fat_null
) TTCN_Logger::log_event_str("null");
501 const char *module_name
, *altstep_name
;
502 if (lookup_altstep_by_address(altstep_address
, module_name
,
503 altstep_name
)) TTCN_Logger::log_event("refers(%s.%s)",
504 module_name
, altstep_name
);
505 else TTCN_Logger::log_event("<invalid altstep reference: %p>",
506 (void*)(unsigned long)altstep_address
);
510 // called by testcase_name::encode_text in the generated code
511 void Module_List::encode_testcase(Text_Buf
& text_buf
,
512 genericfunc_t testcase_address
)
514 if (testcase_address
== NULL
)
515 TTCN_error("Text encoder: Encoding an unbound testcase reference.");
516 else if (testcase_address
== fat_null
) text_buf
.push_string("");
518 const char *module_name
, *testcase_name
;
519 if (lookup_testcase_by_address(testcase_address
, module_name
,
521 text_buf
.push_string(module_name
);
522 text_buf
.push_string(testcase_name
);
523 } else TTCN_error("Text encoder: Encoding testcase reference %p, "
524 "which does not point to a valid testcase.",
525 (void*)(unsigned long)testcase_address
);
529 // called by testcase_name::decode_text in the generated code
530 void Module_List::decode_testcase(Text_Buf
& text_buf
,
531 genericfunc_t
*testcase_addr_ptr
)
533 char *module_name
= text_buf
.pull_string();
534 if (module_name
[0] != '\0') {
535 TTCN_Module
* module_ptr
= lookup_module(module_name
);
536 if (module_ptr
== NULL
) {
538 TTCN_error("Text decoder: Module %s does not exist when trying "
539 "to decode a testcase reference.", module_name
);
541 // to prevent from memory leaks
542 delete [] module_name
;
546 char *testcase_name
= text_buf
.pull_string();
547 genericfunc_t testcase_address
=
548 module_ptr
->get_testcase_address_by_name(testcase_name
);
549 if (testcase_address
!= NULL
) *testcase_addr_ptr
= testcase_address
;
552 TTCN_error("Text decoder: Reference to non-existent testcase "
553 "%s.%s was received.", module_name
, testcase_name
);
555 // to prevent from memory leaks
556 delete [] module_name
;
557 delete [] testcase_name
;
561 delete [] testcase_name
;
562 } else *testcase_addr_ptr
= fat_null
;
563 delete [] module_name
;
566 void Module_List::log_testcase(genericfunc_t testcase_address
)
568 if (testcase_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
569 else if (testcase_address
== fat_null
) TTCN_Logger::log_event_str("null");
571 const char *module_name
, *testcase_name
;
572 if (lookup_testcase_by_address(testcase_address
, module_name
,
573 testcase_name
)) TTCN_Logger::log_event("refers(%s.%s)",
574 module_name
, testcase_name
);
575 else TTCN_Logger::log_event("<invalid testcase reference: %p>",
576 (void*)(unsigned long)testcase_address
);
580 genericfunc_t
Module_List::get_fat_null()
585 genericfunc_t
Module_List::lookup_start_by_function_address(
586 genericfunc_t function_address
)
588 if (function_address
== NULL
) TTCN_error("Performing a start test "
589 "component operation with an unbound function reference.");
590 else if (function_address
== fat_null
) TTCN_error("Start test component "
591 "operation cannot be performed with a null function reference.");
592 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
593 list_iter
= list_iter
->list_next
) {
594 genericfunc_t function_start
=
595 list_iter
->get_function_start_by_address(function_address
);
596 if (function_start
!= NULL
) return function_start
;
598 TTCN_error("Function reference %p in start test component operation does "
599 "not point to a valid function.",
600 (void*)(unsigned long)function_address
);
605 genericfunc_t
Module_List::lookup_standalone_address_by_altstep_address(
606 genericfunc_t altstep_address
)
608 if (altstep_address
== NULL
) TTCN_error("Performing an invoke operation "
609 "on an unbound altstep reference.");
610 else if (altstep_address
== fat_null
) TTCN_error("Invoke operation "
611 "cannot be performed on a null altstep reference.");
612 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
613 list_iter
= list_iter
->list_next
) {
614 genericfunc_t standalone_address
, activate_address
;
615 if (list_iter
->get_altstep_data_by_address(altstep_address
,
616 standalone_address
, activate_address
)) {
617 if (standalone_address
== NULL
)
618 TTCN_error("Internal error: Altstep reference %p cannot be "
619 "instantiated as a stand-alone alt statement.",
620 (void*)(unsigned long)altstep_address
);
621 return standalone_address
;
624 TTCN_error("Altstep reference %p in invoke operation does not point to a "
625 "valid altstep.", (void*)(unsigned long)altstep_address
);
630 genericfunc_t
Module_List::lookup_activate_address_by_altstep_address(
631 genericfunc_t altstep_address
)
633 if (altstep_address
== NULL
) TTCN_error("Performing an activate operation "
634 "on an unbound altstep reference.");
635 else if (altstep_address
== fat_null
) TTCN_error("Activate operation "
636 "cannot be performed on a null altstep reference.");
637 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
638 list_iter
= list_iter
->list_next
) {
639 genericfunc_t standalone_address
, activate_address
;
640 if (list_iter
->get_altstep_data_by_address(altstep_address
,
641 standalone_address
, activate_address
)) {
642 if (activate_address
== NULL
)
643 TTCN_error("Internal error: Altstep reference %p cannot be "
644 "activated as a default.",
645 (void*)(unsigned long)altstep_address
);
646 return activate_address
;
649 TTCN_error("Altstep reference %p in activate operation does not point to "
650 "a valid altstep.", (void*)(unsigned long)altstep_address
);
655 boolean
Module_List::lookup_function_by_address(genericfunc_t function_address
,
656 const char*& module_name
, const char*& function_name
)
658 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
659 list_iter
= list_iter
->list_next
) {
661 list_iter
->get_function_name_by_address(function_address
);
662 if (function_name
!= NULL
) {
663 module_name
= list_iter
->module_name
;
670 boolean
Module_List::lookup_altstep_by_address(genericfunc_t altstep_address
,
671 const char*& module_name
, const char*& altstep_name
)
673 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
674 list_iter
= list_iter
->list_next
) {
675 altstep_name
= list_iter
->get_altstep_name_by_address(altstep_address
);
676 if (altstep_name
!= NULL
) {
677 module_name
= list_iter
->module_name
;
684 boolean
Module_List::lookup_testcase_by_address(genericfunc_t testcase_address
,
685 const char*& module_name
, const char*& testcase_name
)
687 for(TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
688 list_iter
= list_iter
->list_next
) {
690 list_iter
->get_testcase_name_by_address(testcase_address
);
691 if (testcase_name
!= NULL
) {
692 module_name
= list_iter
->module_name
;
699 // ======================= TTCN_Module =======================
701 struct TTCN_Module::function_list_item
{
702 const char *function_name
;
703 genericfunc_t function_address
;
704 genericfunc_t start_address
;
705 function_list_item
*next_function
;
708 struct TTCN_Module::altstep_list_item
{
709 const char *altstep_name
;
710 genericfunc_t altstep_address
; //instance
711 genericfunc_t activate_address
;
712 genericfunc_t standalone_address
;
713 altstep_list_item
*next_altstep
;
716 struct TTCN_Module::testcase_list_item
{
717 const char *testcase_name
;
720 testcase_t testcase_function
;
721 genericfunc_t testcase_address
;
723 testcase_list_item
*next_testcase
;
726 /** Constructor for TTCN modules */
727 TTCN_Module::TTCN_Module(const char *par_module_name
,
728 const char *par_compilation_date
,
729 const char *par_compilation_time
,
730 const unsigned char *par_md5_checksum
,
731 init_func_t par_pre_init_func
,
732 const char* par_product_number
,
733 unsigned int par_suffix
,
734 unsigned int par_release
,
735 unsigned int par_patch
,
736 unsigned int par_build
,
737 const char* par_extra
,
738 size_t par_num_namespace
,
739 const namespace_t
*par_namespaces
,
740 init_func_t par_post_init_func
,
741 set_param_func_t par_set_param_func
,
742 get_param_func_t par_get_param_func
,
743 log_param_func_t par_log_param_func
,
744 initialize_component_func_t par_initialize_component_func
,
745 start_func_t par_start_func
,
746 control_func_t par_control_func
)
747 : list_prev(NULL
), list_next(NULL
)
748 , module_type(TTCN3_MODULE
)
749 , module_name(par_module_name
)
750 , compilation_date(par_compilation_date
)
751 , compilation_time(par_compilation_time
)
752 , md5_checksum(par_md5_checksum
)
753 , product_number(par_product_number
)
755 , release(par_release
)
759 , num_namespaces(par_num_namespace
)
760 , xer_namespaces(par_namespaces
)
761 , pre_init_func(par_pre_init_func
)
762 , post_init_func(par_post_init_func
)
763 , pre_init_called(FALSE
)
764 , post_init_called(FALSE
)
765 , set_param_func(par_set_param_func
)
766 , get_param_func(par_get_param_func
)
767 , log_param_func(par_log_param_func
)
768 , initialize_component_func(par_initialize_component_func
)
769 , start_func(par_start_func
)
770 , control_func(par_control_func
)
771 , function_head(NULL
)
772 , function_tail(NULL
)
775 , testcase_head(NULL
)
776 , testcase_tail(NULL
)
778 Module_List::add_module(this);
781 /** Constructor for ASN.1 modules */
782 TTCN_Module::TTCN_Module(const char *par_module_name
,
783 const char *par_compilation_date
,
784 const char *par_compilation_time
,
785 const unsigned char par_md5_checksum
[16],
786 init_func_t par_init_func
)
787 : list_prev(NULL
), list_next(NULL
)
788 , module_type(ASN1_MODULE
)
789 , module_name(par_module_name
)
790 , compilation_date(par_compilation_date
)
791 , compilation_time(par_compilation_time
)
792 , md5_checksum(par_md5_checksum
)
793 , product_number(NULL
)
800 , xer_namespaces(NULL
) // no EXER, no namespaces for ASN.1
801 , pre_init_func(par_init_func
)
802 , post_init_func(NULL
)
803 , pre_init_called(FALSE
)
804 , post_init_called(FALSE
)
805 , set_param_func(NULL
)
806 , get_param_func(NULL
)
807 , log_param_func(NULL
)
808 , initialize_component_func(NULL
)
811 , function_head(NULL
)
812 , function_tail(NULL
)
815 , testcase_head(NULL
)
816 , testcase_tail(NULL
)
818 Module_List::add_module(this);
821 /** Constructor for C++ modules (?) */
822 TTCN_Module::TTCN_Module(const char *par_module_name
,
823 const char *par_compilation_date
,
824 const char *par_compilation_time
,
825 init_func_t par_init_func
)
826 : list_prev(NULL
), list_next(NULL
)
827 , module_type(CPLUSPLUS_MODULE
)
828 , module_name(par_module_name
? par_module_name
: "<unknown>")
829 , compilation_date(par_compilation_date
? par_compilation_date
: "<unknown>")
830 , compilation_time(par_compilation_time
? par_compilation_time
: "<unknown>")
832 , product_number(NULL
)
839 , xer_namespaces(NULL
)
840 , pre_init_func(par_init_func
)
841 , post_init_func(NULL
)
842 , pre_init_called(FALSE
)
843 , post_init_called(FALSE
)
844 , set_param_func(NULL
)
845 , log_param_func(NULL
)
846 , initialize_component_func(NULL
)
849 , function_head(NULL
)
850 , function_tail(NULL
)
853 , testcase_head(NULL
)
854 , testcase_tail(NULL
)
856 Module_List::add_module(this);
859 TTCN_Module::~TTCN_Module()
861 Module_List::remove_module(this);
862 while (function_head
!= NULL
) {
863 function_list_item
*tmp_ptr
=function_head
->next_function
;
864 delete function_head
;
865 function_head
= tmp_ptr
;
867 while (altstep_head
!= NULL
) {
868 altstep_list_item
*tmp_ptr
=altstep_head
->next_altstep
;
870 altstep_head
= tmp_ptr
;
872 while (testcase_head
!= NULL
) {
873 testcase_list_item
*tmp_ptr
= testcase_head
->next_testcase
;
874 delete testcase_head
;
875 testcase_head
= tmp_ptr
;
879 void TTCN_Module::pre_init_module()
881 if (pre_init_called
) return;
882 pre_init_called
= TRUE
;
883 if (pre_init_func
== NULL
) return;
887 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
888 "An error occurred while initializing the constants of module %s.",
894 void TTCN_Module::post_init_module()
896 if (post_init_called
) return;
897 post_init_called
= TRUE
;
898 TTCN_Logger::log_module_init(module_name
);
899 if (post_init_func
!= NULL
) post_init_func();
900 TTCN_Logger::log_module_init(module_name
, true);
903 void TTCN_Module::add_function(const char *function_name
,
904 genericfunc_t function_address
, genericfunc_t start_address
)
906 function_list_item
*new_item
= new function_list_item
;
907 new_item
->function_name
= function_name
;
908 new_item
->function_address
= function_address
;
909 new_item
->start_address
= start_address
;
910 new_item
->next_function
= NULL
;
911 if(function_head
== NULL
) function_head
= new_item
;
912 else function_tail
->next_function
= new_item
;
913 function_tail
= new_item
;
916 void TTCN_Module::add_altstep(const char *altstep_name
,
917 genericfunc_t altstep_address
, genericfunc_t activate_address
,
918 genericfunc_t standalone_address
)
920 altstep_list_item
*new_item
= new altstep_list_item
;
921 new_item
->altstep_name
= altstep_name
;
922 new_item
->altstep_address
= altstep_address
;
923 new_item
->activate_address
= activate_address
;
924 new_item
->standalone_address
= standalone_address
;
925 new_item
->next_altstep
= NULL
;
926 if(altstep_head
== NULL
) altstep_head
= new_item
;
927 else altstep_tail
->next_altstep
= new_item
;
928 altstep_tail
= new_item
;
931 void TTCN_Module::add_testcase_nonpard(const char *testcase_name
,
932 testcase_t testcase_function
)
934 testcase_list_item
*new_item
= new testcase_list_item
;
935 new_item
->testcase_name
= testcase_name
;
936 new_item
->is_pard
= FALSE
;
937 new_item
->testcase_function
= testcase_function
;
938 new_item
->next_testcase
= NULL
;
939 if (testcase_head
== NULL
) testcase_head
= new_item
;
940 else testcase_tail
->next_testcase
= new_item
;
941 testcase_tail
= new_item
;
944 void TTCN_Module::add_testcase_pard(const char *testcase_name
,
945 genericfunc_t testcase_address
)
947 testcase_list_item
*new_item
= new testcase_list_item
;
948 new_item
->testcase_name
= testcase_name
;
949 new_item
->is_pard
= TRUE
;
950 new_item
->testcase_address
= testcase_address
;
951 new_item
->next_testcase
= NULL
;
952 if(testcase_head
== NULL
) testcase_head
= new_item
;
953 else testcase_tail
->next_testcase
= new_item
;
954 testcase_tail
= new_item
;
957 void TTCN_Module::execute_testcase(const char *testcase_name
)
959 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
960 list_iter
= list_iter
->next_testcase
) {
961 if (!strcmp(list_iter
->testcase_name
, testcase_name
)) {
962 if (list_iter
->is_pard
) {
963 // Testcase has parameters. However, there might be a chance...
964 // Move to the next one (if any) and check that it has the same name.
965 list_iter
= list_iter
->next_testcase
;
966 if (list_iter
== NULL
967 || strcmp(list_iter
->testcase_name
, testcase_name
)) {
968 TTCN_error("Test case %s in module %s "
969 "cannot be executed individually (without control part) "
970 "because it has parameters.", testcase_name
, module_name
);
971 continue; // not reached
973 // else it has the same name, fall through
976 list_iter
->testcase_function(FALSE
, 0.0);
980 TTCN_error("Test case %s does not exist in module %s.", testcase_name
,
984 void TTCN_Module::execute_all_testcases()
986 boolean found
= FALSE
;
987 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
988 list_iter
= list_iter
->next_testcase
) {
989 if (ttcn3_debugger
.is_exiting()) {
992 if (!list_iter
->is_pard
) {
993 list_iter
->testcase_function(FALSE
, 0.0);
998 if (testcase_head
!= NULL
) TTCN_warning("Module %s does not contain "
999 "non-parameterized test cases, which can be executed individually "
1000 "without control part.", module_name
);
1001 else TTCN_warning("Module %s does not contain test cases.",
1006 const char *TTCN_Module::get_function_name_by_address(
1007 genericfunc_t function_address
)
1009 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
1010 list_iter
= list_iter
->next_function
)
1011 if (list_iter
->function_address
== function_address
)
1012 return list_iter
->function_name
;
1016 genericfunc_t
TTCN_Module::get_function_address_by_name(const char *func_name
)
1018 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
1019 list_iter
= list_iter
->next_function
)
1020 if (!strcmp(list_iter
->function_name
, func_name
))
1021 return list_iter
->function_address
;
1025 genericfunc_t
TTCN_Module::get_function_start_by_address(
1026 genericfunc_t function_address
)
1028 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
1029 list_iter
= list_iter
->next_function
) {
1030 if (list_iter
->function_address
== function_address
) {
1031 if (list_iter
->start_address
!= NULL
)
1032 return list_iter
->start_address
;
1033 else TTCN_error("Function %s.%s cannot be started on a parallel "
1034 "test component.", module_name
, list_iter
->function_name
);
1040 const char *TTCN_Module::get_altstep_name_by_address(
1041 genericfunc_t altstep_address
)
1043 for(altstep_list_item
*list_iter
= altstep_head
; list_iter
!= NULL
;
1044 list_iter
= list_iter
->next_altstep
) {
1045 if (list_iter
->altstep_address
== altstep_address
)
1046 return list_iter
->altstep_name
;
1051 genericfunc_t
TTCN_Module::get_altstep_address_by_name(const char* altstep_name
)
1053 for(altstep_list_item
*list_iter
= altstep_head
; list_iter
!= NULL
;
1054 list_iter
= list_iter
->next_altstep
) {
1055 if (!strcmp(list_iter
->altstep_name
, altstep_name
))
1056 return list_iter
->altstep_address
;
1061 boolean
TTCN_Module::get_altstep_data_by_address(genericfunc_t altstep_address
,
1062 genericfunc_t
& standalone_address
, genericfunc_t
& activate_address
)
1064 for(altstep_list_item
* list_iter
= altstep_head
; list_iter
!= NULL
;
1065 list_iter
= list_iter
->next_altstep
) {
1066 if (list_iter
->altstep_address
== altstep_address
) {
1067 standalone_address
= list_iter
->standalone_address
;
1068 activate_address
= list_iter
->activate_address
;
1075 const char *TTCN_Module::get_testcase_name_by_address(
1076 genericfunc_t testcase_address
)
1078 for(testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1079 list_iter
= list_iter
->next_testcase
) {
1080 if (list_iter
->is_pard
) {
1081 if (list_iter
->testcase_address
== testcase_address
)
1082 return list_iter
->testcase_name
;
1084 if ((genericfunc_t
)list_iter
->testcase_function
== testcase_address
)
1085 return list_iter
->testcase_name
;
1091 genericfunc_t
TTCN_Module::get_testcase_address_by_name(const char *testcase_name
)
1093 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1094 list_iter
= list_iter
->next_testcase
) {
1095 if (!strcmp(list_iter
->testcase_name
, testcase_name
)) {
1096 if (!list_iter
->is_pard
) return list_iter
->testcase_address
;
1097 else return (genericfunc_t
)list_iter
->testcase_function
;
1103 ModuleVersion
* TTCN_Module::get_version() const {
1104 return new ModuleVersion(product_number
, suffix
, release
, patch
, build
, extra
);
1107 void TTCN_Module::print_version()
1109 const char *type_str
;
1110 switch (module_type
) {
1112 type_str
= "TTCN-3";
1117 case CPLUSPLUS_MODULE
:
1124 fprintf(stderr
, "%-18s %-6s ", module_name
, type_str
);
1125 if (compilation_date
!= NULL
&& compilation_time
!= NULL
) {
1126 fprintf(stderr
, "%s %s", compilation_date
, compilation_time
);
1128 fputs("<unknown> ", stderr
);
1130 if (md5_checksum
!= NULL
) {
1132 for (int i
= 0; i
< 16; i
++) fprintf(stderr
, "%02x", md5_checksum
[i
]);
1134 // else it's likely not a TTCN module, so no version info
1136 putc(' ', stderr
); // separator for the version number
1137 if (product_number
!= NULL
) {
1138 fprintf(stderr
, "%s", product_number
);
1140 fprintf(stderr
, "/%d", suffix
);
1144 // release can be between 0 and 999999 inclusive
1145 // patch can go from 0 to 26 (English alphabet) - 6 (IOPQRW forbidden)
1146 // build can be between 0 and 99 inclusive
1147 if (release
<= 999999 && patch
<= ('Z'-'A'-6) && build
<= 99) {
1148 char *build_str
= buildstr(build
);
1149 if (build_str
== 0) TTCN_error("TTCN_Module::print_version()");
1150 if (extra
!= NULL
) {
1151 build_str
= mputprintf(build_str
, "%s", extra
);
1153 fprintf(stderr
, "R%u%c%-4s", release
, eri(patch
), build_str
);
1159 void TTCN_Module::list_testcases()
1161 if (control_func
!= NULL
) printf("%s.control\n", module_name
);
1162 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1163 list_iter
= list_iter
->next_testcase
)
1164 if(!list_iter
->is_pard
)
1165 printf("%s.%s\n", module_name
, list_iter
->testcase_name
);
1168 const namespace_t
*TTCN_Module::get_ns(size_t p_index
) const
1170 if (p_index
== (size_t)-1) return NULL
;
1171 if (p_index
>= num_namespaces
) TTCN_error(
1172 "Index overflow for namespaces, %lu instead of %lu",
1173 (unsigned long)p_index
, (unsigned long)num_namespaces
);
1175 return xer_namespaces
+ p_index
;
1178 const namespace_t
*TTCN_Module::get_controlns() const
1180 if (xer_namespaces
==NULL
) {
1181 TTCN_error("No namespaces for module %s", module_name
);
1183 if (xer_namespaces
[num_namespaces
].px
== NULL
1184 ||xer_namespaces
[num_namespaces
].px
[0] == '\0') {
1185 TTCN_error("No control namespace for module %s", module_name
);
1187 return xer_namespaces
+num_namespaces
;