Update README.linux
[deliverable/titan.core.git] / core / Module_list.cc
CommitLineData
970ed795
EL
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///////////////////////////////////////////////////////////////////////////////
8#include <set>
9#include <sstream>
10#include <string>
11
12#include "Module_list.hh"
13#include "Logger.hh"
14#include "Error.hh"
15#include "Textbuf.hh"
16#include "Types.h"
17#include "Param_Types.hh"
18#include "Basetype.hh"
19#include "Encdec.hh"
20
21#include "../common/ModuleVersion.hh"
22#ifdef USAGE_STATS
23#include "../common/usage_stats.hh"
24#endif
25
26#include "../common/dbgnew.hh"
27
28#include <stdio.h>
29#include <string.h>
30#include <limits.h>
31
32TTCN_Module *Module_List::list_head = NULL, *Module_List::list_tail = NULL;
33
34void fat_null() {}
35
36void Module_List::add_module(TTCN_Module *module_ptr)
37{
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)
42 break;
43 list_iter = list_iter->list_next;
44 }
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;
51 } else {
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;
56 }
57 module_ptr->list_next = list_iter;
58 if (list_iter == list_head) list_head = module_ptr;
59 }
60}
61
62void Module_List::remove_module(TTCN_Module *module_ptr)
63{
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;
68
69 module_ptr->list_prev = NULL;
70 module_ptr->list_next = NULL;
71}
72
73TTCN_Module *Module_List::lookup_module(const char *module_name)
74{
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;
78 return NULL;
79}
80
81TTCN_Module *Module_List::single_control_part()
82{
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;
89 }
90 return retval;
91}
92
93
94void Module_List::pre_init_modules()
95{
96 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
97 list_iter = list_iter->list_next) list_iter->pre_init_module();
970ed795
EL
98}
99
100void Module_List::post_init_modules()
101{
102 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
103 list_iter = list_iter->list_next) list_iter->post_init_called = FALSE;
104 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
105 list_iter = list_iter->list_next) list_iter->post_init_module();
106}
107
108void Module_List::start_function(const char *module_name,
109 const char *function_name, Text_Buf& function_arguments)
110{
111 TTCN_Module *module_ptr = lookup_module(module_name);
112 if (module_ptr == NULL) {
113 // the START message must be dropped here
114 function_arguments.cut_message();
115 TTCN_error("Internal error: Module %s does not exist.", module_name);
116 } else if (module_ptr->start_func == NULL) {
117 // the START message must be dropped here
118 function_arguments.cut_message();
119 TTCN_error("Internal error: Module %s does not have startable "
120 "functions.", module_name);
121 } else if (!module_ptr->start_func(function_name, function_arguments)) {
122 // the START message must be dropped here
123 function_arguments.cut_message();
124 TTCN_error("Internal error: Startable function %s does not exist in "
125 "module %s.", function_name, module_name);
126 }
127}
128
129void Module_List::initialize_component(const char *module_name,
130 const char *component_type, boolean init_base_comps)
131{
132 TTCN_Module *module_ptr = lookup_module(module_name);
133 if (module_ptr == NULL)
134 TTCN_error("Internal error: Module %s does not exist.", module_name);
135 else if (module_ptr->initialize_component_func == NULL)
136 TTCN_error("Internal error: Module %s does not have component types.",
137 module_name);
138 else if (!module_ptr->initialize_component_func(component_type,
139 init_base_comps))
140 TTCN_error("Internal error: Component type %s does not exist in "
141 "module %s.", component_type, module_name);
142}
143
144void Module_List::set_param(Module_Param& param)
145{
146 // The first segment in the parameter name can either be the module name,
147 // or the module parameter name - both must be checked
148 const char* const first_name = param.get_id()->get_current_name();
149 const char* second_name = NULL;
150 boolean param_found = FALSE;
151
152 // Check if the first name segment is an existing module name
153 TTCN_Module *module_ptr = lookup_module(first_name);
154 if (module_ptr != NULL && module_ptr->set_param_func != NULL && param.get_id()->next_name()) {
155 param_found = module_ptr->set_param_func(param);
156 if (!param_found) {
157 second_name = param.get_id()->get_current_name(); // for error messages
158 }
159 }
160
161 // If not found, check if the first name segment was the module parameter name
162 // (even if it matched a module name)
163 if (!param_found) {
164 param.get_id()->next_name(-1); // set the position back to the first segment
165 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
166 list_iter = list_iter->list_next) {
167 if (list_iter->set_param_func != NULL &&
168 list_iter->set_param_func(param)) {
169 param_found = TRUE;
170 }
171 }
172 }
173
174 // Still not found -> error
175 if (!param_found) {
176 if (module_ptr == NULL) {
177 param.error("Module parameter cannot be set, because module `%s' does not exist, "
178 "and no parameter with name `%s' exists in any module.",
179 first_name, first_name);
180 } else if (module_ptr->set_param_func == NULL) {
181 param.error("Module parameter cannot be set, because module `%s' does not have "
182 "parameters, and no parameter with name `%s' exists in other modules.",
183 first_name, first_name);
184 } else {
185 param.error("Module parameter cannot be set, because no parameter with name `%s' "
186 "exists in module `%s', and no parameter with name `%s' exists in any module.",
187 second_name, first_name, first_name);
188 }
189 }
190}
191
192void Module_List::log_param()
193{
194 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
195 list_iter = list_iter->list_next) {
196 if (list_iter->log_param_func != NULL) {
197 TTCN_Logger::begin_event(TTCN_Logger::EXECUTOR_CONFIGDATA);
198 TTCN_Logger::log_event("Module %s has the following parameters: "
199 "{ ", list_iter->module_name);
200 list_iter->log_param_func();
201 TTCN_Logger::log_event_str(" }");
202 TTCN_Logger::end_event();
203 }
204 }
205}
206
207void Module_List::execute_control(const char *module_name)
208{
209 TTCN_Module *module_ptr = lookup_module(module_name);
210 if (module_ptr != NULL) {
211 if (module_ptr->control_func != NULL) {
212 try {
213 module_ptr->control_func();
214 } catch (const TC_Error& tc_error) {
215 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED,
216 "Unrecoverable error in control part of module %s. Execution aborted.",
217 module_name);
218 } catch (const TC_End& tc_end) {
219 TTCN_Logger::log(TTCN_Logger::FUNCTION_UNQUALIFIED,
220 "Control part of module %s was stopped.", module_name);
221 }
222 } else TTCN_error("Module %s does not have control part.", module_name);
223 } else TTCN_error("Module %s does not exist.", module_name);
224}
225
226void Module_List::execute_testcase(const char *module_name,
227 const char *testcase_name)
228{
229 TTCN_Module *module_ptr = lookup_module(module_name);
230 if (module_ptr != NULL) module_ptr->execute_testcase(testcase_name);
231 else TTCN_error("Module %s does not exist.", module_name);
232}
233
234void Module_List::execute_all_testcases(const char *module_name)
235{
236 TTCN_Module *module_ptr = lookup_module(module_name);
237 if (module_ptr != NULL) module_ptr->execute_all_testcases();
238 else TTCN_error("Module %s does not exist.", module_name);
239}
240
241void Module_List::print_version()
242{
243 fputs(
244 "Module name Language Compilation time MD5 checksum "
245 " Version\n"
246 "-------------------------------------------------------------------"
247 "--------------------\n", stderr);
248 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
249 list_iter = list_iter->list_next) list_iter->print_version();
250 fputs("-------------------------------------------------------------------"
251 "--------------------\n", stderr);
252}
253
254void Module_List::send_versions() {
255#ifdef USAGE_STATS
256 std::set<ModuleVersion> versions;
257 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
258 list_iter = list_iter->list_next) {
259 ModuleVersion* version = list_iter->get_version();
260 if (version->hasProductNumber()) {
261 versions.insert(*version);
262 }
263 delete version;
264 }
265
266 std::stringstream stream;
267 stream << "runtime";
268 for (std::set<ModuleVersion>::iterator it = versions.begin(); it != versions.end(); ++it) {
269 if (it == versions.begin()) {
270 stream << "&products=" << it->toString();
271 } else {
272 stream << "," << it->toString();
273 }
274 }
275
276 HttpSender* sender = new HttpSender;
277 UsageData::getInstance().sendDataThreaded(stream.str().c_str(), sender);
278#endif
279}
280
281
282void Module_List::list_testcases()
283{
284 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
285 list_iter = list_iter->list_next) list_iter->list_testcases();
286}
287
288void Module_List::push_version(Text_Buf& text_buf)
289{
290 int n_modules = 0;
291 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
292 list_iter = list_iter->list_next) n_modules++;
293 text_buf.push_int(n_modules);
294 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
295 list_iter = list_iter->list_next) {
296 text_buf.push_string(list_iter->module_name);
297 if (list_iter->md5_checksum != NULL) {
298 text_buf.push_int(16);
299 text_buf.push_raw(16, list_iter->md5_checksum);
300 } else text_buf.push_int((RInt)0);
301 }
302}
303
304void Module_List::encode_function(Text_Buf& text_buf,
305 genericfunc_t function_address)
306{
307 if (function_address == NULL)
308 TTCN_error("Text encoder: Encoding an unbound function reference.");
309 else if (function_address == fat_null) text_buf.push_string("");
310 else {
311 const char *module_name, *function_name;
312 if (lookup_function_by_address(function_address, module_name,
313 function_name)) {
314 text_buf.push_string(module_name);
315 text_buf.push_string(function_name);
316 } else TTCN_error("Text encoder: Encoding function reference %p, "
317 "which does not point to a valid function.",
318 (void*)(unsigned long)function_address);
319 }
320}
321
322void Module_List::decode_function(Text_Buf& text_buf,
323 genericfunc_t *function_addr_ptr)
324{
325 char *module_name = text_buf.pull_string();
326 if (module_name[0] != '\0') {
327 TTCN_Module* module_ptr = lookup_module(module_name);
328 if (module_ptr == NULL) {
329 try {
330 TTCN_error("Text decoder: Module %s does not exist when trying "
331 "to decode a function reference.", module_name);
332 } catch (...) {
333 // to prevent from memory leaks
334 delete [] module_name;
335 throw;
336 }
337 }
338 char *function_name = text_buf.pull_string();
339 genericfunc_t function_address =
340 module_ptr->get_function_address_by_name(function_name);
341 if (function_address != NULL) *function_addr_ptr = function_address;
342 else {
343 try {
344 TTCN_error("Text decoder: Reference to non-existent function "
345 "%s.%s was received.", module_name, function_name);
346 } catch (...) {
347 // to prevent from memory leaks
348 delete [] module_name;
349 delete [] function_name;
350 throw;
351 }
352 }
353 delete [] function_name;
354 } else *function_addr_ptr = fat_null;
355 delete [] module_name;
356}
357
358void Module_List::log_function(genericfunc_t function_address)
359{
360 if (function_address == NULL) TTCN_Logger::log_event_str("<unbound>");
361 else if (function_address == fat_null) TTCN_Logger::log_event_str("null");
362 else {
363 const char *module_name, *function_name;
364 if (lookup_function_by_address(function_address, module_name,
365 function_name)) TTCN_Logger::log_event("refers(%s.%s)",
366 module_name, function_name);
367 else TTCN_Logger::log_event("<invalid function reference: %p>",
368 (void*)(unsigned long)function_address);
369 }
370}
371
372void Module_List::encode_altstep(Text_Buf& text_buf,
373 genericfunc_t altstep_address)
374{
375 if (altstep_address == NULL)
376 TTCN_error("Text encoder: Encoding an unbound altstep reference.");
377 else if (altstep_address == fat_null) text_buf.push_string("");
378 else {
379 const char *module_name, *altstep_name;
380 if (lookup_altstep_by_address(altstep_address, module_name,
381 altstep_name)) {
382 text_buf.push_string(module_name);
383 text_buf.push_string(altstep_name);
384 } else TTCN_error("Text encoder: Encoding altstep reference %p, "
385 "which does not point to a valid altstep.",
386 (void*)(unsigned long)altstep_address);
387 }
388}
389
390void Module_List::decode_altstep(Text_Buf& text_buf,
391 genericfunc_t *altstep_addr_ptr)
392{
393 char *module_name = text_buf.pull_string();
394 if (module_name[0] != '\0') {
395 TTCN_Module* module_ptr = lookup_module(module_name);
396 if (module_ptr == NULL) {
397 try {
398 TTCN_error("Text decoder: Module %s does not exist when trying "
399 "to decode an altstep reference.", module_name);
400 } catch (...) {
401 // to prevent from memory leaks
402 delete [] module_name;
403 throw;
404 }
405 }
406 char *altstep_name = text_buf.pull_string();
407 genericfunc_t altstep_address =
408 module_ptr->get_altstep_address_by_name(altstep_name);
409 if (altstep_address != NULL) *altstep_addr_ptr = altstep_address;
410 else {
411 try {
412 TTCN_error("Text decoder: Reference to non-existent altstep "
413 "%s.%s was received.", module_name, altstep_name);
414 } catch (...) {
415 // to prevent from memory leaks
416 delete [] module_name;
417 delete [] altstep_name;
418 throw;
419 }
420 }
421 delete [] altstep_name;
422 } else *altstep_addr_ptr = fat_null;
423 delete [] module_name;
424}
425
426void Module_List::log_altstep(genericfunc_t altstep_address)
427{
428 if (altstep_address == NULL) TTCN_Logger::log_event_str("<unbound>");
429 else if (altstep_address == fat_null) TTCN_Logger::log_event_str("null");
430 else {
431 const char *module_name, *altstep_name;
432 if (lookup_altstep_by_address(altstep_address, module_name,
433 altstep_name)) TTCN_Logger::log_event("refers(%s.%s)",
434 module_name, altstep_name);
435 else TTCN_Logger::log_event("<invalid altstep reference: %p>",
436 (void*)(unsigned long)altstep_address);
437 }
438}
439
440// called by testcase_name::encode_text in the generated code
441void Module_List::encode_testcase(Text_Buf& text_buf,
442 genericfunc_t testcase_address)
443{
444 if (testcase_address == NULL)
445 TTCN_error("Text encoder: Encoding an unbound testcase reference.");
446 else if (testcase_address == fat_null) text_buf.push_string("");
447 else {
448 const char *module_name, *testcase_name;
449 if (lookup_testcase_by_address(testcase_address, module_name,
450 testcase_name)) {
451 text_buf.push_string(module_name);
452 text_buf.push_string(testcase_name);
453 } else TTCN_error("Text encoder: Encoding testcase reference %p, "
454 "which does not point to a valid testcase.",
455 (void*)(unsigned long)testcase_address);
456 }
457}
458
459// called by testcase_name::decode_text in the generated code
460void Module_List::decode_testcase(Text_Buf& text_buf,
461 genericfunc_t *testcase_addr_ptr)
462{
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) {
467 try {
468 TTCN_error("Text decoder: Module %s does not exist when trying "
469 "to decode a testcase reference.", module_name);
470 } catch (...) {
471 // to prevent from memory leaks
472 delete [] module_name;
473 throw;
474 }
475 }
476 char *testcase_name = text_buf.pull_string();
477 genericfunc_t testcase_address =
478 module_ptr->get_testcase_address_by_name(testcase_name);
479 if (testcase_address != NULL) *testcase_addr_ptr = testcase_address;
480 else {
481 try {
482 TTCN_error("Text decoder: Reference to non-existent testcase "
483 "%s.%s was received.", module_name, testcase_name);
484 } catch (...) {
485 // to prevent from memory leaks
486 delete [] module_name;
487 delete [] testcase_name;
488 throw;
489 }
490 }
491 delete [] testcase_name;
492 } else *testcase_addr_ptr = fat_null;
493 delete [] module_name;
494}
495
496void Module_List::log_testcase(genericfunc_t testcase_address)
497{
498 if (testcase_address == NULL) TTCN_Logger::log_event_str("<unbound>");
499 else if (testcase_address == fat_null) TTCN_Logger::log_event_str("null");
500 else {
501 const char *module_name, *testcase_name;
502 if (lookup_testcase_by_address(testcase_address, module_name,
503 testcase_name)) TTCN_Logger::log_event("refers(%s.%s)",
504 module_name, testcase_name);
505 else TTCN_Logger::log_event("<invalid testcase reference: %p>",
506 (void*)(unsigned long)testcase_address);
507 }
508}
509
510genericfunc_t Module_List::get_fat_null()
511{
512 return fat_null;
513}
514
515genericfunc_t Module_List::lookup_start_by_function_address(
516 genericfunc_t function_address)
517{
518 if (function_address == NULL) TTCN_error("Performing a start test "
519 "component operation with an unbound function reference.");
520 else if (function_address == fat_null) TTCN_error("Start test component "
521 "operation cannot be performed with a null function reference.");
522 for (TTCN_Module* list_iter = list_head; list_iter != NULL;
523 list_iter = list_iter->list_next) {
524 genericfunc_t function_start =
525 list_iter->get_function_start_by_address(function_address);
526 if (function_start != NULL) return function_start;
527 }
528 TTCN_error("Function reference %p in start test component operation does "
529 "not point to a valid function.",
530 (void*)(unsigned long)function_address);
531 // to avoid warnings
532 return NULL;
533}
534
535genericfunc_t Module_List::lookup_standalone_address_by_altstep_address(
536 genericfunc_t altstep_address)
537{
538 if (altstep_address == NULL) TTCN_error("Performing an invoke operation "
539 "on an unbound altstep reference.");
540 else if (altstep_address == fat_null) TTCN_error("Invoke operation "
541 "cannot be performed on a null altstep reference.");
542 for (TTCN_Module* list_iter = list_head; list_iter != NULL;
543 list_iter = list_iter->list_next) {
544 genericfunc_t standalone_address, activate_address;
545 if (list_iter->get_altstep_data_by_address(altstep_address,
546 standalone_address, activate_address)) {
547 if (standalone_address == NULL)
548 TTCN_error("Internal error: Altstep reference %p cannot be "
549 "instantiated as a stand-alone alt statement.",
550 (void*)(unsigned long)altstep_address);
551 return standalone_address;
552 }
553 }
554 TTCN_error("Altstep reference %p in invoke operation does not point to a "
555 "valid altstep.", (void*)(unsigned long)altstep_address);
556 // to avoid warnings
557 return NULL;
558}
559
560genericfunc_t Module_List::lookup_activate_address_by_altstep_address(
561 genericfunc_t altstep_address)
562{
563 if (altstep_address == NULL) TTCN_error("Performing an activate operation "
564 "on an unbound altstep reference.");
565 else if (altstep_address == fat_null) TTCN_error("Activate operation "
566 "cannot be performed on a null altstep reference.");
567 for (TTCN_Module* list_iter = list_head; list_iter != NULL;
568 list_iter = list_iter->list_next) {
569 genericfunc_t standalone_address, activate_address;
570 if (list_iter->get_altstep_data_by_address(altstep_address,
571 standalone_address, activate_address)) {
572 if (activate_address == NULL)
573 TTCN_error("Internal error: Altstep reference %p cannot be "
574 "activated as a default.",
575 (void*)(unsigned long)altstep_address);
576 return activate_address;
577 }
578 }
579 TTCN_error("Altstep reference %p in activate operation does not point to "
580 "a valid altstep.", (void*)(unsigned long)altstep_address);
581 // to avoid warnings
582 return NULL;
583}
584
585boolean Module_List::lookup_function_by_address(genericfunc_t function_address,
586 const char*& module_name, const char*& function_name)
587{
588 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
589 list_iter = list_iter->list_next) {
590 function_name =
591 list_iter->get_function_name_by_address(function_address);
592 if (function_name != NULL) {
593 module_name = list_iter->module_name;
594 return TRUE;
595 }
596 }
597 return FALSE;
598}
599
600boolean Module_List::lookup_altstep_by_address(genericfunc_t altstep_address,
601 const char*& module_name, const char*& altstep_name)
602{
603 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
604 list_iter = list_iter->list_next) {
605 altstep_name = list_iter->get_altstep_name_by_address(altstep_address);
606 if (altstep_name != NULL) {
607 module_name = list_iter->module_name;
608 return TRUE;
609 }
610 }
611 return FALSE;
612}
613
614boolean Module_List::lookup_testcase_by_address(genericfunc_t testcase_address,
615 const char*& module_name, const char*& testcase_name)
616{
617 for(TTCN_Module *list_iter = list_head; list_iter != NULL;
618 list_iter = list_iter->list_next) {
619 testcase_name =
620 list_iter->get_testcase_name_by_address(testcase_address);
621 if (testcase_name != NULL) {
622 module_name = list_iter->module_name;
623 return TRUE;
624 }
625 }
626 return FALSE;
627}
628
629// ======================= TTCN_Module =======================
630
631struct TTCN_Module::function_list_item {
632 const char *function_name;
633 genericfunc_t function_address;
634 genericfunc_t start_address;
635 function_list_item *next_function;
636};
637
638struct TTCN_Module::altstep_list_item {
639 const char *altstep_name;
640 genericfunc_t altstep_address; //instance
641 genericfunc_t activate_address;
642 genericfunc_t standalone_address;
643 altstep_list_item *next_altstep;
644};
645
646struct TTCN_Module::testcase_list_item {
647 const char *testcase_name;
648 boolean is_pard;
649 union {
650 testcase_t testcase_function;
651 genericfunc_t testcase_address;
652 };
653 testcase_list_item *next_testcase;
654};
655
656/** Constructor for TTCN modules */
657TTCN_Module::TTCN_Module(const char *par_module_name,
658 const char *par_compilation_date,
659 const char *par_compilation_time,
660 const unsigned char *par_md5_checksum,
661 init_func_t par_pre_init_func,
662 const char* par_product_number,
663 unsigned int par_suffix,
664 unsigned int par_release,
665 unsigned int par_patch,
666 unsigned int par_build,
667 const char* par_extra,
668 size_t par_num_namespace,
669 const namespace_t *par_namespaces,
670 init_func_t par_post_init_func,
671 set_param_func_t par_set_param_func,
672 log_param_func_t par_log_param_func,
673 initialize_component_func_t par_initialize_component_func,
674 start_func_t par_start_func,
675 control_func_t par_control_func)
676: list_prev(NULL), list_next(NULL)
677, module_type(TTCN3_MODULE)
678, module_name(par_module_name)
679, compilation_date(par_compilation_date)
680, compilation_time(par_compilation_time)
681, md5_checksum(par_md5_checksum)
682, product_number(par_product_number)
683, suffix(par_suffix)
684, release(par_release)
685, patch(par_patch)
686, build(par_build)
687, extra(par_extra)
688, num_namespaces(par_num_namespace)
689, xer_namespaces(par_namespaces)
690, pre_init_func(par_pre_init_func)
691, post_init_func(par_post_init_func)
692, pre_init_called(FALSE)
693, post_init_called(FALSE)
694, set_param_func(par_set_param_func)
695, log_param_func(par_log_param_func)
696, initialize_component_func(par_initialize_component_func)
697, start_func(par_start_func)
698, control_func(par_control_func)
699, function_head(NULL)
700, function_tail(NULL)
701, altstep_head(NULL)
702, altstep_tail(NULL)
703, testcase_head(NULL)
704, testcase_tail(NULL)
705{
706 Module_List::add_module(this);
707}
708
709/** Constructor for ASN.1 modules */
710TTCN_Module::TTCN_Module(const char *par_module_name,
711 const char *par_compilation_date,
712 const char *par_compilation_time,
713 const unsigned char par_md5_checksum[16],
714 init_func_t par_init_func)
715: list_prev(NULL), list_next(NULL)
716, module_type(ASN1_MODULE)
717, module_name(par_module_name)
718, compilation_date(par_compilation_date)
719, compilation_time(par_compilation_time)
720, md5_checksum(par_md5_checksum)
721, product_number(NULL)
722, suffix(0)
723, release(UINT_MAX)
724, patch(UINT_MAX)
725, build(UINT_MAX)
726, extra(NULL)
727, num_namespaces(0)
728, xer_namespaces(NULL) // no EXER, no namespaces for ASN.1
729, pre_init_func(par_init_func)
730, post_init_func(NULL)
731, pre_init_called(FALSE)
732, post_init_called(FALSE)
733, set_param_func(NULL)
734, log_param_func(NULL)
735, initialize_component_func(NULL)
736, start_func(NULL)
737, control_func(NULL)
738, function_head(NULL)
739, function_tail(NULL)
740, altstep_head(NULL)
741, altstep_tail(NULL)
742, testcase_head(NULL)
743, testcase_tail(NULL)
744{
745 Module_List::add_module(this);
746}
747
748/** Constructor for C++ modules (?) */
749TTCN_Module::TTCN_Module(const char *par_module_name,
750 const char *par_compilation_date,
751 const char *par_compilation_time,
752 init_func_t par_init_func)
753: list_prev(NULL), list_next(NULL)
754, module_type(CPLUSPLUS_MODULE)
755, module_name(par_module_name ? par_module_name : "<unknown>")
756, compilation_date(par_compilation_date ? par_compilation_date : "<unknown>")
757, compilation_time(par_compilation_time ? par_compilation_time : "<unknown>")
758, md5_checksum(NULL)
759, product_number(NULL)
760, suffix(0)
761, release(UINT_MAX)
762, patch(UINT_MAX)
763, build(UINT_MAX)
764, extra(NULL)
765, num_namespaces(0)
766, xer_namespaces(NULL)
767, pre_init_func(par_init_func)
768, post_init_func(NULL)
769, pre_init_called(FALSE)
770, post_init_called(FALSE)
771, set_param_func(NULL)
772, log_param_func(NULL)
773, initialize_component_func(NULL)
774, start_func(NULL)
775, control_func(NULL)
776, function_head(NULL)
777, function_tail(NULL)
778, altstep_head(NULL)
779, altstep_tail(NULL)
780, testcase_head(NULL)
781, testcase_tail(NULL)
782{
783 Module_List::add_module(this);
784 }
785
786TTCN_Module::~TTCN_Module()
787{
788 Module_List::remove_module(this);
789 while (function_head != NULL) {
790 function_list_item *tmp_ptr=function_head->next_function;
791 delete function_head;
792 function_head = tmp_ptr;
793 }
794 while (altstep_head != NULL) {
795 altstep_list_item *tmp_ptr=altstep_head->next_altstep;
796 delete altstep_head;
797 altstep_head = tmp_ptr;
798 }
799 while (testcase_head != NULL) {
800 testcase_list_item *tmp_ptr = testcase_head->next_testcase;
801 delete testcase_head;
802 testcase_head = tmp_ptr;
803 }
804}
805
806void TTCN_Module::pre_init_module()
807{
808 if (pre_init_called) return;
809 pre_init_called = TRUE;
810 if (pre_init_func == NULL) return;
811 try {
812 pre_init_func();
813 } catch (...) {
814 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED,
815 "An error occurred while initializing the constants of module %s.",
816 module_name);
817 throw;
818 }
819}
820
821void TTCN_Module::post_init_module()
822{
823 if (post_init_called) return;
824 post_init_called = TRUE;
825 TTCN_Logger::log_module_init(module_name);
826 if (post_init_func != NULL) post_init_func();
827 TTCN_Logger::log_module_init(module_name, true);
828}
829
830void TTCN_Module::add_function(const char *function_name,
831 genericfunc_t function_address, genericfunc_t start_address)
832{
833 function_list_item *new_item = new function_list_item;
834 new_item->function_name = function_name;
835 new_item->function_address = function_address;
836 new_item->start_address = start_address;
837 new_item->next_function = NULL;
838 if(function_head == NULL) function_head = new_item;
839 else function_tail->next_function = new_item;
840 function_tail = new_item;
841}
842
843void TTCN_Module::add_altstep(const char *altstep_name,
844 genericfunc_t altstep_address, genericfunc_t activate_address,
845 genericfunc_t standalone_address)
846{
847 altstep_list_item *new_item = new altstep_list_item;
848 new_item->altstep_name = altstep_name;
849 new_item->altstep_address = altstep_address;
850 new_item->activate_address = activate_address;
851 new_item->standalone_address = standalone_address;
852 new_item->next_altstep = NULL;
853 if(altstep_head == NULL) altstep_head = new_item;
854 else altstep_tail->next_altstep = new_item;
855 altstep_tail = new_item;
856}
857
858void TTCN_Module::add_testcase_nonpard(const char *testcase_name,
859 testcase_t testcase_function)
860{
861 testcase_list_item *new_item = new testcase_list_item;
862 new_item->testcase_name = testcase_name;
863 new_item->is_pard = FALSE;
864 new_item->testcase_function = testcase_function;
865 new_item->next_testcase = NULL;
866 if (testcase_head == NULL) testcase_head = new_item;
867 else testcase_tail->next_testcase = new_item;
868 testcase_tail = new_item;
869}
870
871void TTCN_Module::add_testcase_pard(const char *testcase_name,
872 genericfunc_t testcase_address)
873{
874 testcase_list_item *new_item = new testcase_list_item;
875 new_item->testcase_name = testcase_name;
876 new_item->is_pard = TRUE;
877 new_item->testcase_address = testcase_address;
878 new_item->next_testcase = NULL;
879 if(testcase_head == NULL) testcase_head = new_item;
880 else testcase_tail->next_testcase = new_item;
881 testcase_tail = new_item;
882}
883
884void TTCN_Module::execute_testcase(const char *testcase_name)
885{
886 for (testcase_list_item *list_iter = testcase_head; list_iter != NULL;
887 list_iter = list_iter->next_testcase) {
888 if (!strcmp(list_iter->testcase_name, testcase_name)) {
889 if (list_iter->is_pard) {
890 // Testcase has parameters. However, there might be a chance...
891 // Move to the next one (if any) and check that it has the same name.
892 list_iter = list_iter->next_testcase;
893 if (list_iter == NULL
894 || strcmp(list_iter->testcase_name, testcase_name)) {
895 TTCN_error("Test case %s in module %s "
896 "cannot be executed individually (without control part) "
897 "because it has parameters.", testcase_name, module_name);
898 continue; // not reached
899 }
900 // else it has the same name, fall through
901 }
902
903 list_iter->testcase_function(FALSE, 0.0);
904 return;
905 }
906 }
907 TTCN_error("Test case %s does not exist in module %s.", testcase_name,
908 module_name);
909}
910
911void TTCN_Module::execute_all_testcases()
912{
913 boolean found = FALSE;
914 for (testcase_list_item *list_iter = testcase_head; list_iter != NULL;
915 list_iter = list_iter->next_testcase) {
916 if (!list_iter->is_pard) {
917 list_iter->testcase_function(FALSE, 0.0);
918 found = TRUE;
919 }
920 }
921 if (!found) {
922 if (testcase_head != NULL) TTCN_warning("Module %s does not contain "
923 "non-parameterized test cases, which can be executed individually "
924 "without control part.", module_name);
925 else TTCN_warning("Module %s does not contain test cases.",
926 module_name);
927 }
928}
929
930const char *TTCN_Module::get_function_name_by_address(
931 genericfunc_t function_address)
932{
933 for (function_list_item *list_iter = function_head; list_iter != NULL;
934 list_iter = list_iter->next_function)
935 if (list_iter->function_address == function_address)
936 return list_iter->function_name;
937 return NULL;
938}
939
940genericfunc_t TTCN_Module::get_function_address_by_name(const char *func_name)
941{
942 for (function_list_item *list_iter = function_head; list_iter != NULL;
943 list_iter = list_iter->next_function)
944 if (!strcmp(list_iter->function_name, func_name))
945 return list_iter->function_address;
946 return NULL;
947}
948
949genericfunc_t TTCN_Module::get_function_start_by_address(
950 genericfunc_t function_address)
951{
952 for (function_list_item *list_iter = function_head; list_iter != NULL;
953 list_iter = list_iter->next_function) {
954 if (list_iter->function_address == function_address) {
955 if (list_iter->start_address != NULL)
956 return list_iter->start_address;
957 else TTCN_error("Function %s.%s cannot be started on a parallel "
958 "test component.", module_name, list_iter->function_name);
959 }
960 }
961 return NULL;
962}
963
964const char *TTCN_Module::get_altstep_name_by_address(
965 genericfunc_t altstep_address)
966{
967 for(altstep_list_item *list_iter = altstep_head; list_iter != NULL;
968 list_iter = list_iter->next_altstep) {
969 if (list_iter->altstep_address == altstep_address)
970 return list_iter->altstep_name;
971 }
972 return NULL;
973}
974
975genericfunc_t TTCN_Module::get_altstep_address_by_name(const char* altstep_name)
976{
977 for(altstep_list_item *list_iter = altstep_head; list_iter != NULL;
978 list_iter = list_iter->next_altstep) {
979 if (!strcmp(list_iter->altstep_name, altstep_name))
980 return list_iter->altstep_address;
981 }
982 return NULL;
983}
984
985boolean TTCN_Module::get_altstep_data_by_address(genericfunc_t altstep_address,
986 genericfunc_t& standalone_address, genericfunc_t& activate_address)
987{
988 for(altstep_list_item* list_iter = altstep_head; list_iter != NULL;
989 list_iter = list_iter->next_altstep) {
990 if (list_iter->altstep_address == altstep_address) {
991 standalone_address = list_iter->standalone_address;
992 activate_address = list_iter->activate_address;
993 return TRUE;
994 }
995 }
996 return FALSE;
997}
998
999const char *TTCN_Module::get_testcase_name_by_address(
1000 genericfunc_t testcase_address)
1001{
1002 for(testcase_list_item *list_iter = testcase_head; list_iter != NULL;
1003 list_iter = list_iter->next_testcase) {
1004 if (list_iter->is_pard) {
1005 if (list_iter->testcase_address == testcase_address)
1006 return list_iter->testcase_name;
1007 } else {
1008 if ((genericfunc_t)list_iter->testcase_function == testcase_address)
1009 return list_iter->testcase_name;
1010 }
1011 }
1012 return NULL;
1013}
1014
1015genericfunc_t TTCN_Module::get_testcase_address_by_name(const char *testcase_name)
1016{
1017 for (testcase_list_item *list_iter = testcase_head; list_iter != NULL;
1018 list_iter = list_iter->next_testcase) {
1019 if (!strcmp(list_iter->testcase_name, testcase_name)) {
1020 if (!list_iter->is_pard) return list_iter->testcase_address;
1021 else return (genericfunc_t)list_iter->testcase_function;
1022 }
1023 }
1024 return NULL;
1025}
1026
1027ModuleVersion* TTCN_Module::get_version() const {
1028 return new ModuleVersion(product_number, suffix, release, patch, build, extra);
1029}
1030
1031void TTCN_Module::print_version()
1032{
1033 const char *type_str;
1034 switch (module_type) {
1035 case TTCN3_MODULE:
1036 type_str = "TTCN-3";
1037 break;
1038 case ASN1_MODULE:
1039 type_str = "ASN.1";
1040 break;
1041 case CPLUSPLUS_MODULE:
1042 type_str = "C++";
1043 break;
1044 default:
1045 type_str = "???";
1046 break;
1047 }
1048 fprintf(stderr, "%-18s %-6s ", module_name, type_str);
1049 if (compilation_date != NULL && compilation_time != NULL) {
1050 fprintf(stderr, "%s %s", compilation_date, compilation_time);
1051 } else {
1052 fputs("<unknown> ", stderr);
1053 }
1054 if (md5_checksum != NULL) {
1055 putc(' ', stderr);
1056 for (int i = 0; i < 16; i++) fprintf(stderr, "%02x", md5_checksum[i]);
1057 }
1058 // else it's likely not a TTCN module, so no version info
1059
1060 putc(' ', stderr); // separator for the version number
1061 if (product_number != NULL) {
1062 fprintf(stderr, "%s", product_number);
1063 if (suffix > 0) {
1064 fprintf(stderr, "/%d", suffix);
1065 }
1066 putc(' ', stderr);
1067 }
1068 // release can be between 0 and 999999 inclusive
1069 // patch can go from 0 to 26 (English alphabet) - 6 (IOPQRW forbidden)
1070 // build can be between 0 and 99 inclusive
1071 if (release <= 999999 && patch <= ('Z'-'A'-6) && build <= 99) {
1072 char *build_str = buildstr(build);
1073 if (build_str == 0) TTCN_error("TTCN_Module::print_version()");
1074 if (extra != NULL ) {
1075 build_str = mputprintf(build_str, "%s", extra);
1076 }
1077 fprintf(stderr, "R%u%c%-4s", release, eri(patch), build_str);
1078 Free(build_str);
1079 }
1080 putc('\n', stderr);
1081}
1082
1083void TTCN_Module::list_testcases()
1084{
1085 if (control_func != NULL) printf("%s.control\n", module_name);
1086 for (testcase_list_item *list_iter = testcase_head; list_iter != NULL;
1087 list_iter = list_iter->next_testcase)
1088 if(!list_iter->is_pard)
1089 printf("%s.%s\n", module_name, list_iter->testcase_name);
1090}
1091
1092const namespace_t *TTCN_Module::get_ns(size_t p_index) const
1093{
1094 if (p_index == (size_t)-1) return NULL;
1095 if (p_index >= num_namespaces) TTCN_error(
1096 "Index overflow for namespaces, %lu instead of %lu",
1097 (unsigned long)p_index, (unsigned long)num_namespaces);
1098
1099 return xer_namespaces + p_index;
1100}
1101
1102const namespace_t *TTCN_Module::get_controlns() const
1103{
1104 if (xer_namespaces==NULL) {
1105 TTCN_error("No namespaces for module %s", module_name);
1106 }
1107 if (xer_namespaces[num_namespaces].px == NULL
1108 ||xer_namespaces[num_namespaces].px[0] == '\0') {
1109 TTCN_error("No control namespace for module %s", module_name);
1110 }
1111 return xer_namespaces+num_namespaces;
1112}
1113
1114
This page took 0.062107 seconds and 5 git commands to generate.