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"
45 TTCN_Module
*Module_List::list_head
= NULL
, *Module_List::list_tail
= NULL
;
49 void Module_List::add_module(TTCN_Module
*module_ptr
)
51 if (module_ptr
->list_next
== NULL
&& module_ptr
!= list_tail
) {
52 TTCN_Module
*list_iter
= list_head
;
53 while (list_iter
!= NULL
) {
54 if (strcmp(list_iter
->module_name
, module_ptr
->module_name
) > 0)
56 list_iter
= list_iter
->list_next
;
58 if (list_iter
!= NULL
) {
59 // inserting before list_iter
60 module_ptr
->list_prev
= list_iter
->list_prev
;
61 if (list_iter
->list_prev
!= NULL
)
62 list_iter
->list_prev
->list_next
= module_ptr
;
63 list_iter
->list_prev
= module_ptr
;
65 // inserting at the end of list
66 module_ptr
->list_prev
= list_tail
;
67 if (list_tail
!= NULL
) list_tail
->list_next
= module_ptr
;
68 list_tail
= module_ptr
;
70 module_ptr
->list_next
= list_iter
;
71 if (list_iter
== list_head
) list_head
= module_ptr
;
75 void Module_List::remove_module(TTCN_Module
*module_ptr
)
77 if (module_ptr
->list_prev
== NULL
) list_head
= module_ptr
->list_next
;
78 else module_ptr
->list_prev
->list_next
= module_ptr
->list_next
;
79 if (module_ptr
->list_next
== NULL
) list_tail
= module_ptr
->list_prev
;
80 else module_ptr
->list_next
->list_prev
= module_ptr
->list_prev
;
82 module_ptr
->list_prev
= NULL
;
83 module_ptr
->list_next
= NULL
;
86 TTCN_Module
*Module_List::lookup_module(const char *module_name
)
88 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
89 list_iter
= list_iter
->list_next
)
90 if (!strcmp(list_iter
->module_name
, module_name
)) return list_iter
;
94 TTCN_Module
*Module_List::single_control_part()
96 TTCN_Module
*retval
= 0;
97 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
98 list_iter
= list_iter
->list_next
)
99 if (list_iter
->control_func
!= 0) {
100 if (retval
!= 0) return 0; // more than one control part => fail
101 else retval
= list_iter
;
107 void Module_List::pre_init_modules()
109 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
110 list_iter
= list_iter
->list_next
) list_iter
->pre_init_module();
113 void Module_List::post_init_modules()
115 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
116 list_iter
= list_iter
->list_next
) list_iter
->post_init_called
= FALSE
;
117 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
118 list_iter
= list_iter
->list_next
) list_iter
->post_init_module();
121 void Module_List::start_function(const char *module_name
,
122 const char *function_name
, Text_Buf
& function_arguments
)
124 TTCN_Module
*module_ptr
= lookup_module(module_name
);
125 if (module_ptr
== NULL
) {
126 // the START message must be dropped here
127 function_arguments
.cut_message();
128 TTCN_error("Internal error: Module %s does not exist.", module_name
);
129 } else if (module_ptr
->start_func
== NULL
) {
130 // the START message must be dropped here
131 function_arguments
.cut_message();
132 TTCN_error("Internal error: Module %s does not have startable "
133 "functions.", module_name
);
134 } else if (!module_ptr
->start_func(function_name
, function_arguments
)) {
135 // the START message must be dropped here
136 function_arguments
.cut_message();
137 TTCN_error("Internal error: Startable function %s does not exist in "
138 "module %s.", function_name
, module_name
);
142 void Module_List::initialize_component(const char *module_name
,
143 const char *component_type
, boolean init_base_comps
)
145 TTCN_Module
*module_ptr
= lookup_module(module_name
);
146 if (module_ptr
== NULL
)
147 TTCN_error("Internal error: Module %s does not exist.", module_name
);
148 else if (module_ptr
->initialize_component_func
== NULL
)
149 TTCN_error("Internal error: Module %s does not have component types.",
151 else if (!module_ptr
->initialize_component_func(component_type
,
153 TTCN_error("Internal error: Component type %s does not exist in "
154 "module %s.", component_type
, module_name
);
157 void Module_List::set_param(Module_Param
& param
)
159 // The first segment in the parameter name can either be the module name,
160 // or the module parameter name - both must be checked
161 const char* const first_name
= param
.get_id()->get_current_name();
162 const char* second_name
= NULL
;
163 boolean param_found
= FALSE
;
165 // Check if the first name segment is an existing module name
166 TTCN_Module
*module_ptr
= lookup_module(first_name
);
167 if (module_ptr
!= NULL
&& module_ptr
->set_param_func
!= NULL
&& param
.get_id()->next_name()) {
168 param_found
= module_ptr
->set_param_func(param
);
170 second_name
= param
.get_id()->get_current_name(); // for error messages
174 // If not found, check if the first name segment was the module parameter name
175 // (even if it matched a module name)
177 param
.get_id()->next_name(-1); // set the position back to the first segment
178 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
179 list_iter
= list_iter
->list_next
) {
180 if (list_iter
->set_param_func
!= NULL
&&
181 list_iter
->set_param_func(param
)) {
187 // Still not found -> error
189 if (module_ptr
== NULL
) {
190 param
.error("Module parameter cannot be set, because module `%s' does not exist, "
191 "and no parameter with name `%s' exists in any module.",
192 first_name
, first_name
);
193 } else if (module_ptr
->set_param_func
== NULL
) {
194 param
.error("Module parameter cannot be set, because module `%s' does not have "
195 "parameters, and no parameter with name `%s' exists in other modules.",
196 first_name
, first_name
);
198 param
.error("Module parameter cannot be set, because no parameter with name `%s' "
199 "exists in module `%s', and no parameter with name `%s' exists in any module.",
200 second_name
, first_name
, first_name
);
205 Module_Param
* Module_List::get_param(Module_Param_Name
& param_name
)
207 // The first segment in the parameter name can either be the module name,
208 // or the module parameter name - both must be checked
209 const char* const first_name
= param_name
.get_current_name();
210 const char* second_name
= NULL
;
211 Module_Param
* param
= NULL
;
213 // Check if the first name segment is an existing module name
214 TTCN_Module
*module_ptr
= lookup_module(first_name
);
215 if (module_ptr
!= NULL
&& module_ptr
->get_param_func
!= NULL
&& param_name
.next_name()) {
216 param
= module_ptr
->get_param_func(param_name
);
218 second_name
= param_name
.get_current_name(); // for error messages
222 // If not found, check if the first name segment was the module parameter name
223 // (even if it matched a module name)
225 param_name
.next_name(-1); // set the position back to the first segment
226 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
227 list_iter
= list_iter
->list_next
) {
228 if (list_iter
->get_param_func
!= NULL
) {
229 param
= list_iter
->get_param_func(param_name
);
237 // Still not found -> error
239 if (module_ptr
== NULL
) {
240 TTCN_error("Referenced module parameter cannot be found. Module `%s' does not exist, "
241 "and no parameter with name `%s' exists in any module.",
242 first_name
, first_name
);
243 } else if (module_ptr
->get_param_func
== NULL
) {
244 TTCN_error("Referenced module parameter cannot be found. Module `%s' does not have "
245 "parameters, and no parameter with name `%s' exists in other modules.",
246 first_name
, first_name
);
248 TTCN_error("Referenced module parameter cannot be found. No parameter with name `%s' "
249 "exists in module `%s', and no parameter with name `%s' exists in any module.",
250 second_name
, first_name
, first_name
);
253 else if (param
->get_type() == Module_Param::MP_Unbound
) {
255 TTCN_error("Referenced module parameter '%s' is unbound.", param_name
.get_str());
261 void Module_List::log_param()
263 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
264 list_iter
= list_iter
->list_next
) {
265 if (list_iter
->log_param_func
!= NULL
) {
266 TTCN_Logger::begin_event(TTCN_Logger::EXECUTOR_CONFIGDATA
);
267 TTCN_Logger::log_event("Module %s has the following parameters: "
268 "{ ", list_iter
->module_name
);
269 list_iter
->log_param_func();
270 TTCN_Logger::log_event_str(" }");
271 TTCN_Logger::end_event();
276 void Module_List::execute_control(const char *module_name
)
278 TTCN_Module
*module_ptr
= lookup_module(module_name
);
279 if (module_ptr
!= NULL
) {
280 if (module_ptr
->control_func
!= NULL
) {
282 module_ptr
->control_func();
283 } catch (const TC_Error
& tc_error
) {
284 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
285 "Unrecoverable error in control part of module %s. Execution aborted.",
287 } catch (const TC_End
& tc_end
) {
288 TTCN_Logger::log(TTCN_Logger::FUNCTION_UNQUALIFIED
,
289 "Control part of module %s was stopped.", module_name
);
291 } else TTCN_error("Module %s does not have control part.", module_name
);
292 } else TTCN_error("Module %s does not exist.", module_name
);
295 void Module_List::execute_testcase(const char *module_name
,
296 const char *testcase_name
)
298 TTCN_Module
*module_ptr
= lookup_module(module_name
);
299 if (module_ptr
!= NULL
) module_ptr
->execute_testcase(testcase_name
);
300 else TTCN_error("Module %s does not exist.", module_name
);
303 void Module_List::execute_all_testcases(const char *module_name
)
305 TTCN_Module
*module_ptr
= lookup_module(module_name
);
306 if (module_ptr
!= NULL
) module_ptr
->execute_all_testcases();
307 else TTCN_error("Module %s does not exist.", module_name
);
310 void Module_List::print_version()
313 "Module name Language Compilation time MD5 checksum "
315 "-------------------------------------------------------------------"
316 "--------------------\n", stderr
);
317 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
318 list_iter
= list_iter
->list_next
) list_iter
->print_version();
319 fputs("-------------------------------------------------------------------"
320 "--------------------\n", stderr
);
323 void Module_List::send_versions() {
325 std::set
<ModuleVersion
> versions
;
326 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
327 list_iter
= list_iter
->list_next
) {
328 ModuleVersion
* version
= list_iter
->get_version();
329 if (version
->hasProductNumber()) {
330 versions
.insert(*version
);
335 std::stringstream stream
;
337 for (std::set
<ModuleVersion
>::iterator it
= versions
.begin(); it
!= versions
.end(); ++it
) {
338 if (it
== versions
.begin()) {
339 stream
<< "&products=" << it
->toString();
341 stream
<< "," << it
->toString();
345 HttpSender
* sender
= new HttpSender
;
346 UsageData::getInstance().sendDataThreaded(stream
.str().c_str(), sender
);
351 void Module_List::list_testcases()
353 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
354 list_iter
= list_iter
->list_next
) list_iter
->list_testcases();
357 void Module_List::push_version(Text_Buf
& text_buf
)
360 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
361 list_iter
= list_iter
->list_next
) n_modules
++;
362 text_buf
.push_int(n_modules
);
363 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
364 list_iter
= list_iter
->list_next
) {
365 text_buf
.push_string(list_iter
->module_name
);
366 if (list_iter
->md5_checksum
!= NULL
) {
367 text_buf
.push_int(16);
368 text_buf
.push_raw(16, list_iter
->md5_checksum
);
369 } else text_buf
.push_int((RInt
)0);
373 void Module_List::encode_function(Text_Buf
& text_buf
,
374 genericfunc_t function_address
)
376 if (function_address
== NULL
)
377 TTCN_error("Text encoder: Encoding an unbound function reference.");
378 else if (function_address
== fat_null
) text_buf
.push_string("");
380 const char *module_name
, *function_name
;
381 if (lookup_function_by_address(function_address
, module_name
,
383 text_buf
.push_string(module_name
);
384 text_buf
.push_string(function_name
);
385 } else TTCN_error("Text encoder: Encoding function reference %p, "
386 "which does not point to a valid function.",
387 (void*)(unsigned long)function_address
);
391 void Module_List::decode_function(Text_Buf
& text_buf
,
392 genericfunc_t
*function_addr_ptr
)
394 char *module_name
= text_buf
.pull_string();
395 if (module_name
[0] != '\0') {
396 TTCN_Module
* module_ptr
= lookup_module(module_name
);
397 if (module_ptr
== NULL
) {
399 TTCN_error("Text decoder: Module %s does not exist when trying "
400 "to decode a function reference.", module_name
);
402 // to prevent from memory leaks
403 delete [] module_name
;
407 char *function_name
= text_buf
.pull_string();
408 genericfunc_t function_address
=
409 module_ptr
->get_function_address_by_name(function_name
);
410 if (function_address
!= NULL
) *function_addr_ptr
= function_address
;
413 TTCN_error("Text decoder: Reference to non-existent function "
414 "%s.%s was received.", module_name
, function_name
);
416 // to prevent from memory leaks
417 delete [] module_name
;
418 delete [] function_name
;
422 delete [] function_name
;
423 } else *function_addr_ptr
= fat_null
;
424 delete [] module_name
;
427 void Module_List::log_function(genericfunc_t function_address
)
429 if (function_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
430 else if (function_address
== fat_null
) TTCN_Logger::log_event_str("null");
432 const char *module_name
, *function_name
;
433 if (lookup_function_by_address(function_address
, module_name
,
434 function_name
)) TTCN_Logger::log_event("refers(%s.%s)",
435 module_name
, function_name
);
436 else TTCN_Logger::log_event("<invalid function reference: %p>",
437 (void*)(unsigned long)function_address
);
441 void Module_List::encode_altstep(Text_Buf
& text_buf
,
442 genericfunc_t altstep_address
)
444 if (altstep_address
== NULL
)
445 TTCN_error("Text encoder: Encoding an unbound altstep reference.");
446 else if (altstep_address
== fat_null
) text_buf
.push_string("");
448 const char *module_name
, *altstep_name
;
449 if (lookup_altstep_by_address(altstep_address
, module_name
,
451 text_buf
.push_string(module_name
);
452 text_buf
.push_string(altstep_name
);
453 } else TTCN_error("Text encoder: Encoding altstep reference %p, "
454 "which does not point to a valid altstep.",
455 (void*)(unsigned long)altstep_address
);
459 void Module_List::decode_altstep(Text_Buf
& text_buf
,
460 genericfunc_t
*altstep_addr_ptr
)
462 char *module_name
= text_buf
.pull_string();
463 if (module_name
[0] != '\0') {
464 TTCN_Module
* module_ptr
= lookup_module(module_name
);
465 if (module_ptr
== NULL
) {
467 TTCN_error("Text decoder: Module %s does not exist when trying "
468 "to decode an altstep reference.", module_name
);
470 // to prevent from memory leaks
471 delete [] module_name
;
475 char *altstep_name
= text_buf
.pull_string();
476 genericfunc_t altstep_address
=
477 module_ptr
->get_altstep_address_by_name(altstep_name
);
478 if (altstep_address
!= NULL
) *altstep_addr_ptr
= altstep_address
;
481 TTCN_error("Text decoder: Reference to non-existent altstep "
482 "%s.%s was received.", module_name
, altstep_name
);
484 // to prevent from memory leaks
485 delete [] module_name
;
486 delete [] altstep_name
;
490 delete [] altstep_name
;
491 } else *altstep_addr_ptr
= fat_null
;
492 delete [] module_name
;
495 void Module_List::log_altstep(genericfunc_t altstep_address
)
497 if (altstep_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
498 else if (altstep_address
== fat_null
) TTCN_Logger::log_event_str("null");
500 const char *module_name
, *altstep_name
;
501 if (lookup_altstep_by_address(altstep_address
, module_name
,
502 altstep_name
)) TTCN_Logger::log_event("refers(%s.%s)",
503 module_name
, altstep_name
);
504 else TTCN_Logger::log_event("<invalid altstep reference: %p>",
505 (void*)(unsigned long)altstep_address
);
509 // called by testcase_name::encode_text in the generated code
510 void Module_List::encode_testcase(Text_Buf
& text_buf
,
511 genericfunc_t testcase_address
)
513 if (testcase_address
== NULL
)
514 TTCN_error("Text encoder: Encoding an unbound testcase reference.");
515 else if (testcase_address
== fat_null
) text_buf
.push_string("");
517 const char *module_name
, *testcase_name
;
518 if (lookup_testcase_by_address(testcase_address
, module_name
,
520 text_buf
.push_string(module_name
);
521 text_buf
.push_string(testcase_name
);
522 } else TTCN_error("Text encoder: Encoding testcase reference %p, "
523 "which does not point to a valid testcase.",
524 (void*)(unsigned long)testcase_address
);
528 // called by testcase_name::decode_text in the generated code
529 void Module_List::decode_testcase(Text_Buf
& text_buf
,
530 genericfunc_t
*testcase_addr_ptr
)
532 char *module_name
= text_buf
.pull_string();
533 if (module_name
[0] != '\0') {
534 TTCN_Module
* module_ptr
= lookup_module(module_name
);
535 if (module_ptr
== NULL
) {
537 TTCN_error("Text decoder: Module %s does not exist when trying "
538 "to decode a testcase reference.", module_name
);
540 // to prevent from memory leaks
541 delete [] module_name
;
545 char *testcase_name
= text_buf
.pull_string();
546 genericfunc_t testcase_address
=
547 module_ptr
->get_testcase_address_by_name(testcase_name
);
548 if (testcase_address
!= NULL
) *testcase_addr_ptr
= testcase_address
;
551 TTCN_error("Text decoder: Reference to non-existent testcase "
552 "%s.%s was received.", module_name
, testcase_name
);
554 // to prevent from memory leaks
555 delete [] module_name
;
556 delete [] testcase_name
;
560 delete [] testcase_name
;
561 } else *testcase_addr_ptr
= fat_null
;
562 delete [] module_name
;
565 void Module_List::log_testcase(genericfunc_t testcase_address
)
567 if (testcase_address
== NULL
) TTCN_Logger::log_event_str("<unbound>");
568 else if (testcase_address
== fat_null
) TTCN_Logger::log_event_str("null");
570 const char *module_name
, *testcase_name
;
571 if (lookup_testcase_by_address(testcase_address
, module_name
,
572 testcase_name
)) TTCN_Logger::log_event("refers(%s.%s)",
573 module_name
, testcase_name
);
574 else TTCN_Logger::log_event("<invalid testcase reference: %p>",
575 (void*)(unsigned long)testcase_address
);
579 genericfunc_t
Module_List::get_fat_null()
584 genericfunc_t
Module_List::lookup_start_by_function_address(
585 genericfunc_t function_address
)
587 if (function_address
== NULL
) TTCN_error("Performing a start test "
588 "component operation with an unbound function reference.");
589 else if (function_address
== fat_null
) TTCN_error("Start test component "
590 "operation cannot be performed with a null function reference.");
591 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
592 list_iter
= list_iter
->list_next
) {
593 genericfunc_t function_start
=
594 list_iter
->get_function_start_by_address(function_address
);
595 if (function_start
!= NULL
) return function_start
;
597 TTCN_error("Function reference %p in start test component operation does "
598 "not point to a valid function.",
599 (void*)(unsigned long)function_address
);
604 genericfunc_t
Module_List::lookup_standalone_address_by_altstep_address(
605 genericfunc_t altstep_address
)
607 if (altstep_address
== NULL
) TTCN_error("Performing an invoke operation "
608 "on an unbound altstep reference.");
609 else if (altstep_address
== fat_null
) TTCN_error("Invoke operation "
610 "cannot be performed on a null altstep reference.");
611 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
612 list_iter
= list_iter
->list_next
) {
613 genericfunc_t standalone_address
, activate_address
;
614 if (list_iter
->get_altstep_data_by_address(altstep_address
,
615 standalone_address
, activate_address
)) {
616 if (standalone_address
== NULL
)
617 TTCN_error("Internal error: Altstep reference %p cannot be "
618 "instantiated as a stand-alone alt statement.",
619 (void*)(unsigned long)altstep_address
);
620 return standalone_address
;
623 TTCN_error("Altstep reference %p in invoke operation does not point to a "
624 "valid altstep.", (void*)(unsigned long)altstep_address
);
629 genericfunc_t
Module_List::lookup_activate_address_by_altstep_address(
630 genericfunc_t altstep_address
)
632 if (altstep_address
== NULL
) TTCN_error("Performing an activate operation "
633 "on an unbound altstep reference.");
634 else if (altstep_address
== fat_null
) TTCN_error("Activate operation "
635 "cannot be performed on a null altstep reference.");
636 for (TTCN_Module
* list_iter
= list_head
; list_iter
!= NULL
;
637 list_iter
= list_iter
->list_next
) {
638 genericfunc_t standalone_address
, activate_address
;
639 if (list_iter
->get_altstep_data_by_address(altstep_address
,
640 standalone_address
, activate_address
)) {
641 if (activate_address
== NULL
)
642 TTCN_error("Internal error: Altstep reference %p cannot be "
643 "activated as a default.",
644 (void*)(unsigned long)altstep_address
);
645 return activate_address
;
648 TTCN_error("Altstep reference %p in activate operation does not point to "
649 "a valid altstep.", (void*)(unsigned long)altstep_address
);
654 boolean
Module_List::lookup_function_by_address(genericfunc_t function_address
,
655 const char*& module_name
, const char*& function_name
)
657 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
658 list_iter
= list_iter
->list_next
) {
660 list_iter
->get_function_name_by_address(function_address
);
661 if (function_name
!= NULL
) {
662 module_name
= list_iter
->module_name
;
669 boolean
Module_List::lookup_altstep_by_address(genericfunc_t altstep_address
,
670 const char*& module_name
, const char*& altstep_name
)
672 for (TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
673 list_iter
= list_iter
->list_next
) {
674 altstep_name
= list_iter
->get_altstep_name_by_address(altstep_address
);
675 if (altstep_name
!= NULL
) {
676 module_name
= list_iter
->module_name
;
683 boolean
Module_List::lookup_testcase_by_address(genericfunc_t testcase_address
,
684 const char*& module_name
, const char*& testcase_name
)
686 for(TTCN_Module
*list_iter
= list_head
; list_iter
!= NULL
;
687 list_iter
= list_iter
->list_next
) {
689 list_iter
->get_testcase_name_by_address(testcase_address
);
690 if (testcase_name
!= NULL
) {
691 module_name
= list_iter
->module_name
;
698 // ======================= TTCN_Module =======================
700 struct TTCN_Module::function_list_item
{
701 const char *function_name
;
702 genericfunc_t function_address
;
703 genericfunc_t start_address
;
704 function_list_item
*next_function
;
707 struct TTCN_Module::altstep_list_item
{
708 const char *altstep_name
;
709 genericfunc_t altstep_address
; //instance
710 genericfunc_t activate_address
;
711 genericfunc_t standalone_address
;
712 altstep_list_item
*next_altstep
;
715 struct TTCN_Module::testcase_list_item
{
716 const char *testcase_name
;
719 testcase_t testcase_function
;
720 genericfunc_t testcase_address
;
722 testcase_list_item
*next_testcase
;
725 /** Constructor for TTCN modules */
726 TTCN_Module::TTCN_Module(const char *par_module_name
,
727 const char *par_compilation_date
,
728 const char *par_compilation_time
,
729 const unsigned char *par_md5_checksum
,
730 init_func_t par_pre_init_func
,
731 const char* par_product_number
,
732 unsigned int par_suffix
,
733 unsigned int par_release
,
734 unsigned int par_patch
,
735 unsigned int par_build
,
736 const char* par_extra
,
737 size_t par_num_namespace
,
738 const namespace_t
*par_namespaces
,
739 init_func_t par_post_init_func
,
740 set_param_func_t par_set_param_func
,
741 get_param_func_t par_get_param_func
,
742 log_param_func_t par_log_param_func
,
743 initialize_component_func_t par_initialize_component_func
,
744 start_func_t par_start_func
,
745 control_func_t par_control_func
)
746 : list_prev(NULL
), list_next(NULL
)
747 , module_type(TTCN3_MODULE
)
748 , module_name(par_module_name
)
749 , compilation_date(par_compilation_date
)
750 , compilation_time(par_compilation_time
)
751 , md5_checksum(par_md5_checksum
)
752 , product_number(par_product_number
)
754 , release(par_release
)
758 , num_namespaces(par_num_namespace
)
759 , xer_namespaces(par_namespaces
)
760 , pre_init_func(par_pre_init_func
)
761 , post_init_func(par_post_init_func
)
762 , pre_init_called(FALSE
)
763 , post_init_called(FALSE
)
764 , set_param_func(par_set_param_func
)
765 , get_param_func(par_get_param_func
)
766 , log_param_func(par_log_param_func
)
767 , initialize_component_func(par_initialize_component_func
)
768 , start_func(par_start_func
)
769 , control_func(par_control_func
)
770 , function_head(NULL
)
771 , function_tail(NULL
)
774 , testcase_head(NULL
)
775 , testcase_tail(NULL
)
777 Module_List::add_module(this);
780 /** Constructor for ASN.1 modules */
781 TTCN_Module::TTCN_Module(const char *par_module_name
,
782 const char *par_compilation_date
,
783 const char *par_compilation_time
,
784 const unsigned char par_md5_checksum
[16],
785 init_func_t par_init_func
)
786 : list_prev(NULL
), list_next(NULL
)
787 , module_type(ASN1_MODULE
)
788 , module_name(par_module_name
)
789 , compilation_date(par_compilation_date
)
790 , compilation_time(par_compilation_time
)
791 , md5_checksum(par_md5_checksum
)
792 , product_number(NULL
)
799 , xer_namespaces(NULL
) // no EXER, no namespaces for ASN.1
800 , pre_init_func(par_init_func
)
801 , post_init_func(NULL
)
802 , pre_init_called(FALSE
)
803 , post_init_called(FALSE
)
804 , set_param_func(NULL
)
805 , get_param_func(NULL
)
806 , log_param_func(NULL
)
807 , initialize_component_func(NULL
)
810 , function_head(NULL
)
811 , function_tail(NULL
)
814 , testcase_head(NULL
)
815 , testcase_tail(NULL
)
817 Module_List::add_module(this);
820 /** Constructor for C++ modules (?) */
821 TTCN_Module::TTCN_Module(const char *par_module_name
,
822 const char *par_compilation_date
,
823 const char *par_compilation_time
,
824 init_func_t par_init_func
)
825 : list_prev(NULL
), list_next(NULL
)
826 , module_type(CPLUSPLUS_MODULE
)
827 , module_name(par_module_name
? par_module_name
: "<unknown>")
828 , compilation_date(par_compilation_date
? par_compilation_date
: "<unknown>")
829 , compilation_time(par_compilation_time
? par_compilation_time
: "<unknown>")
831 , product_number(NULL
)
838 , xer_namespaces(NULL
)
839 , pre_init_func(par_init_func
)
840 , post_init_func(NULL
)
841 , pre_init_called(FALSE
)
842 , post_init_called(FALSE
)
843 , set_param_func(NULL
)
844 , log_param_func(NULL
)
845 , initialize_component_func(NULL
)
848 , function_head(NULL
)
849 , function_tail(NULL
)
852 , testcase_head(NULL
)
853 , testcase_tail(NULL
)
855 Module_List::add_module(this);
858 TTCN_Module::~TTCN_Module()
860 Module_List::remove_module(this);
861 while (function_head
!= NULL
) {
862 function_list_item
*tmp_ptr
=function_head
->next_function
;
863 delete function_head
;
864 function_head
= tmp_ptr
;
866 while (altstep_head
!= NULL
) {
867 altstep_list_item
*tmp_ptr
=altstep_head
->next_altstep
;
869 altstep_head
= tmp_ptr
;
871 while (testcase_head
!= NULL
) {
872 testcase_list_item
*tmp_ptr
= testcase_head
->next_testcase
;
873 delete testcase_head
;
874 testcase_head
= tmp_ptr
;
878 void TTCN_Module::pre_init_module()
880 if (pre_init_called
) return;
881 pre_init_called
= TRUE
;
882 if (pre_init_func
== NULL
) return;
886 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED
,
887 "An error occurred while initializing the constants of module %s.",
893 void TTCN_Module::post_init_module()
895 if (post_init_called
) return;
896 post_init_called
= TRUE
;
897 TTCN_Logger::log_module_init(module_name
);
898 if (post_init_func
!= NULL
) post_init_func();
899 TTCN_Logger::log_module_init(module_name
, true);
902 void TTCN_Module::add_function(const char *function_name
,
903 genericfunc_t function_address
, genericfunc_t start_address
)
905 function_list_item
*new_item
= new function_list_item
;
906 new_item
->function_name
= function_name
;
907 new_item
->function_address
= function_address
;
908 new_item
->start_address
= start_address
;
909 new_item
->next_function
= NULL
;
910 if(function_head
== NULL
) function_head
= new_item
;
911 else function_tail
->next_function
= new_item
;
912 function_tail
= new_item
;
915 void TTCN_Module::add_altstep(const char *altstep_name
,
916 genericfunc_t altstep_address
, genericfunc_t activate_address
,
917 genericfunc_t standalone_address
)
919 altstep_list_item
*new_item
= new altstep_list_item
;
920 new_item
->altstep_name
= altstep_name
;
921 new_item
->altstep_address
= altstep_address
;
922 new_item
->activate_address
= activate_address
;
923 new_item
->standalone_address
= standalone_address
;
924 new_item
->next_altstep
= NULL
;
925 if(altstep_head
== NULL
) altstep_head
= new_item
;
926 else altstep_tail
->next_altstep
= new_item
;
927 altstep_tail
= new_item
;
930 void TTCN_Module::add_testcase_nonpard(const char *testcase_name
,
931 testcase_t testcase_function
)
933 testcase_list_item
*new_item
= new testcase_list_item
;
934 new_item
->testcase_name
= testcase_name
;
935 new_item
->is_pard
= FALSE
;
936 new_item
->testcase_function
= testcase_function
;
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::add_testcase_pard(const char *testcase_name
,
944 genericfunc_t testcase_address
)
946 testcase_list_item
*new_item
= new testcase_list_item
;
947 new_item
->testcase_name
= testcase_name
;
948 new_item
->is_pard
= TRUE
;
949 new_item
->testcase_address
= testcase_address
;
950 new_item
->next_testcase
= NULL
;
951 if(testcase_head
== NULL
) testcase_head
= new_item
;
952 else testcase_tail
->next_testcase
= new_item
;
953 testcase_tail
= new_item
;
956 void TTCN_Module::execute_testcase(const char *testcase_name
)
958 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
959 list_iter
= list_iter
->next_testcase
) {
960 if (!strcmp(list_iter
->testcase_name
, testcase_name
)) {
961 if (list_iter
->is_pard
) {
962 // Testcase has parameters. However, there might be a chance...
963 // Move to the next one (if any) and check that it has the same name.
964 list_iter
= list_iter
->next_testcase
;
965 if (list_iter
== NULL
966 || strcmp(list_iter
->testcase_name
, testcase_name
)) {
967 TTCN_error("Test case %s in module %s "
968 "cannot be executed individually (without control part) "
969 "because it has parameters.", testcase_name
, module_name
);
970 continue; // not reached
972 // else it has the same name, fall through
975 list_iter
->testcase_function(FALSE
, 0.0);
979 TTCN_error("Test case %s does not exist in module %s.", testcase_name
,
983 void TTCN_Module::execute_all_testcases()
985 boolean found
= FALSE
;
986 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
987 list_iter
= list_iter
->next_testcase
) {
988 if (!list_iter
->is_pard
) {
989 list_iter
->testcase_function(FALSE
, 0.0);
994 if (testcase_head
!= NULL
) TTCN_warning("Module %s does not contain "
995 "non-parameterized test cases, which can be executed individually "
996 "without control part.", module_name
);
997 else TTCN_warning("Module %s does not contain test cases.",
1002 const char *TTCN_Module::get_function_name_by_address(
1003 genericfunc_t function_address
)
1005 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
1006 list_iter
= list_iter
->next_function
)
1007 if (list_iter
->function_address
== function_address
)
1008 return list_iter
->function_name
;
1012 genericfunc_t
TTCN_Module::get_function_address_by_name(const char *func_name
)
1014 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
1015 list_iter
= list_iter
->next_function
)
1016 if (!strcmp(list_iter
->function_name
, func_name
))
1017 return list_iter
->function_address
;
1021 genericfunc_t
TTCN_Module::get_function_start_by_address(
1022 genericfunc_t function_address
)
1024 for (function_list_item
*list_iter
= function_head
; list_iter
!= NULL
;
1025 list_iter
= list_iter
->next_function
) {
1026 if (list_iter
->function_address
== function_address
) {
1027 if (list_iter
->start_address
!= NULL
)
1028 return list_iter
->start_address
;
1029 else TTCN_error("Function %s.%s cannot be started on a parallel "
1030 "test component.", module_name
, list_iter
->function_name
);
1036 const char *TTCN_Module::get_altstep_name_by_address(
1037 genericfunc_t altstep_address
)
1039 for(altstep_list_item
*list_iter
= altstep_head
; list_iter
!= NULL
;
1040 list_iter
= list_iter
->next_altstep
) {
1041 if (list_iter
->altstep_address
== altstep_address
)
1042 return list_iter
->altstep_name
;
1047 genericfunc_t
TTCN_Module::get_altstep_address_by_name(const char* altstep_name
)
1049 for(altstep_list_item
*list_iter
= altstep_head
; list_iter
!= NULL
;
1050 list_iter
= list_iter
->next_altstep
) {
1051 if (!strcmp(list_iter
->altstep_name
, altstep_name
))
1052 return list_iter
->altstep_address
;
1057 boolean
TTCN_Module::get_altstep_data_by_address(genericfunc_t altstep_address
,
1058 genericfunc_t
& standalone_address
, genericfunc_t
& activate_address
)
1060 for(altstep_list_item
* list_iter
= altstep_head
; list_iter
!= NULL
;
1061 list_iter
= list_iter
->next_altstep
) {
1062 if (list_iter
->altstep_address
== altstep_address
) {
1063 standalone_address
= list_iter
->standalone_address
;
1064 activate_address
= list_iter
->activate_address
;
1071 const char *TTCN_Module::get_testcase_name_by_address(
1072 genericfunc_t testcase_address
)
1074 for(testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1075 list_iter
= list_iter
->next_testcase
) {
1076 if (list_iter
->is_pard
) {
1077 if (list_iter
->testcase_address
== testcase_address
)
1078 return list_iter
->testcase_name
;
1080 if ((genericfunc_t
)list_iter
->testcase_function
== testcase_address
)
1081 return list_iter
->testcase_name
;
1087 genericfunc_t
TTCN_Module::get_testcase_address_by_name(const char *testcase_name
)
1089 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1090 list_iter
= list_iter
->next_testcase
) {
1091 if (!strcmp(list_iter
->testcase_name
, testcase_name
)) {
1092 if (!list_iter
->is_pard
) return list_iter
->testcase_address
;
1093 else return (genericfunc_t
)list_iter
->testcase_function
;
1099 ModuleVersion
* TTCN_Module::get_version() const {
1100 return new ModuleVersion(product_number
, suffix
, release
, patch
, build
, extra
);
1103 void TTCN_Module::print_version()
1105 const char *type_str
;
1106 switch (module_type
) {
1108 type_str
= "TTCN-3";
1113 case CPLUSPLUS_MODULE
:
1120 fprintf(stderr
, "%-18s %-6s ", module_name
, type_str
);
1121 if (compilation_date
!= NULL
&& compilation_time
!= NULL
) {
1122 fprintf(stderr
, "%s %s", compilation_date
, compilation_time
);
1124 fputs("<unknown> ", stderr
);
1126 if (md5_checksum
!= NULL
) {
1128 for (int i
= 0; i
< 16; i
++) fprintf(stderr
, "%02x", md5_checksum
[i
]);
1130 // else it's likely not a TTCN module, so no version info
1132 putc(' ', stderr
); // separator for the version number
1133 if (product_number
!= NULL
) {
1134 fprintf(stderr
, "%s", product_number
);
1136 fprintf(stderr
, "/%d", suffix
);
1140 // release can be between 0 and 999999 inclusive
1141 // patch can go from 0 to 26 (English alphabet) - 6 (IOPQRW forbidden)
1142 // build can be between 0 and 99 inclusive
1143 if (release
<= 999999 && patch
<= ('Z'-'A'-6) && build
<= 99) {
1144 char *build_str
= buildstr(build
);
1145 if (build_str
== 0) TTCN_error("TTCN_Module::print_version()");
1146 if (extra
!= NULL
) {
1147 build_str
= mputprintf(build_str
, "%s", extra
);
1149 fprintf(stderr
, "R%u%c%-4s", release
, eri(patch
), build_str
);
1155 void TTCN_Module::list_testcases()
1157 if (control_func
!= NULL
) printf("%s.control\n", module_name
);
1158 for (testcase_list_item
*list_iter
= testcase_head
; list_iter
!= NULL
;
1159 list_iter
= list_iter
->next_testcase
)
1160 if(!list_iter
->is_pard
)
1161 printf("%s.%s\n", module_name
, list_iter
->testcase_name
);
1164 const namespace_t
*TTCN_Module::get_ns(size_t p_index
) const
1166 if (p_index
== (size_t)-1) return NULL
;
1167 if (p_index
>= num_namespaces
) TTCN_error(
1168 "Index overflow for namespaces, %lu instead of %lu",
1169 (unsigned long)p_index
, (unsigned long)num_namespaces
);
1171 return xer_namespaces
+ p_index
;
1174 const namespace_t
*TTCN_Module::get_controlns() const
1176 if (xer_namespaces
==NULL
) {
1177 TTCN_error("No namespaces for module %s", module_name
);
1179 if (xer_namespaces
[num_namespaces
].px
== NULL
1180 ||xer_namespaces
[num_namespaces
].px
[0] == '\0') {
1181 TTCN_error("No control namespace for module %s", module_name
);
1183 return xer_namespaces
+num_namespaces
;