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
10 * Baranyi, Botond – initial implementation
12 ******************************************************************************/
14 #include "DebuggerStuff.hh"
17 #include "ttcn3/AST_ttcn3.hh"
18 #include "ttcn3/ArrayDimensions.hh"
22 /** Returns a string, that contains the template parameters of the debugger's
23 * port array or timer array printing function.
25 * Recursive (handles one array dimension per call).
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
32 string
function_params_for_array_dims(Ttcn::ArrayDimensions
* p_dims
,
33 string p_element_type
,
37 if (index
== p_dims
->get_nof_dims()) {
38 return p_element_type
;
42 ret_val
= p_array_type
+ string("<");
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());
49 ret_val
+= string(">");
54 /** Returns a string, that contains the template parameters of the debugger's
55 * value array or template array printing function.
57 * Recursive (handles one array dimension per call).
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
64 string
function_params_for_array_type(Type
* p_type
,
70 if (p_type
->get_typetype() != Type::T_ARRAY
) {
71 ret_val
= p_type
->get_genname_value(p_scope
);
73 ret_val
+= "_template";
79 ret_val
= "TEMPLATE_ARRAY<";
82 ret_val
= "VALUE_ARRAY<";
85 Type
* elem_type
= p_type
->get_ofType()->get_type_refd_last();
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);
91 ret_val
+= function_params_for_array_type(elem_type
, p_scope
, false, false);
93 Ttcn::ArrayDimension
* dim
= p_type
->get_dimension();
94 ret_val
+= string(", ") + Int2string(dim
->get_size()) +
95 string(", ") + Int2string(dim
->get_offset());
97 ret_val
+= string(">");
103 /** Appends the string representations of the specified array dimensions. */
104 string
array_dimensions_to_string(Ttcn::ArrayDimensions
* p_dims
)
107 for (size_t i
= 0; i
< p_dims
->get_nof_dims(); ++i
) {
108 ret_val
+= p_dims
->get_dim_byIndex(i
)->get_stringRepr();
113 void calculate_type_name_and_debug_functions_from_type(Type
* p_type
,
117 string
& p_print_function
,
118 string
& p_set_function
)
120 if (p_type_last
->get_typetype() == Type::T_COMPONENT
) {
121 p_type_name
= "component";
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
||
126 p_type_last
->get_typetype() == Type::T_PORT
||
127 p_type_last
->get_typetype() == Type::T_SIGNATURE
||
128 p_type_last
->get_typetype() == Type::T_FUNCTION
||
129 p_type_last
->get_typetype() == Type::T_ALTSTEP
||
130 p_type_last
->get_typetype() == Type::T_TESTCASE
) {
132 if (p_type_last
->is_pard_type_instance()) {
133 // if the referenced type is an instance of an ASN.1 parameterized type,
134 // then use the last non-parameterized type in the reference chain to
135 // calculate the type name
137 while (t
->is_ref() && !t
->is_pard_type_instance()) {
138 p_type_name
= t
->get_dispname();
139 t
= t
->get_type_refd();
143 p_type_name
= p_type_last
->get_dispname();
145 const Module
* var_type_mod
= p_type_last
->get_my_scope()->get_scope_mod();
146 string module_prefix
;
147 if (var_type_mod
!= p_module
) {
148 module_prefix
= var_type_mod
->get_modid().get_name() + "::";
150 p_print_function
= module_prefix
+ "print_var_" +
151 var_type_mod
->get_modid().get_ttcnname();
152 if (p_type_last
->get_typetype() != Type::T_SIGNATURE
&&
153 p_type_last
->get_typetype() != Type::T_PORT
) {
154 p_set_function
= module_prefix
+ "set_var_" +
155 var_type_mod
->get_modid().get_ttcnname();
159 // built-in type, get the TTCN-3 version of the type if possible
160 switch (p_type_last
->get_typetype()) {
161 case Type::T_GENERALSTRING
:
162 case Type::T_GRAPHICSTRING
:
163 case Type::T_TELETEXSTRING
:
164 case Type::T_VIDEOTEXSTRING
:
165 // these ASN.1 string types are not converted right by Type::get_typetype_ttcn3()
166 p_type_name
= "universal charstring";
168 case Type::T_UNRESTRICTEDSTRING
:
169 case Type::T_EMBEDDED_PDV
:
170 case Type::T_EXTERNAL
:
171 // these are converted to T_SEQ_T by Type::get_typetype_ttcn3()
172 p_type_name
= Type::get_typename_builtin(p_type_last
->get_typetype());
175 p_type_name
= Type::get_typename_builtin(p_type_last
->get_typetype_ttcn3());
181 char* generate_code_debugger_add_var(char* str
, Common::Assignment
* var_ass
,
182 Module
* current_mod
/* = NULL */,
183 const char* scope_name
/* = NULL */)
185 if (current_mod
== NULL
) {
186 current_mod
= var_ass
->get_my_scope()->get_scope_mod();
189 bool is_lazy_param
= false;
190 bool is_constant
= false;
191 switch (var_ass
->get_asstype()) {
192 case Common::Assignment::A_PAR_VAL
:
193 case Common::Assignment::A_PAR_VAL_IN
:
194 case Common::Assignment::A_PAR_TEMPL_IN
: {
195 if (var_ass
->get_lazy_eval()) {
196 // lazy parameters have their own printing function
197 is_lazy_param
= true;
199 Ttcn::FormalPar
* fpar
= dynamic_cast<Ttcn::FormalPar
*>(var_ass
);
200 is_constant
= fpar
== NULL
|| !fpar
->get_used_as_lvalue();
202 case Common::Assignment::A_CONST
:
203 case Common::Assignment::A_EXT_CONST
:
204 case Common::Assignment::A_MODULEPAR
:
205 case Common::Assignment::A_MODULEPAR_TEMP
:
206 case Common::Assignment::A_TEMPLATE
:
207 is_constant
= scope_name
!= NULL
;
212 // recreate the TTCN-3 version of the type name and determine the type's
213 // printing and overwriting functions
214 string type_name
, print_function
, set_function
;
215 print_function
= is_lazy_param
? "TTCN3_Debugger::print_lazy_param<" :
216 "TTCN3_Debugger::print_base_var";
217 set_function
= "TTCN3_Debugger::set_base_var";
218 if (var_ass
->get_asstype() == Common::Assignment::A_TIMER
||
219 var_ass
->get_asstype() == Common::Assignment::A_PAR_TIMER
) {
221 if (var_ass
->get_Dimensions() != NULL
) {
223 type_name
+= array_dimensions_to_string(var_ass
->get_Dimensions());
224 print_function
= string("TTCN3_Debugger::print_timer_array<") +
225 function_params_for_array_dims(var_ass
->get_Dimensions(),
226 string("TIMER"), string("TIMER_ARRAY")) +
231 Common::Type
* var_type
= var_ass
->get_Type();
232 // get the type at the end of the reference chain, but don't go through
233 // CHARACTER STRINGs, EMBEDDED PDVs and EXTERNALs
234 while (var_type
->is_ref() && var_type
->get_typetype() != Type::T_EXTERNAL
&&
235 var_type
->get_typetype() != Type::T_EMBEDDED_PDV
&&
236 var_type
->get_typetype() != Type::T_UNRESTRICTEDSTRING
) {
237 var_type
= var_type
->get_type_refd();
240 print_function
+= var_type
->get_genname_value(current_mod
);
242 if (var_type
->get_typetype() == Type::T_PORT
&& var_ass
->get_Dimensions() != NULL
) {
244 type_name
= var_type
->get_dispname() +
245 array_dimensions_to_string(var_ass
->get_Dimensions());
246 if (!is_lazy_param
) {
247 print_function
= string("TTCN3_Debugger::print_port_array<") +
248 function_params_for_array_dims(var_ass
->get_Dimensions(),
249 var_type
->get_genname_value(current_mod
),
250 string("PORT_ARRAY")) +
254 else if (var_type
->get_typetype() == Type::T_ARRAY
) {
257 while (t
->get_typetype() == Type::T_ARRAY
) {
258 dims_str
+= t
->get_dimension()->get_stringRepr();
259 t
= t
->get_ofType()->get_type_refd_last();
261 string dummy1
, dummy2
;
262 calculate_type_name_and_debug_functions_from_type(t
, t
, current_mod
,
263 type_name
, dummy1
, dummy2
);
264 type_name
+= dims_str
;
265 if (!is_lazy_param
) {
266 switch (var_ass
->get_asstype()) {
267 case Common::Assignment::A_MODULEPAR_TEMP
:
268 case Common::Assignment::A_TEMPLATE
:
269 case Common::Assignment::A_VAR_TEMPLATE
:
270 case Common::Assignment::A_PAR_TEMPL_IN
:
271 case Common::Assignment::A_PAR_TEMPL_OUT
:
272 case Common::Assignment::A_PAR_TEMPL_INOUT
:
274 print_function
= string("TTCN3_Debugger::print_template_array<") +
275 function_params_for_array_type(var_type
, current_mod
, true) +
277 set_function
= string("TTCN3_Debugger::set_template_array<") +
278 function_params_for_array_type(var_type
, current_mod
, true) +
283 print_function
= string("TTCN3_Debugger::print_value_array<") +
284 function_params_for_array_type(var_type
, current_mod
, false) +
286 set_function
= string("TTCN3_Debugger::set_value_array<") +
287 function_params_for_array_type(var_type
, current_mod
, false) +
295 calculate_type_name_and_debug_functions_from_type(var_ass
->get_Type(),
296 var_type
, current_mod
, type_name
, is_lazy_param
? dummy
: print_function
,
301 switch (var_ass
->get_asstype()) {
302 case Common::Assignment::A_MODULEPAR_TEMP
:
303 case Common::Assignment::A_TEMPLATE
:
304 case Common::Assignment::A_VAR_TEMPLATE
:
305 case Common::Assignment::A_PAR_TEMPL_IN
:
306 case Common::Assignment::A_PAR_TEMPL_OUT
:
307 case Common::Assignment::A_PAR_TEMPL_INOUT
:
308 // add a suffix, if it's a template
309 type_name
+= " template";
311 print_function
+= "_template";
319 print_function
+= ">";
322 return mputprintf(str
, "%s%s_scope%sadd_variable(&%s, \"%s\", \"%s\", %s%s%s);\n",
323 scope_name
!= NULL
? " " : "", // add indenting for global variables
324 scope_name
!= NULL
? scope_name
: "debug", // the prefix of the debugger scope:
325 // ("global" for global variables, "debug" for local variables,
326 // or the component name for component variables)
327 scope_name
!= NULL
? "->" : ".", // global scopes are pointers, local scopes
328 // are local variables
329 var_ass
->get_genname_from_scope(current_mod
, "").c_str(), // variable name in C++
330 // (HACK: an empty string is passed as the prefix parameter to get_genname_from_scope,
331 // so the lazy parameter evaluation code is not generated)
332 var_ass
->get_id().get_ttcnname().c_str(), // variable name in TTCN-3
333 type_name
.c_str(), // variable type in TTCN-3, with a suffix if it's a template
334 print_function
.c_str(), // variable printing function
335 is_constant
? "" : ", ", is_constant
? "" : set_function
.c_str());
336 // variable overwriting function (not generated for constants)
339 char* generate_code_debugger_function_init(char* str
, Common::Assignment
* func_ass
)
341 string comp_str
= func_ass
->get_RunsOnType() == NULL
? string("NULL") :
342 string("\"") + func_ass
->get_RunsOnType()->get_dispname() + string("\"");
343 const char* func_type_str
= NULL
;
344 switch (func_ass
->get_asstype()) {
345 case Common::Assignment::A_FUNCTION
:
346 case Common::Assignment::A_FUNCTION_RVAL
:
347 case Common::Assignment::A_FUNCTION_RTEMP
:
348 func_type_str
= "function";
350 case Common::Assignment::A_EXT_FUNCTION
:
351 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
352 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
353 func_type_str
= "external function";
355 case Common::Assignment::A_TESTCASE
:
356 func_type_str
= "testcase";
358 case Common::Assignment::A_ALTSTEP
:
359 func_type_str
= "altstep";
361 case Common::Assignment::A_TEMPLATE
: // parameterized template
362 func_type_str
= "template";
367 Ttcn::FormalParList
* fp_list
= func_ass
!= NULL
? func_ass
->get_FormalParList() : NULL
;
368 if (fp_list
!= NULL
&& fp_list
->get_nof_fps() != 0) {
370 char* fp_names_str
= NULL
;
371 char* fp_types_str
= NULL
;
372 char* fp_add_var_str
= NULL
;
373 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); ++i
) {
374 // gather everything needed for this parameter in sub-strings
375 Ttcn::FormalPar
* fp
= fp_list
->get_fp_byIndex(i
);
376 const char* fp_type_str
= NULL
;
377 switch (fp
->get_asstype()) {
378 case Common::Assignment::A_PAR_VAL
:
379 case Common::Assignment::A_PAR_VAL_IN
:
380 case Common::Assignment::A_PAR_TEMPL_IN
:
383 case Common::Assignment::A_PAR_VAL_INOUT
:
384 case Common::Assignment::A_PAR_TEMPL_INOUT
:
385 case Common::Assignment::A_PAR_TIMER
: // treat timers and ports as 'inout' parameters
386 case Common::Assignment::A_PAR_PORT
:
387 fp_type_str
= "inout";
389 case Common::Assignment::A_PAR_VAL_OUT
:
390 case Common::Assignment::A_PAR_TEMPL_OUT
:
396 fp_names_str
= mputprintf(fp_names_str
,
397 "param_names[%d] = \"%s\";\n", (int)i
, fp
->get_id().get_ttcnname().c_str());
398 fp_types_str
= mputprintf(fp_types_str
,
399 "param_types[%d] = \"%s\";\n", (int)i
, fp_type_str
);
400 fp_add_var_str
= generate_code_debugger_add_var(fp_add_var_str
, fp
);
402 str
= mputprintf(str
,
403 "charstring_list param_names;\n"
405 "charstring_list param_types;\n"
407 "TTCN3_Debug_Function debug_scope(\"%s\", \"%s\", \"%s\", param_names, param_types, %s);\n"
409 "debug_scope.initial_snapshot();\n"
410 , fp_names_str
, fp_types_str
411 , func_ass
->get_id().get_dispname().c_str(), func_type_str
412 , func_ass
->get_my_scope()->get_scope_mod()->get_modid().get_ttcnname().c_str()
413 , comp_str
.c_str(), fp_add_var_str
);
416 Free(fp_add_var_str
);
420 str
= mputprintf(str
,
421 "charstring_list no_params = NULL_VALUE;\n"
422 "TTCN3_Debug_Function debug_scope(\"%s\", \"%s\", \"%s\", no_params, no_params, %s);\n"
423 "debug_scope.initial_snapshot();\n"
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()
This page took 0.040897 seconds and 5 git commands to generate.