Merge "fixed self-ref check to no longer display errors for omit values (bug 498430)"
[deliverable/titan.core.git] / compiler2 / DebuggerStuff.cc
CommitLineData
7329404e
BB
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 * Baranyi, Botond – initial implementation
11 *
12 ******************************************************************************/
13
14#include "DebuggerStuff.hh"
15#include "AST.hh"
16#include "Type.hh"
17#include "ttcn3/AST_ttcn3.hh"
18#include "ttcn3/ArrayDimensions.hh"
19
20namespace Common {
21
22/** Returns a string, that contains the template parameters of the debugger's
23 * port array or timer array printing function.
24 *
25 * Recursive (handles one array dimension per call).
26 *
27 * @param p_dims the array's dimensions
28 * @param p_element_type name of the array's element C++ class
29 * @param p_array_type name of the array's C++ class ("PORT_ARRAY" or "TIMER_ARRAY")
30 * @param index the index of the currently handled dimension in \a p_dims
31 */
32string function_params_for_array_dims(Ttcn::ArrayDimensions* p_dims,
33 string p_element_type,
34 string p_array_type,
35 size_t index = 0)
36{
37 if (index == p_dims->get_nof_dims()) {
38 return p_element_type;
39 }
40 string ret_val;
41 if (index != 0) {
42 ret_val = p_array_type + string("<");
43 }
44 ret_val += function_params_for_array_dims(p_dims, p_element_type, p_array_type, index + 1);
45 Ttcn::ArrayDimension* dim = p_dims->get_dim_byIndex(index);
46 ret_val += string(", ") + Int2string(dim->get_size()) +
47 string(", ") + Int2string(dim->get_offset());
48 if (index != 0) {
49 ret_val += string(">");
50 }
51 return ret_val;
52}
53
54/** Returns a string, that contains the template parameters of the debugger's
55 * value array or template array printing function.
56 *
57 * Recursive (handles one array dimension per call).
58 *
59 * @param p_type the current type (either an array or the array element)
60 * @param p_scope the current scope
61 * @param p_templ indicates whether it's a template array or value array
62 * @param p_first indicates whether this is the first call or a recursive call
63 */
64string function_params_for_array_type(Type* p_type,
65 Scope* p_scope,
66 bool p_templ,
67 bool p_first = true)
68{
69 string ret_val;
70 if (p_type->get_typetype() != Type::T_ARRAY) {
71 ret_val = p_type->get_genname_value(p_scope);
72 if (p_templ) {
73 ret_val += "_template";
74 }
75 }
76 else {
77 if (!p_first) {
78 if (p_templ) {
79 ret_val = "TEMPLATE_ARRAY<";
80 }
81 else {
82 ret_val = "VALUE_ARRAY<";
83 }
84 }
85 Type* elem_type = p_type->get_ofType()->get_type_refd_last();
86 if (p_templ) {
87 ret_val += function_params_for_array_type(elem_type, p_scope, false, false) +
88 ", " + function_params_for_array_type(elem_type, p_scope, true, false);
89 }
90 else {
91 ret_val += function_params_for_array_type(elem_type, p_scope, false, false);
92 }
93 Ttcn::ArrayDimension* dim = p_type->get_dimension();
94 ret_val += string(", ") + Int2string(dim->get_size()) +
95 string(", ") + Int2string(dim->get_offset());
96 if (!p_first) {
97 ret_val += string(">");
98 }
99 }
100 return ret_val;
101}
102
103/** Appends the string representations of the specified array dimensions. */
104string array_dimensions_to_string(Ttcn::ArrayDimensions* p_dims)
105{
106 string ret_val;
107 for (size_t i = 0; i < p_dims->get_nof_dims(); ++i) {
108 ret_val += p_dims->get_dim_byIndex(i)->get_stringRepr();
109 }
110 return ret_val;
111}
112
f08ff9ca
BB
113void calculate_type_name_and_debug_functions_from_type(Type* p_type,
114 Type* p_type_last,
115 Module* p_module,
116 string& p_type_name,
117 string& p_print_function,
118 string& p_set_function)
7329404e
BB
119{
120 if (p_type_last->get_typetype() == Type::T_COMPONENT) {
121 p_type_name = "component";
122 }
123 else if (p_type_last->is_structured_type() ||
124 p_type_last->get_typetype() == Type::T_ENUM_A ||
125 p_type_last->get_typetype() == Type::T_ENUM_T ||
7329404e
BB
126 p_type_last->get_typetype() == Type::T_SIGNATURE ||
127 p_type_last->get_typetype() == Type::T_FUNCTION ||
128 p_type_last->get_typetype() == Type::T_ALTSTEP ||
129 p_type_last->get_typetype() == Type::T_TESTCASE) {
130 // user-defined type
131 if (p_type_last->is_pard_type_instance()) {
132 // if the referenced type is an instance of an ASN.1 parameterized type,
133 // then use the last non-parameterized type in the reference chain to
134 // calculate the type name
135 Type* t = p_type;
136 while (t->is_ref() && !t->is_pard_type_instance()) {
137 p_type_name = t->get_dispname();
138 t = t->get_type_refd();
139 }
140 }
141 else {
142 p_type_name = p_type_last->get_dispname();
143 }
144 const Module* var_type_mod = p_type_last->get_my_scope()->get_scope_mod();
f08ff9ca 145 string module_prefix;
7329404e 146 if (var_type_mod != p_module) {
f08ff9ca 147 module_prefix = var_type_mod->get_modid().get_name() + "::";
7329404e 148 }
f08ff9ca
BB
149 p_print_function = module_prefix + "print_var_" +
150 var_type_mod->get_modid().get_ttcnname();
151 if (p_type_last->get_typetype() != Type::T_SIGNATURE &&
152 p_type_last->get_typetype() != Type::T_PORT) {
153 p_set_function = module_prefix + "set_var_" +
154 var_type_mod->get_modid().get_ttcnname();
7329404e 155 }
7329404e
BB
156 }
157 else {
158 // built-in type, get the TTCN-3 version of the type if possible
159 switch (p_type_last->get_typetype()) {
160 case Type::T_GENERALSTRING:
161 case Type::T_GRAPHICSTRING:
162 case Type::T_TELETEXSTRING:
163 case Type::T_VIDEOTEXSTRING:
164 // these ASN.1 string types are not converted right by Type::get_typetype_ttcn3()
165 p_type_name = "universal charstring";
166 break;
788b5893
BB
167 case Type::T_PORT:
168 p_type_name = "port";
169 break;
7329404e
BB
170 case Type::T_UNRESTRICTEDSTRING:
171 case Type::T_EMBEDDED_PDV:
172 case Type::T_EXTERNAL:
173 // these are converted to T_SEQ_T by Type::get_typetype_ttcn3()
174 p_type_name = Type::get_typename_builtin(p_type_last->get_typetype());
175 break;
176 default:
177 p_type_name = Type::get_typename_builtin(p_type_last->get_typetype_ttcn3());
178 break;
179 }
180 }
181}
182
183char* generate_code_debugger_add_var(char* str, Common::Assignment* var_ass,
184 Module* current_mod /* = NULL */,
185 const char* scope_name /* = NULL */)
186{
187 if (current_mod == NULL) {
188 current_mod = var_ass->get_my_scope()->get_scope_mod();
189 }
190
191 bool is_lazy_param = false;
f08ff9ca 192 bool is_constant = false;
7329404e
BB
193 switch (var_ass->get_asstype()) {
194 case Common::Assignment::A_PAR_VAL:
195 case Common::Assignment::A_PAR_VAL_IN:
f08ff9ca 196 case Common::Assignment::A_PAR_TEMPL_IN: {
7329404e
BB
197 if (var_ass->get_lazy_eval()) {
198 // lazy parameters have their own printing function
199 is_lazy_param = true;
200 }
f08ff9ca
BB
201 Ttcn::FormalPar* fpar = dynamic_cast<Ttcn::FormalPar*>(var_ass);
202 is_constant = fpar == NULL || !fpar->get_used_as_lvalue();
203 break; }
204 case Common::Assignment::A_CONST:
205 case Common::Assignment::A_EXT_CONST:
206 case Common::Assignment::A_MODULEPAR:
207 case Common::Assignment::A_MODULEPAR_TEMP:
208 case Common::Assignment::A_TEMPLATE:
f57971fe 209 is_constant = true; //scope_name != NULL;
7329404e
BB
210 default:
211 break;
212 }
213
f08ff9ca
BB
214 // recreate the TTCN-3 version of the type name and determine the type's
215 // printing and overwriting functions
216 string type_name, print_function, set_function;
7329404e
BB
217 print_function = is_lazy_param ? "TTCN3_Debugger::print_lazy_param<" :
218 "TTCN3_Debugger::print_base_var";
f08ff9ca 219 set_function = "TTCN3_Debugger::set_base_var";
7329404e
BB
220 if (var_ass->get_asstype() == Common::Assignment::A_TIMER ||
221 var_ass->get_asstype() == Common::Assignment::A_PAR_TIMER) {
222 type_name = "timer";
223 if (var_ass->get_Dimensions() != NULL) {
224 // timer array
225 type_name += array_dimensions_to_string(var_ass->get_Dimensions());
226 print_function = string("TTCN3_Debugger::print_timer_array<") +
227 function_params_for_array_dims(var_ass->get_Dimensions(),
228 string("TIMER"), string("TIMER_ARRAY")) +
229 string(">");
230 }
231 }
232 else {
233 Common::Type* var_type = var_ass->get_Type();
234 // get the type at the end of the reference chain, but don't go through
235 // CHARACTER STRINGs, EMBEDDED PDVs and EXTERNALs
236 while (var_type->is_ref() && var_type->get_typetype() != Type::T_EXTERNAL &&
237 var_type->get_typetype() != Type::T_EMBEDDED_PDV &&
238 var_type->get_typetype() != Type::T_UNRESTRICTEDSTRING) {
239 var_type = var_type->get_type_refd();
240 }
241 if (is_lazy_param) {
242 print_function += var_type->get_genname_value(current_mod);
243 }
244 if (var_type->get_typetype() == Type::T_PORT && var_ass->get_Dimensions() != NULL) {
245 // port array
246 type_name = var_type->get_dispname() +
247 array_dimensions_to_string(var_ass->get_Dimensions());
248 if (!is_lazy_param) {
249 print_function = string("TTCN3_Debugger::print_port_array<") +
250 function_params_for_array_dims(var_ass->get_Dimensions(),
251 var_type->get_genname_value(current_mod),
252 string("PORT_ARRAY")) +
253 string(">");
254 }
255 }
256 else if (var_type->get_typetype() == Type::T_ARRAY) {
257 string dims_str;
258 Type* t = var_type;
259 while (t->get_typetype() == Type::T_ARRAY) {
260 dims_str += t->get_dimension()->get_stringRepr();
261 t = t->get_ofType()->get_type_refd_last();
262 }
f08ff9ca
BB
263 string dummy1, dummy2;
264 calculate_type_name_and_debug_functions_from_type(t, t, current_mod,
265 type_name, dummy1, dummy2);
7329404e
BB
266 type_name += dims_str;
267 if (!is_lazy_param) {
268 switch (var_ass->get_asstype()) {
269 case Common::Assignment::A_MODULEPAR_TEMP:
270 case Common::Assignment::A_TEMPLATE:
271 case Common::Assignment::A_VAR_TEMPLATE:
272 case Common::Assignment::A_PAR_TEMPL_IN:
273 case Common::Assignment::A_PAR_TEMPL_OUT:
274 case Common::Assignment::A_PAR_TEMPL_INOUT:
275 // template array
276 print_function = string("TTCN3_Debugger::print_template_array<") +
277 function_params_for_array_type(var_type, current_mod, true) +
278 string(">");
f08ff9ca
BB
279 set_function = string("TTCN3_Debugger::set_template_array<") +
280 function_params_for_array_type(var_type, current_mod, true) +
281 string(">");
7329404e
BB
282 break;
283 default:
284 // value array
285 print_function = string("TTCN3_Debugger::print_value_array<") +
286 function_params_for_array_type(var_type, current_mod, false) +
287 string(">");
f08ff9ca
BB
288 set_function = string("TTCN3_Debugger::set_value_array<") +
289 function_params_for_array_type(var_type, current_mod, false) +
290 string(">");
7329404e
BB
291 break;
292 }
293 }
294 }
295 else {
296 string dummy;
f08ff9ca
BB
297 calculate_type_name_and_debug_functions_from_type(var_ass->get_Type(),
298 var_type, current_mod, type_name, is_lazy_param ? dummy : print_function,
299 set_function);
7329404e
BB
300 }
301 }
302
303 switch (var_ass->get_asstype()) {
304 case Common::Assignment::A_MODULEPAR_TEMP:
305 case Common::Assignment::A_TEMPLATE:
306 case Common::Assignment::A_VAR_TEMPLATE:
307 case Common::Assignment::A_PAR_TEMPL_IN:
308 case Common::Assignment::A_PAR_TEMPL_OUT:
309 case Common::Assignment::A_PAR_TEMPL_INOUT:
310 // add a suffix, if it's a template
311 type_name += " template";
312 if (is_lazy_param) {
313 print_function += "_template";
314 }
315 break;
316 default:
317 break;
318 }
319
320 if (is_lazy_param) {
321 print_function += ">";
322 }
323
1cb5b229
BB
324 string module_str;
325 if (scope_name != NULL && !strcmp(scope_name, "global")) {
326 // only store the module name for global variables
327 module_str = string("\"") +
328 var_ass->get_my_scope()->get_scope_mod()->get_modid().get_ttcnname() + string("\"");
329 }
330 else {
331 module_str = "NULL";
332 }
333
334 return mputprintf(str, "%s%s_scope%sadd_variable(&%s, \"%s\", \"%s\", %s, %s%s%s);\n",
7329404e
BB
335 scope_name != NULL ? " " : "", // add indenting for global variables
336 scope_name != NULL ? scope_name : "debug", // the prefix of the debugger scope:
337 // ("global" for global variables, "debug" for local variables,
338 // or the component name for component variables)
339 scope_name != NULL ? "->" : ".", // global scopes are pointers, local scopes
340 // are local variables
341 var_ass->get_genname_from_scope(current_mod, "").c_str(), // variable name in C++
342 // (HACK: an empty string is passed as the prefix parameter to get_genname_from_scope,
343 // so the lazy parameter evaluation code is not generated)
344 var_ass->get_id().get_ttcnname().c_str(), // variable name in TTCN-3
345 type_name.c_str(), // variable type in TTCN-3, with a suffix if it's a template
1cb5b229 346 module_str.c_str(), // module name, where the variable was defined
f08ff9ca
BB
347 print_function.c_str(), // variable printing function
348 is_constant ? "" : ", ", is_constant ? "" : set_function.c_str());
349 // variable overwriting function (not generated for constants)
7329404e
BB
350}
351
352char* generate_code_debugger_function_init(char* str, Common::Assignment* func_ass)
353{
354 string comp_str = func_ass->get_RunsOnType() == NULL ? string("NULL") :
355 string("\"") + func_ass->get_RunsOnType()->get_dispname() + string("\"");
356 const char* func_type_str = NULL;
357 switch (func_ass->get_asstype()) {
358 case Common::Assignment::A_FUNCTION:
359 case Common::Assignment::A_FUNCTION_RVAL:
360 case Common::Assignment::A_FUNCTION_RTEMP:
361 func_type_str = "function";
362 break;
363 case Common::Assignment::A_EXT_FUNCTION:
364 case Common::Assignment::A_EXT_FUNCTION_RVAL:
365 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
366 func_type_str = "external function";
367 break;
368 case Common::Assignment::A_TESTCASE:
369 func_type_str = "testcase";
370 break;
371 case Common::Assignment::A_ALTSTEP:
372 func_type_str = "altstep";
373 break;
374 case Common::Assignment::A_TEMPLATE: // parameterized template
375 func_type_str = "template";
376 break;
377 default:
378 break;
379 }
380 Ttcn::FormalParList* fp_list = func_ass != NULL ? func_ass->get_FormalParList() : NULL;
381 if (fp_list != NULL && fp_list->get_nof_fps() != 0) {
382 // has parameters
383 char* fp_names_str = NULL;
384 char* fp_types_str = NULL;
385 char* fp_add_var_str = NULL;
386 for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) {
387 // gather everything needed for this parameter in sub-strings
388 Ttcn::FormalPar* fp = fp_list->get_fp_byIndex(i);
389 const char* fp_type_str = NULL;
390 switch (fp->get_asstype()) {
391 case Common::Assignment::A_PAR_VAL:
392 case Common::Assignment::A_PAR_VAL_IN:
393 case Common::Assignment::A_PAR_TEMPL_IN:
394 fp_type_str = "in";
395 break;
396 case Common::Assignment::A_PAR_VAL_INOUT:
397 case Common::Assignment::A_PAR_TEMPL_INOUT:
398 case Common::Assignment::A_PAR_TIMER: // treat timers and ports as 'inout' parameters
399 case Common::Assignment::A_PAR_PORT:
400 fp_type_str = "inout";
401 break;
402 case Common::Assignment::A_PAR_VAL_OUT:
403 case Common::Assignment::A_PAR_TEMPL_OUT:
404 fp_type_str = "out";
405 break;
406 default:
407 break;
408 }
409 fp_names_str = mputprintf(fp_names_str,
410 "param_names[%d] = \"%s\";\n", (int)i, fp->get_id().get_ttcnname().c_str());
411 fp_types_str = mputprintf(fp_types_str,
412 "param_types[%d] = \"%s\";\n", (int)i, fp_type_str);
413 fp_add_var_str = generate_code_debugger_add_var(fp_add_var_str, fp);
414 }
415 str = mputprintf(str,
416 "charstring_list param_names;\n"
417 "%s"
418 "charstring_list param_types;\n"
419 "%s"
420 "TTCN3_Debug_Function debug_scope(\"%s\", \"%s\", \"%s\", param_names, param_types, %s);\n"
421 "%s"
422 "debug_scope.initial_snapshot();\n"
423 , fp_names_str, fp_types_str
424 , func_ass->get_id().get_dispname().c_str(), func_type_str
425 , func_ass->get_my_scope()->get_scope_mod()->get_modid().get_ttcnname().c_str()
426 , comp_str.c_str(), fp_add_var_str);
427 Free(fp_names_str);
428 Free(fp_types_str);
429 Free(fp_add_var_str);
430 }
431 else {
432 // no parameters
433 str = mputprintf(str,
434 "charstring_list no_params = NULL_VALUE;\n"
435 "TTCN3_Debug_Function debug_scope(\"%s\", \"%s\", \"%s\", no_params, no_params, %s);\n"
436 "debug_scope.initial_snapshot();\n"
437 , func_ass->get_id().get_dispname().c_str(), func_type_str
438 , func_ass->get_my_scope()->get_scope_mod()->get_modid().get_ttcnname().c_str()
439 , comp_str.c_str());
440 }
441 return str;
442}
443
444}
This page took 0.040409 seconds and 5 git commands to generate.