Debugger - Stage 3 (artf511247)
[deliverable/titan.core.git] / core / Module_list.cc
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
7 *
8 * Contributors:
9 *
10 * Balasko, Jeno
11 * Baranyi, Botond
12 * Beres, Szabolcs
13 * Delic, Adam
14 * Feher, Csaba
15 * Kovacs, Ferenc
16 * Raduly, Csaba
17 * Szabados, Kristof
18 * Szabo, Janos Zoltan – initial implementation
19 *
20 ******************************************************************************/
21 #include <set>
22 #include <sstream>
23 #include <string>
24
25 #include "Module_list.hh"
26 #include "Logger.hh"
27 #include "Error.hh"
28 #include "Textbuf.hh"
29 #include "Types.h"
30 #include "Param_Types.hh"
31 #include "Basetype.hh"
32 #include "Encdec.hh"
33
34 #include "../common/ModuleVersion.hh"
35 #ifdef USAGE_STATS
36 #include "../common/usage_stats.hh"
37 #endif
38
39 #include "../common/dbgnew.hh"
40 #include "Debugger.hh"
41
42 #include <stdio.h>
43 #include <string.h>
44 #include <limits.h>
45
46 TTCN_Module *Module_List::list_head = NULL, *Module_List::list_tail = NULL;
47
48 void fat_null() {}
49
50 void Module_List::add_module(TTCN_Module *module_ptr)
51 {
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)
56 break;
57 list_iter = list_iter->list_next;
58 }
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;
65 } else {
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;
70 }
71 module_ptr->list_next = list_iter;
72 if (list_iter == list_head) list_head = module_ptr;
73 }
74 }
75
76 void Module_List::remove_module(TTCN_Module *module_ptr)
77 {
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;
82
83 module_ptr->list_prev = NULL;
84 module_ptr->list_next = NULL;
85 }
86
87 TTCN_Module *Module_List::lookup_module(const char *module_name)
88 {
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;
92 return NULL;
93 }
94
95 TTCN_Module *Module_List::single_control_part()
96 {
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;
103 }
104 return retval;
105 }
106
107
108 void Module_List::pre_init_modules()
109 {
110 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
111 list_iter = list_iter->list_next) list_iter->pre_init_module();
112 }
113
114 void Module_List::post_init_modules()
115 {
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();
120 }
121
122 void Module_List::start_function(const char *module_name,
123 const char *function_name, Text_Buf& function_arguments)
124 {
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);
140 }
141 }
142
143 void Module_List::initialize_component(const char *module_name,
144 const char *component_type, boolean init_base_comps)
145 {
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.",
151 module_name);
152 else if (!module_ptr->initialize_component_func(component_type,
153 init_base_comps))
154 TTCN_error("Internal error: Component type %s does not exist in "
155 "module %s.", component_type, module_name);
156 }
157
158 void Module_List::set_param(Module_Param& param)
159 {
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;
165
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);
170 if (!param_found) {
171 second_name = param.get_id()->get_current_name(); // for error messages
172 }
173 }
174
175 // If not found, check if the first name segment was the module parameter name
176 // (even if it matched a module name)
177 if (!param_found) {
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)) {
183 param_found = TRUE;
184 }
185 }
186 }
187
188 // Still not found -> error
189 if (!param_found) {
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);
198 } else {
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);
202 }
203 }
204 }
205
206 Module_Param* Module_List::get_param(Module_Param_Name& param_name)
207 {
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;
213
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);
218 if (param == NULL) {
219 second_name = param_name.get_current_name(); // for error messages
220 }
221 }
222
223 // If not found, check if the first name segment was the module parameter name
224 // (even if it matched a module name)
225 if (param == NULL) {
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);
231 if (param != NULL) {
232 break;
233 }
234 }
235 }
236 }
237
238 // Still not found -> error
239 if (param == NULL) {
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);
248 } else {
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);
252 }
253 }
254 else if (param->get_type() == Module_Param::MP_Unbound) {
255 delete param;
256 TTCN_error("Referenced module parameter '%s' is unbound.", param_name.get_str());
257 }
258
259 return param;
260 }
261
262 void Module_List::log_param()
263 {
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();
273 }
274 }
275 }
276
277 void Module_List::execute_control(const char *module_name)
278 {
279 TTCN_Module *module_ptr = lookup_module(module_name);
280 if (module_ptr != NULL) {
281 if (module_ptr->control_func != NULL) {
282 try {
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.",
287 module_name);
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);
291 }
292 } else TTCN_error("Module %s does not have control part.", module_name);
293 } else TTCN_error("Module %s does not exist.", module_name);
294 }
295
296 void Module_List::execute_testcase(const char *module_name,
297 const char *testcase_name)
298 {
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);
302 }
303
304 void Module_List::execute_all_testcases(const char *module_name)
305 {
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);
309 }
310
311 void Module_List::print_version()
312 {
313 fputs(
314 "Module name Language Compilation time MD5 checksum "
315 " Version\n"
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);
322 }
323
324 void Module_List::send_versions() {
325 #ifdef USAGE_STATS
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);
332 }
333 delete version;
334 }
335
336 std::stringstream stream;
337 stream << "runtime";
338 for (std::set<ModuleVersion>::iterator it = versions.begin(); it != versions.end(); ++it) {
339 if (it == versions.begin()) {
340 stream << "&products=" << it->toString();
341 } else {
342 stream << "," << it->toString();
343 }
344 }
345
346 HttpSender* sender = new HttpSender;
347 UsageData::getInstance().sendDataThreaded(stream.str().c_str(), sender);
348 #endif
349 }
350
351
352 void Module_List::list_testcases()
353 {
354 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
355 list_iter = list_iter->list_next) list_iter->list_testcases();
356 }
357
358 void Module_List::push_version(Text_Buf& text_buf)
359 {
360 int n_modules = 0;
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);
371 }
372 }
373
374 void Module_List::encode_function(Text_Buf& text_buf,
375 genericfunc_t function_address)
376 {
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("");
380 else {
381 const char *module_name, *function_name;
382 if (lookup_function_by_address(function_address, module_name,
383 function_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);
389 }
390 }
391
392 void Module_List::decode_function(Text_Buf& text_buf,
393 genericfunc_t *function_addr_ptr)
394 {
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) {
399 try {
400 TTCN_error("Text decoder: Module %s does not exist when trying "
401 "to decode a function reference.", module_name);
402 } catch (...) {
403 // to prevent from memory leaks
404 delete [] module_name;
405 throw;
406 }
407 }
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;
412 else {
413 try {
414 TTCN_error("Text decoder: Reference to non-existent function "
415 "%s.%s was received.", module_name, function_name);
416 } catch (...) {
417 // to prevent from memory leaks
418 delete [] module_name;
419 delete [] function_name;
420 throw;
421 }
422 }
423 delete [] function_name;
424 } else *function_addr_ptr = fat_null;
425 delete [] module_name;
426 }
427
428 void Module_List::log_function(genericfunc_t function_address)
429 {
430 if (function_address == NULL) TTCN_Logger::log_event_str("<unbound>");
431 else if (function_address == fat_null) TTCN_Logger::log_event_str("null");
432 else {
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);
439 }
440 }
441
442 void Module_List::encode_altstep(Text_Buf& text_buf,
443 genericfunc_t altstep_address)
444 {
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("");
448 else {
449 const char *module_name, *altstep_name;
450 if (lookup_altstep_by_address(altstep_address, module_name,
451 altstep_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);
457 }
458 }
459
460 void Module_List::decode_altstep(Text_Buf& text_buf,
461 genericfunc_t *altstep_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 an altstep reference.", module_name);
470 } catch (...) {
471 // to prevent from memory leaks
472 delete [] module_name;
473 throw;
474 }
475 }
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;
480 else {
481 try {
482 TTCN_error("Text decoder: Reference to non-existent altstep "
483 "%s.%s was received.", module_name, altstep_name);
484 } catch (...) {
485 // to prevent from memory leaks
486 delete [] module_name;
487 delete [] altstep_name;
488 throw;
489 }
490 }
491 delete [] altstep_name;
492 } else *altstep_addr_ptr = fat_null;
493 delete [] module_name;
494 }
495
496 void Module_List::log_altstep(genericfunc_t altstep_address)
497 {
498 if (altstep_address == NULL) TTCN_Logger::log_event_str("<unbound>");
499 else if (altstep_address == fat_null) TTCN_Logger::log_event_str("null");
500 else {
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);
507 }
508 }
509
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)
513 {
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("");
517 else {
518 const char *module_name, *testcase_name;
519 if (lookup_testcase_by_address(testcase_address, module_name,
520 testcase_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);
526 }
527 }
528
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)
532 {
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) {
537 try {
538 TTCN_error("Text decoder: Module %s does not exist when trying "
539 "to decode a testcase reference.", module_name);
540 } catch (...) {
541 // to prevent from memory leaks
542 delete [] module_name;
543 throw;
544 }
545 }
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;
550 else {
551 try {
552 TTCN_error("Text decoder: Reference to non-existent testcase "
553 "%s.%s was received.", module_name, testcase_name);
554 } catch (...) {
555 // to prevent from memory leaks
556 delete [] module_name;
557 delete [] testcase_name;
558 throw;
559 }
560 }
561 delete [] testcase_name;
562 } else *testcase_addr_ptr = fat_null;
563 delete [] module_name;
564 }
565
566 void Module_List::log_testcase(genericfunc_t testcase_address)
567 {
568 if (testcase_address == NULL) TTCN_Logger::log_event_str("<unbound>");
569 else if (testcase_address == fat_null) TTCN_Logger::log_event_str("null");
570 else {
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);
577 }
578 }
579
580 genericfunc_t Module_List::get_fat_null()
581 {
582 return fat_null;
583 }
584
585 genericfunc_t Module_List::lookup_start_by_function_address(
586 genericfunc_t function_address)
587 {
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;
597 }
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);
601 // to avoid warnings
602 return NULL;
603 }
604
605 genericfunc_t Module_List::lookup_standalone_address_by_altstep_address(
606 genericfunc_t altstep_address)
607 {
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;
622 }
623 }
624 TTCN_error("Altstep reference %p in invoke operation does not point to a "
625 "valid altstep.", (void*)(unsigned long)altstep_address);
626 // to avoid warnings
627 return NULL;
628 }
629
630 genericfunc_t Module_List::lookup_activate_address_by_altstep_address(
631 genericfunc_t altstep_address)
632 {
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;
647 }
648 }
649 TTCN_error("Altstep reference %p in activate operation does not point to "
650 "a valid altstep.", (void*)(unsigned long)altstep_address);
651 // to avoid warnings
652 return NULL;
653 }
654
655 boolean Module_List::lookup_function_by_address(genericfunc_t function_address,
656 const char*& module_name, const char*& function_name)
657 {
658 for (TTCN_Module *list_iter = list_head; list_iter != NULL;
659 list_iter = list_iter->list_next) {
660 function_name =
661 list_iter->get_function_name_by_address(function_address);
662 if (function_name != NULL) {
663 module_name = list_iter->module_name;
664 return TRUE;
665 }
666 }
667 return FALSE;
668 }
669
670 boolean Module_List::lookup_altstep_by_address(genericfunc_t altstep_address,
671 const char*& module_name, const char*& altstep_name)
672 {
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;
678 return TRUE;
679 }
680 }
681 return FALSE;
682 }
683
684 boolean Module_List::lookup_testcase_by_address(genericfunc_t testcase_address,
685 const char*& module_name, const char*& testcase_name)
686 {
687 for(TTCN_Module *list_iter = list_head; list_iter != NULL;
688 list_iter = list_iter->list_next) {
689 testcase_name =
690 list_iter->get_testcase_name_by_address(testcase_address);
691 if (testcase_name != NULL) {
692 module_name = list_iter->module_name;
693 return TRUE;
694 }
695 }
696 return FALSE;
697 }
698
699 // ======================= TTCN_Module =======================
700
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;
706 };
707
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;
714 };
715
716 struct TTCN_Module::testcase_list_item {
717 const char *testcase_name;
718 boolean is_pard;
719 union {
720 testcase_t testcase_function;
721 genericfunc_t testcase_address;
722 };
723 testcase_list_item *next_testcase;
724 };
725
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)
754 , suffix(par_suffix)
755 , release(par_release)
756 , patch(par_patch)
757 , build(par_build)
758 , extra(par_extra)
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)
773 , altstep_head(NULL)
774 , altstep_tail(NULL)
775 , testcase_head(NULL)
776 , testcase_tail(NULL)
777 {
778 Module_List::add_module(this);
779 }
780
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)
794 , suffix(0)
795 , release(UINT_MAX)
796 , patch(UINT_MAX)
797 , build(UINT_MAX)
798 , extra(NULL)
799 , num_namespaces(0)
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)
809 , start_func(NULL)
810 , control_func(NULL)
811 , function_head(NULL)
812 , function_tail(NULL)
813 , altstep_head(NULL)
814 , altstep_tail(NULL)
815 , testcase_head(NULL)
816 , testcase_tail(NULL)
817 {
818 Module_List::add_module(this);
819 }
820
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>")
831 , md5_checksum(NULL)
832 , product_number(NULL)
833 , suffix(0)
834 , release(UINT_MAX)
835 , patch(UINT_MAX)
836 , build(UINT_MAX)
837 , extra(NULL)
838 , num_namespaces(0)
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)
847 , start_func(NULL)
848 , control_func(NULL)
849 , function_head(NULL)
850 , function_tail(NULL)
851 , altstep_head(NULL)
852 , altstep_tail(NULL)
853 , testcase_head(NULL)
854 , testcase_tail(NULL)
855 {
856 Module_List::add_module(this);
857 }
858
859 TTCN_Module::~TTCN_Module()
860 {
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;
866 }
867 while (altstep_head != NULL) {
868 altstep_list_item *tmp_ptr=altstep_head->next_altstep;
869 delete altstep_head;
870 altstep_head = tmp_ptr;
871 }
872 while (testcase_head != NULL) {
873 testcase_list_item *tmp_ptr = testcase_head->next_testcase;
874 delete testcase_head;
875 testcase_head = tmp_ptr;
876 }
877 }
878
879 void TTCN_Module::pre_init_module()
880 {
881 if (pre_init_called) return;
882 pre_init_called = TRUE;
883 if (pre_init_func == NULL) return;
884 try {
885 pre_init_func();
886 } catch (...) {
887 TTCN_Logger::log(TTCN_Logger::ERROR_UNQUALIFIED,
888 "An error occurred while initializing the constants of module %s.",
889 module_name);
890 throw;
891 }
892 }
893
894 void TTCN_Module::post_init_module()
895 {
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);
901 }
902
903 void TTCN_Module::add_function(const char *function_name,
904 genericfunc_t function_address, genericfunc_t start_address)
905 {
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;
914 }
915
916 void TTCN_Module::add_altstep(const char *altstep_name,
917 genericfunc_t altstep_address, genericfunc_t activate_address,
918 genericfunc_t standalone_address)
919 {
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;
929 }
930
931 void TTCN_Module::add_testcase_nonpard(const char *testcase_name,
932 testcase_t testcase_function)
933 {
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;
942 }
943
944 void TTCN_Module::add_testcase_pard(const char *testcase_name,
945 genericfunc_t testcase_address)
946 {
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;
955 }
956
957 void TTCN_Module::execute_testcase(const char *testcase_name)
958 {
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
972 }
973 // else it has the same name, fall through
974 }
975
976 list_iter->testcase_function(FALSE, 0.0);
977 return;
978 }
979 }
980 TTCN_error("Test case %s does not exist in module %s.", testcase_name,
981 module_name);
982 }
983
984 void TTCN_Module::execute_all_testcases()
985 {
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()) {
990 break;
991 }
992 if (!list_iter->is_pard) {
993 list_iter->testcase_function(FALSE, 0.0);
994 found = TRUE;
995 }
996 }
997 if (!found) {
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.",
1002 module_name);
1003 }
1004 }
1005
1006 const char *TTCN_Module::get_function_name_by_address(
1007 genericfunc_t function_address)
1008 {
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;
1013 return NULL;
1014 }
1015
1016 genericfunc_t TTCN_Module::get_function_address_by_name(const char *func_name)
1017 {
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;
1022 return NULL;
1023 }
1024
1025 genericfunc_t TTCN_Module::get_function_start_by_address(
1026 genericfunc_t function_address)
1027 {
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);
1035 }
1036 }
1037 return NULL;
1038 }
1039
1040 const char *TTCN_Module::get_altstep_name_by_address(
1041 genericfunc_t altstep_address)
1042 {
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;
1047 }
1048 return NULL;
1049 }
1050
1051 genericfunc_t TTCN_Module::get_altstep_address_by_name(const char* altstep_name)
1052 {
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;
1057 }
1058 return NULL;
1059 }
1060
1061 boolean TTCN_Module::get_altstep_data_by_address(genericfunc_t altstep_address,
1062 genericfunc_t& standalone_address, genericfunc_t& activate_address)
1063 {
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;
1069 return TRUE;
1070 }
1071 }
1072 return FALSE;
1073 }
1074
1075 const char *TTCN_Module::get_testcase_name_by_address(
1076 genericfunc_t testcase_address)
1077 {
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;
1083 } else {
1084 if ((genericfunc_t)list_iter->testcase_function == testcase_address)
1085 return list_iter->testcase_name;
1086 }
1087 }
1088 return NULL;
1089 }
1090
1091 genericfunc_t TTCN_Module::get_testcase_address_by_name(const char *testcase_name)
1092 {
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;
1098 }
1099 }
1100 return NULL;
1101 }
1102
1103 ModuleVersion* TTCN_Module::get_version() const {
1104 return new ModuleVersion(product_number, suffix, release, patch, build, extra);
1105 }
1106
1107 void TTCN_Module::print_version()
1108 {
1109 const char *type_str;
1110 switch (module_type) {
1111 case TTCN3_MODULE:
1112 type_str = "TTCN-3";
1113 break;
1114 case ASN1_MODULE:
1115 type_str = "ASN.1";
1116 break;
1117 case CPLUSPLUS_MODULE:
1118 type_str = "C++";
1119 break;
1120 default:
1121 type_str = "???";
1122 break;
1123 }
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);
1127 } else {
1128 fputs("<unknown> ", stderr);
1129 }
1130 if (md5_checksum != NULL) {
1131 putc(' ', stderr);
1132 for (int i = 0; i < 16; i++) fprintf(stderr, "%02x", md5_checksum[i]);
1133 }
1134 // else it's likely not a TTCN module, so no version info
1135
1136 putc(' ', stderr); // separator for the version number
1137 if (product_number != NULL) {
1138 fprintf(stderr, "%s", product_number);
1139 if (suffix > 0) {
1140 fprintf(stderr, "/%d", suffix);
1141 }
1142 putc(' ', stderr);
1143 }
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);
1152 }
1153 fprintf(stderr, "R%u%c%-4s", release, eri(patch), build_str);
1154 Free(build_str);
1155 }
1156 putc('\n', stderr);
1157 }
1158
1159 void TTCN_Module::list_testcases()
1160 {
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);
1166 }
1167
1168 const namespace_t *TTCN_Module::get_ns(size_t p_index) const
1169 {
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);
1174
1175 return xer_namespaces + p_index;
1176 }
1177
1178 const namespace_t *TTCN_Module::get_controlns() const
1179 {
1180 if (xer_namespaces==NULL) {
1181 TTCN_error("No namespaces for module %s", module_name);
1182 }
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);
1186 }
1187 return xer_namespaces+num_namespaces;
1188 }
1189
1190
This page took 0.058032 seconds and 5 git commands to generate.