Debugger - Stage 3 (artf511247)
[deliverable/titan.core.git] / compiler2 / ttcn3 / AST_ttcn3.cc
index 8449e696bcd62947a0bdd1b3dac1a9ae6a5a4895..6859e36cc11c7b90c97f61bc1d2e7e2f15091a43 100644 (file)
@@ -1,10 +1,24 @@
-///////////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2000-2014 Ericsson Telecom AB
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// which accompanies this distribution, and is available at
-// http://www.eclipse.org/legal/epl-v10.html
-///////////////////////////////////////////////////////////////////////////////
+/******************************************************************************
+ * Copyright (c) 2000-2016 Ericsson Telecom AB
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Baji, Laszlo
+ *   Balasko, Jeno
+ *   Baranyi, Botond
+ *   Beres, Szabolcs
+ *   Delic, Adam
+ *   Kovacs, Ferenc
+ *   Raduly, Csaba
+ *   Szabados, Kristof
+ *   Szalai, Gabor
+ *   Zalanyi, Balazs Andor
+ *   Pandi, Krisztian
+ *
+ ******************************************************************************/
 #include "../../common/dbgnew.hh"
 #include "AST_ttcn3.hh"
 #include "../Identifier.hh"
@@ -29,6 +43,7 @@
 #include "../../common/version_internal.h"
 #include "../CodeGenHelper.hh"
 #include "../../common/JSON_Tokenizer.hh"
+#include "../DebuggerStuff.hh"
 #include <limits.h>
 
 // implemented in coding_attrib_p.y
@@ -178,6 +193,25 @@ namespace Ttcn {
       str += "<unknown sub-reference>";
     }
   }
+  
+  void FieldOrArrayRef::set_field_name_to_lowercase()
+  {
+    if (ref_type != FIELD_REF) FATAL_ERROR("FieldOrArrayRef::set_field_name_to_lowercase()");
+    string new_name = u.id->get_name();
+    if (isupper(new_name[0])) {
+      new_name[0] = tolower(new_name[0]);
+      if (new_name[new_name.size() - 1] == '_') {
+        // an underscore is inserted at the end of the field name if it's
+        // a basic type's name (since it would conflict with the class generated
+        // for that type)
+        // remove the underscore, it won't conflict with anything if its name
+        // starts with a lowercase letter
+        new_name.replace(new_name.size() - 1, 1, "");
+      }
+      delete u.id;
+      u.id = new Identifier(Identifier::ID_NAME, new_name);
+    }
+  }
 
   // =================================
   // ===== FieldOrArrayRefs
@@ -582,9 +616,42 @@ namespace Ttcn {
     }
     return true;
   }
+  
+  void Reference::ref_usage_found()
+  {
+    Common::Assignment *ass = get_refd_assignment();
+    if (!ass) FATAL_ERROR("Reference::ref_usage_found()");
+    switch (ass->get_asstype()) {
+    case Common::Assignment::A_PAR_VAL_OUT:
+    case Common::Assignment::A_PAR_TEMPL_OUT:
+    case Common::Assignment::A_PAR_VAL:
+    case Common::Assignment::A_PAR_VAL_IN:
+    case Common::Assignment::A_PAR_VAL_INOUT:
+    case Common::Assignment::A_PAR_TEMPL_IN:
+    case Common::Assignment::A_PAR_TEMPL_INOUT:
+    case Common::Assignment::A_PAR_PORT:
+    case Common::Assignment::A_PAR_TIMER: {
+      FormalPar *fpar = dynamic_cast<FormalPar*>(ass);
+      if (fpar == NULL) {
+        FATAL_ERROR("Reference::ref_usage_found()");
+      }
+      fpar->set_usage_found();
+      break; }
+    case Common::Assignment::A_EXT_CONST: {
+      Def_ExtConst* def = dynamic_cast<Def_ExtConst*>(ass);
+      if (def == NULL) {
+        FATAL_ERROR("Reference::ref_usage_found()");
+      }
+      def->set_usage_found();
+      break; }
+    default:
+      break;
+    }
+  }
 
   void Reference::generate_code(expression_struct_t *expr)
   {
+    ref_usage_found();
     Common::Assignment *ass = get_refd_assignment();
     if (!ass) FATAL_ERROR("Reference::generate_code()");
     if (parlist) {
@@ -611,7 +678,8 @@ namespace Ttcn {
       generate_code(expr);
       return;
     }
-
+    
+    ref_usage_found();
     Common::Assignment *ass = get_refd_assignment();
     if (!ass) FATAL_ERROR("Reference::generate_code_const_ref()");
 
@@ -672,6 +740,7 @@ namespace Ttcn {
   void Reference::generate_code_portref(expression_struct_t *expr,
     Scope *p_scope)
   {
+    ref_usage_found();
     Common::Assignment *ass = get_refd_assignment();
     if (!ass) FATAL_ERROR("Reference::generate_code_portref()");
     expr->expr = mputstr(expr->expr,
@@ -683,6 +752,7 @@ namespace Ttcn {
   void Reference::generate_code_ispresentbound(expression_struct_t *expr,
     bool is_template, const bool isbound)
   {
+    ref_usage_found();
     Common::Assignment *ass = get_refd_assignment();
     const string& ass_id = ass->get_genname_from_scope(my_scope);
     const char *ass_id_str = ass_id.c_str();
@@ -706,7 +776,9 @@ namespace Ttcn {
 
       expr->expr = mputprintf(expr->expr, "%s", tmp_generalid_str);
     } else {
-      expr->expr = mputprintf(expr->expr, "%s.%s()", ass_id_str, isbound ? "is_bound":"is_present");
+      expr->expr = mputprintf(expr->expr, "%s.%s(%s)", ass_id_str,
+        isbound ? "is_bound":"is_present",
+        (!isbound && is_template && omit_in_value_list) ? "TRUE" : "");
     }
   }
 
@@ -942,28 +1014,34 @@ namespace Ttcn {
 
     bool is_template;
     switch (ass->get_asstype()) {
+    case Common::Assignment::A_TEMPLATE:
+      if (NULL == ass->get_FormalParList()) {
+        // not a parameterized template
+        is_template = true;
+        break;
+      }
+      // else fall through
     case Common::Assignment::A_CONST:
     case Common::Assignment::A_EXT_CONST:
     case Common::Assignment::A_ALTSTEP:
     case Common::Assignment::A_TESTCASE:
     case Common::Assignment::A_FUNCTION:
     case Common::Assignment::A_EXT_FUNCTION:
+    case Common::Assignment::A_FUNCTION_RVAL:
+    case Common::Assignment::A_EXT_FUNCTION_RVAL:
+    case Common::Assignment::A_FUNCTION_RTEMP:
+    case Common::Assignment::A_EXT_FUNCTION_RTEMP:
       generate_code(expr);
       return;
     case Common::Assignment::A_MODULEPAR:
     case Common::Assignment::A_VAR:
-    case Common::Assignment::A_FUNCTION_RVAL:
-    case Common::Assignment::A_EXT_FUNCTION_RVAL:
     case Common::Assignment::A_PAR_VAL_IN:
     case Common::Assignment::A_PAR_VAL_OUT:
     case Common::Assignment::A_PAR_VAL_INOUT: {
       is_template = false;
       break; }
     case Common::Assignment::A_MODULEPAR_TEMP:
-    case Common::Assignment::A_TEMPLATE:
     case Common::Assignment::A_VAR_TEMPLATE:
-    case Common::Assignment::A_FUNCTION_RTEMP:
-    case Common::Assignment::A_EXT_FUNCTION_RTEMP:
     case Common::Assignment::A_PAR_TEMPL_IN:
     case Common::Assignment::A_PAR_TEMPL_OUT:
     case Common::Assignment::A_PAR_TEMPL_INOUT: {
@@ -1386,7 +1464,7 @@ namespace Ttcn {
                     result = NULL;
                   } else {
                   loc->error(
-                  "It is not possible to resolve the reference unambigously"
+                  "It is not possible to resolve the reference unambiguously"
                   ", as it can be resolved to `%s' and to `%s'",
                        result->get_fullname().c_str(), t_ass->get_fullname().c_str());
                   }
@@ -1578,7 +1656,7 @@ namespace Ttcn {
             result = NULL;
           } else {
           loc->error(
-          "It is not possible to resolve the reference unambigously"
+          "It is not possible to resolve the reference unambiguously"
           ", as it can be resolved to `%s' and to `%s'",
             result->get_fullname().c_str(), ass->get_fullname().c_str());
         }
@@ -1603,13 +1681,11 @@ namespace Ttcn {
 
   void Imports::generate_code(output_struct *target)
   {
-    bool base_lib_needed = true;
+    target->header.includes = mputstr(target->header.includes,
+      "#include <TTCN3.hh>\n");
     for (size_t i = 0; i < impmods_v.size(); i++) {
       ImpMod *im = impmods_v[i];
       Common::Module *m = im->get_mod();
-      // do not include the header file of the base library if a real
-      // (not circular) imported module is found
-      if (base_lib_needed && !m->is_visible(my_mod)) base_lib_needed = false;
       // inclusion of m's header file can be eliminated if we find another
       // imported module that imports m
       bool covered = false;
@@ -1631,12 +1707,6 @@ namespace Ttcn {
       // do not generate the #include if a covering module is found
       if (!covered) im->generate_code(target);
     }
-    if (base_lib_needed) {
-      // if no real import was found the base library definitions has to be
-      // #include'd
-      target->header.includes = mputstr(target->header.includes,
-        "#include <TTCN3.hh>\n");
-    }
   }
 
   void Imports::generate_code(CodeGenHelper& cgh) {
@@ -2031,6 +2101,12 @@ namespace Ttcn {
       module_dispname);
     target->functions.control = mputprintf(target->functions.control,
       "TTCN_Runtime::begin_controlpart(\"%s\");\n", module_dispname);
+    if (debugger_active) {
+      target->functions.control = mputprintf(target->functions.control,
+        "charstring_list no_params = NULL_VALUE;\n"
+        "TTCN3_Debug_Function debug_scope(NULL, \"control\", \"%s\", no_params, no_params, NULL);\n"
+        "debug_scope.initial_snapshot();\n", module_dispname);
+    }
     target->functions.control =
       block->generate_code(target->functions.control);
     target->functions.control = mputstr(target->functions.control,
@@ -2203,7 +2279,7 @@ namespace Ttcn {
                   result_ass = t_ass;
                 } else if(result_ass != t_ass) {
                   p_ref->error(
-                  "It is not possible to resolve the reference unambigously"
+                  "It is not possible to resolve the reference unambiguously"
                   ", as it can be resolved to `%s' and to `%s'",
                     result_ass->get_fullname().c_str(), t_ass->get_fullname().c_str());
                 }
@@ -2273,7 +2349,7 @@ namespace Ttcn {
                 t_result = t_ass;
               } else if(t_result != t_ass) {
                 p_ref->error(
-                "It is not possible to resolve the reference unambigously"
+                "It is not possible to resolve the reference unambiguously"
                 ", as it can be resolved to `%s' and to `%s'",
                   t_result->get_fullname().c_str(), t_ass->get_fullname().c_str());
               }
@@ -2745,6 +2821,176 @@ namespace Ttcn {
       }
     }
   }
+  
+  void Module::generate_debugger_init(output_struct* output)
+  {
+    static boolean first = TRUE;
+    // create the initializer function
+    output->source.global_vars = mputprintf(output->source.global_vars,
+      "\n/* Initializing the TTCN-3 debugger */\n"
+      "void init_ttcn3_debugger()\n"
+      "{\n"
+      "%s", first ? "  ttcn3_debugger.activate();\n" : "");
+    first = FALSE;
+    
+    // initialize global scope and variables (including imported variables)
+    char* str_glob = generate_debugger_global_vars(NULL, this);
+    for (int i = 0; i < imp->get_imports_size(); ++i) {
+      str_glob = imp->get_impmod(i)->get_mod()->generate_debugger_global_vars(str_glob, this);
+    }
+    if (str_glob != NULL) {
+      // only add the global scope if it actually has variables
+      output->source.global_vars = mputprintf(output->source.global_vars,
+        "  /* global variables */\n"
+        "  TTCN3_Debug_Scope* global_scope = ttcn3_debugger.add_global_scope(\"%s\");\n"
+        "%s",
+        get_modid().get_dispname().c_str(), str_glob);
+      Free(str_glob);
+    }
+    
+    // initialize components' scopes and their variables
+    for (size_t i = 0; i < asss->get_nof_asss(); ++i) {
+      Def_Type* def = dynamic_cast<Def_Type*>(asss->get_ass_byIndex(i));
+      if (def != NULL) {
+        Type* comp_type = def->get_Type();
+        if (comp_type->get_typetype() == Type::T_COMPONENT) {
+          char* str_comp = NULL;
+          ComponentTypeBody* comp_body = comp_type->get_CompBody();
+          for (size_t j = 0; j < comp_body->get_nof_asss(); ++j) {
+            str_comp = generate_code_debugger_add_var(str_comp, comp_body->get_ass_byIndex(j),
+              this, comp_type->get_dispname().c_str());
+          }
+          if (str_comp != NULL) {
+            // only add the component if it actually has variables
+            output->source.global_vars = mputprintf(output->source.global_vars,
+              "  /* variables of component %s */\n"
+              "  TTCN3_Debug_Scope* %s_scope = ttcn3_debugger.add_component_scope(\"%s\");\n"
+              "%s"
+              , comp_type->get_dispname().c_str(), comp_type->get_dispname().c_str()
+              , comp_type->get_dispname().c_str(), str_comp);
+            Free(str_comp);
+          }
+        }
+      }
+    }
+    
+    // close the initializer function
+    output->source.global_vars = mputstr(output->source.global_vars, "}\n");
+  }
+  
+  char* Module::generate_debugger_global_vars(char* str, Common::Module* current_mod)
+  {
+    for (size_t i = 0; i < asss->get_nof_asss(); ++i) {
+      Common::Assignment* ass = asss->get_ass_byIndex(i);
+      switch (ass->get_asstype()) {
+      case Common::Assignment::A_TEMPLATE:
+        if (ass->get_FormalParList() != NULL) {
+          // don't add parameterized templates, since they are functions in C++
+          break;
+        }
+        // else fall through
+      case Common::Assignment::A_CONST:
+      case Common::Assignment::A_MODULEPAR:
+      case Common::Assignment::A_MODULEPAR_TEMP:
+        str = generate_code_debugger_add_var(str, ass, current_mod, "global");
+        break;
+      case Common::Assignment::A_EXT_CONST: {
+        Def_ExtConst* def = dynamic_cast<Def_ExtConst*>(ass);
+        if (def == NULL) {
+          FATAL_ERROR("Module::generate_debugger_global_vars");
+        }
+        if (def->is_used()) {
+          str = generate_code_debugger_add_var(str, ass, current_mod, "global");
+        }
+        break; }
+      default:
+        break;
+      }
+    }
+    return str;
+  }
+  
+  void Module::generate_debugger_functions(output_struct *output)
+  {
+    char* print_str = NULL;
+    char* overwrite_str = NULL;
+    for (size_t i = 0; i < asss->get_nof_asss(); ++i) {
+      Def_Type* def = dynamic_cast<Def_Type*>(asss->get_ass_byIndex(i));
+      if (def != NULL) {
+        Type* t = def->get_Type();
+        if (!t->is_ref() && t->get_typetype() != Type::T_COMPONENT) {
+          // don't generate code for subtypes
+          if (t->get_typetype() != Type::T_SIGNATURE) {
+            print_str = mputprintf(print_str, 
+              "  %sif (!strcmp(p_var.type_name, \"%s\")) {\n"
+              "    ((const %s*)ptr)->log();\n"
+              "  }\n"
+              , (print_str != NULL) ? "else " : ""
+              , t->get_dispname().c_str(), t->get_genname_value(this).c_str());
+            if (t->get_typetype() != Type::T_PORT) {
+              overwrite_str = mputprintf(overwrite_str,
+                "  %sif (!strcmp(p_var.type_name, \"%s\")) {\n"
+                "    ((%s*)p_var.value)->set_param(p_new_value);\n"
+                "  }\n"
+                , (overwrite_str != NULL) ? "else " : ""
+                , t->get_dispname().c_str(), t->get_genname_value(this).c_str());
+            }
+          }
+          if (t->get_typetype() != Type::T_PORT) {
+            print_str = mputprintf(print_str,
+              "  %sif (!strcmp(p_var.type_name, \"%s template\")) {\n"
+              "    ((const %s_template*)ptr)->log();\n"
+              "  }\n"
+              , (print_str != NULL) ? "else " : ""
+              , t->get_dispname().c_str(), t->get_genname_value(this).c_str());
+            if (t->get_typetype() != Type::T_SIGNATURE) {
+              overwrite_str = mputprintf(overwrite_str,
+                "  %sif (!strcmp(p_var.type_name, \"%s template\")) {\n"
+                "    ((%s_template*)p_var.value)->set_param(p_new_value);\n"
+                "  }\n"
+                , (overwrite_str != NULL) ? "else " : ""
+                , t->get_dispname().c_str(), t->get_genname_value(this).c_str());
+            }
+          }
+        }
+      }
+    }
+    if (print_str != NULL) {
+      // don't generate an empty printing function
+      output->header.class_defs = mputprintf(output->header.class_defs,
+        "/* Debugger printing and overwriting functions for types declared in this module */\n\n"
+        "extern CHARSTRING print_var_%s(const TTCN3_Debugger::variable_t& p_var);\n",
+        get_modid().get_ttcnname().c_str());
+      output->source.global_vars = mputprintf(output->source.global_vars,
+        "\n/* Debugger printing function for types declared in this module */\n"
+        "CHARSTRING print_var_%s(const TTCN3_Debugger::variable_t& p_var)\n"
+        "{\n"
+        "  const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue;\n"
+        "  TTCN_Logger::begin_event_log2str();\n"
+        "%s"
+        "  else {\n"
+        "    TTCN_Logger::log_event_str(\"<unrecognized value or template>\");\n"
+        "  }\n"
+        "  return TTCN_Logger::end_event_log2str();\n"
+        "}\n", get_modid().get_ttcnname().c_str(), print_str);
+    }
+    if (overwrite_str != NULL) {
+      // don't generate an empty overwriting function
+      output->header.class_defs = mputprintf(output->header.class_defs,
+        "extern boolean set_var_%s(TTCN3_Debugger::variable_t& p_var, Module_Param& p_new_value);\n",
+        get_modid().get_ttcnname().c_str());
+      output->source.global_vars = mputprintf(output->source.global_vars,
+        "\n/* Debugger overwriting function for types declared in this module */\n"
+        "boolean set_var_%s(TTCN3_Debugger::variable_t& p_var, Module_Param& p_new_value)\n"
+        "{\n"
+        "%s"
+        "  else {\n"
+        "    return FALSE;\n"
+        "  }\n"
+        "  return TRUE;\n"
+        "}\n", get_modid().get_ttcnname().c_str(), overwrite_str);
+    }
+  }
 
   // =================================
   // ===== Definition
@@ -3321,6 +3567,9 @@ namespace Ttcn {
       // the value is assigned using subsequent statements
       str = value->generate_code_init(str, genname_str);
     }
+    if (debugger_active) {
+      str = generate_code_debugger_add_var(str, this);
+    }
     return str;
   }
 
@@ -3359,6 +3608,7 @@ namespace Ttcn {
     if (!p_type) FATAL_ERROR("Ttcn::Def_ExtConst::Def_ExtConst()");
     type = p_type;
     type->set_ownertype(Type::OT_CONST_DEF, this);
+    usage_found = false;
   }
 
   Def_ExtConst::~Def_ExtConst()
@@ -3585,6 +3835,10 @@ namespace Ttcn {
       "modulepar_%s.set_param(param);\n"
       "return TRUE;\n"
       "} else ", dispname, name);
+    target->functions.get_param = mputprintf(target->functions.get_param,
+      "if (!strcmp(par_name, \"%s\")) {\n"
+      "return modulepar_%s.get_param(param_name);\n"
+      "} else ", dispname, name);
 
     if (target->functions.log_param) {
       // this is not the first modulepar
@@ -3753,6 +4007,10 @@ namespace Ttcn {
       "modulepar_%s.set_param(param);\n"
       "return TRUE;\n"
       "} else ", dispname, name);
+    target->functions.get_param = mputprintf(target->functions.get_param,
+      "if (!strcmp(par_name, \"%s\")) {\n"
+      "return modulepar_%s.get_param(param_name);\n"
+      "} else ", dispname, name);
 
     if (target->functions.log_param) {
       // this is not the first modulepar
@@ -3922,7 +4180,7 @@ namespace Ttcn {
       Error_Context ec(this, "While checking template restriction `%s'",
                        Template::get_restriction_name(template_restriction));
       gen_restriction_check =
-        body->chk_restriction("template definition", template_restriction);
+        body->chk_restriction("template definition", template_restriction, body);
       if (fp_list && template_restriction!=TR_PRESENT) {
         size_t nof_fps = fp_list->get_nof_fps();
         for (size_t i=0; i<nof_fps; i++) {
@@ -4156,16 +4414,15 @@ namespace Ttcn {
       const char *template_dispname = id->get_dispname().c_str();
       const string& type_genname = type->get_genname_template(my_scope);
       const char *type_genname_str = type_genname.c_str();
-      char *formal_par_list = fp_list->generate_code(memptystr());
-      fp_list->generate_code_defval(target);
-      target->header.function_prototypes =
-        mputprintf(target->header.function_prototypes,
-          "extern %s %s(%s);\n",
-          type_genname_str, template_name, formal_par_list);
-      char *function_body = mprintf("%s %s(%s)\n"
-        "{\n", type_genname_str, template_name, formal_par_list);
-      function_body = create_location_object(function_body, "TEMPLATE",
+      
+      // assemble the function body first (this also determines which parameters
+      // are never used)
+      size_t nof_base_pars = 0;
+      char* function_body = create_location_object(memptystr(), "TEMPLATE",
         template_dispname);
+      if (debugger_active) {
+        function_body = generate_code_debugger_function_init(function_body, this);
+      }
       if (base_template) {
         // modified template
         function_body = mputprintf(function_body, "%s ret_val(%s",
@@ -4174,7 +4431,7 @@ namespace Ttcn {
         if (base_template->fp_list) {
           // the base template is also parameterized
           function_body = mputc(function_body, '(');
-          size_t nof_base_pars = base_template->fp_list->get_nof_fps();
+          nof_base_pars = base_template->fp_list->get_nof_fps();
           for (size_t i = 0; i < nof_base_pars; i++) {
             if (i > 0) function_body = mputstr(function_body, ", ");
             function_body = mputstr(function_body,
@@ -4196,10 +4453,27 @@ namespace Ttcn {
       if (template_restriction!=TR_NONE && gen_restriction_check)
         function_body = Template::generate_restriction_check_code(function_body,
                           "ret_val", template_restriction);
-      function_body = mputstr(function_body, "return ret_val;\n"
-        "}\n\n");
-      target->source.function_bodies =
-        mputstr(target->source.function_bodies, function_body);
+      if (debugger_active) {
+        function_body = mputstr(function_body,
+          "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
+          "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
+      }
+      function_body = mputstr(function_body, "return ret_val;\n");
+      // if the template modifies a parameterized template, then the inherited
+      // formal parameters must always be displayed, otherwise generate a smart
+      // formal parameter list (where the names of unused parameters are omitted)
+      char *formal_par_list = fp_list->generate_code(memptystr(), nof_base_pars);
+      fp_list->generate_code_defval(target);
+      
+      target->header.function_prototypes =
+        mputprintf(target->header.function_prototypes,
+          "extern %s %s(%s);\n",
+          type_genname_str, template_name, formal_par_list);
+      target->source.function_bodies = mputprintf(target->source.function_bodies,
+        "%s %s(%s)\n"
+        "{\n"
+        "%s"
+        "}\n\n", type_genname_str, template_name, formal_par_list, function_body);
       Free(formal_par_list);
       Free(function_body);
     } else {
@@ -4314,6 +4588,8 @@ namespace Ttcn {
           // the object is initialized by the constructor
           str = mputprintf(str, "%s %s(%s);\n", type_genname_str,
           genname_str, body->get_single_expr(false).c_str());
+          // make sure the template's code is not generated twice (TR: HU56425)
+          body->set_code_generated();
         } else {
           // the default constructor is used
           str = mputprintf(str, "%s %s;\n", type_genname_str, genname_str);
@@ -4325,6 +4601,9 @@ namespace Ttcn {
         str = Template::generate_restriction_check_code(str, genname_str,
           template_restriction);
     }
+    if (debugger_active) {
+      str = generate_code_debugger_add_var(str, this);
+    }
     return str;
   }
 
@@ -4548,6 +4827,9 @@ namespace Ttcn {
         str = initial_value->generate_code_init(str, genname_str);
       }
     }
+    if (debugger_active) {
+      str = generate_code_debugger_add_var(str, this);
+    }
     return str;
   }
 
@@ -4656,7 +4938,7 @@ namespace Ttcn {
         OMIT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, IMPLICIT_OMIT, 0);
       gen_restriction_check =
         initial_value->chk_restriction("template variable definition",
-                                       template_restriction);
+                                       template_restriction, initial_value);
       if (!semantic_check_only) {
         initial_value->set_genname_recursive(get_genname());
         initial_value->set_code_section(GovernedSimple::CS_INLINE);
@@ -4775,6 +5057,9 @@ namespace Ttcn {
         && gen_restriction_check)
       str = Template::generate_restriction_check_code(str, genname_str,
                                                       template_restriction);
+    if (debugger_active) {
+      str = generate_code_debugger_add_var(str, this);
+    }
     return str;
   }
 
@@ -5293,6 +5578,9 @@ namespace Ttcn {
         }
       }
     }
+    if (debugger_active) {
+      str = generate_code_debugger_add_var(str, this);
+    }
     return str;
   }
 
@@ -5987,6 +6275,18 @@ namespace Ttcn {
       FATAL_ERROR("Def_Function::generate_code()");
     }
     const char *return_type_str = return_type_name.c_str();
+    
+    // assemble the function body first (this also determines which parameters
+    // are never used)
+    char* body = create_location_object(memptystr(), "FUNCTION", dispname_str);
+    if (!enable_set_bound_out_param)
+      body = fp_list->generate_code_set_unbound(body); // conform the standard out parameter is unbound
+    body = fp_list->generate_shadow_objects(body);
+    if (debugger_active) {
+      body = generate_code_debugger_function_init(body, this);
+    }
+    body = block->generate_code(body);
+    // smart formal parameter list (names of unused parameters are omitted)
     char *formal_par_list = fp_list->generate_code(memptystr());
     fp_list->generate_code_defval(target);
     // function prototype
@@ -5994,34 +6294,32 @@ namespace Ttcn {
       mputprintf(target->header.function_prototypes, "extern %s %s(%s);\n",
         return_type_str, genname_str, formal_par_list);
 
-    // function body
-    char *body = mprintf("%s %s(%s)\n"
-      "{\n", return_type_str, genname_str, formal_par_list);
-    body = create_location_object(body, "FUNCTION", dispname_str);
-    if (!enable_set_bound_out_param)
-      body = fp_list->generate_code_set_unbound(body); // conform the standard out parameter is unbound
-    body = fp_list->generate_shadow_objects(body);
-    body = block->generate_code(body);
-    body = mputstr(body, "}\n\n");
-    target->source.function_bodies = mputstr(target->source.function_bodies,
-      body);
+    // function body    
+    target->source.function_bodies = mputprintf(target->source.function_bodies,
+      "%s %s(%s)\n"
+      "{\n"
+      "%s"
+      "}\n\n", return_type_str, genname_str, formal_par_list, body);
+    Free(formal_par_list);
     Free(body);
 
     if (is_startable) {
       size_t nof_fps = fp_list->get_nof_fps();
+      // use the full list of formal parameters here (since they are all logged)
+      char *full_formal_par_list = fp_list->generate_code(memptystr(), nof_fps);
       // starter function (stub)
         // function prototype
         target->header.function_prototypes =
           mputprintf(target->header.function_prototypes,
             "extern void start_%s(const COMPONENT& component_reference%s%s);\n",
-            genname_str, nof_fps>0?", ":"", formal_par_list);
+            genname_str, nof_fps>0?", ":"", full_formal_par_list);
         // function body
         body = mprintf("void start_%s(const COMPONENT& component_reference%s"
             "%s)\n"
           "{\n"
           "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
           "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
-          genname_str, nof_fps>0?", ":"", formal_par_list, dispname_str);
+          genname_str, nof_fps>0?", ":"", full_formal_par_list, dispname_str);
         for (size_t i = 0; i < nof_fps; i++) {
           if (i > 0) body = mputstr(body,
              "TTCN_Logger::log_event_str(\", \");\n");
@@ -6113,8 +6411,8 @@ namespace Ttcn {
         "} else ");
       target->functions.start = mputstr(target->functions.start, body);
       Free(body);
+      Free(full_formal_par_list);
     }
-    Free(formal_par_list);
 
     target->functions.pre_init = mputprintf(target->functions.pre_init,
       "%s.add_function(\"%s\", (genericfunc_t)&%s, ", get_module_object_name(),
@@ -6234,35 +6532,55 @@ namespace Ttcn {
       }
 
       if (input_type) {
-        if (!input_type->has_encoding(encoding_type)) {
-          input_type->error("Input type `%s' does not support %s encoding",
-            input_type->get_typename().c_str(),
-            Type::get_encoding_name(encoding_type));
+        if (!input_type->has_encoding(encoding_type, encoding_options)) {
+          if (Common::Type::CT_CUSTOM == encoding_type) {
+            input_type->error("Input type `%s' does not support custom encoding '%s'",
+              input_type->get_typename().c_str(), encoding_options->c_str());
+          }
+          else {
+            input_type->error("Input type `%s' does not support %s encoding",
+              input_type->get_typename().c_str(),
+              Type::get_encoding_name(encoding_type));
+          }
         }
-        if (Common::Type::CT_XER == encoding_type
-          && input_type->get_type_refd_last()->is_untagged()) {
-          // "untagged" on the (toplevel) input type will have no effect.
-          warning("UNTAGGED encoding attribute is ignored on top-level type");
+        else {
+          if (Common::Type::CT_XER == encoding_type
+            && input_type->get_type_refd_last()->is_untagged()) {
+            // "untagged" on the (toplevel) input type will have no effect.
+            warning("UNTAGGED encoding attribute is ignored on top-level type");
+          }
+          if (Common::Type::CT_CUSTOM == encoding_type) {
+            if (PROTOTYPE_CONVERT != prototype) {
+              error("Only `prototype(convert)' is allowed for custom encoding functions");
+            }
+            else {
+              // let the input type know that this is its encoding function
+              input_type->get_type_refd()->set_coding_function(true,
+                get_genname_from_scope(input_type->get_type_refd()->get_my_scope()));
+              // treat this as a manual external function during code generation
+              function_type = EXTFUNC_MANUAL;
+            }
+          }
         }
       }
       if (output_type) {
-        if(encoding_type == Common::Type::CT_TEXT){  // the TEXT encoding support both octetstring ans charstring stream type
+        if(encoding_type == Common::Type::CT_TEXT) { // TEXT encoding supports both octetstring and charstring stream types
           Type *stream_type = Type::get_stream_type(encoding_type,0);
           Type *stream_type2 = Type::get_stream_type(encoding_type,1);
           if ( (!stream_type->is_identical(output_type)) && (!stream_type2->is_identical(output_type)) ) {
-            input_type->error("The output type of %s encoding should be `%s' or `%s' "
+            output_type->error("The output type of %s encoding should be `%s' or `%s' "
               "instead of `%s'", Type::get_encoding_name(encoding_type),
               stream_type->get_typename().c_str(),
               stream_type2->get_typename().c_str(),
-              input_type->get_typename().c_str());
+              output_type->get_typename().c_str());
           }
         } else {
           Type *stream_type = Type::get_stream_type(encoding_type);
           if (!stream_type->is_identical(output_type)) {
-            input_type->error("The output type of %s encoding should be `%s' "
+            output_type->error("The output type of %s encoding should be `%s' "
               "instead of `%s'", Type::get_encoding_name(encoding_type),
               stream_type->get_typename().c_str(),
-              input_type->get_typename().c_str());
+              output_type->get_typename().c_str());
           }
         }
       }
@@ -6274,11 +6592,11 @@ namespace Ttcn {
         error("Attribute `decode' cannot be used without `prototype'");
       }
       if (input_type) {
-        if(encoding_type == Common::Type::CT_TEXT){  // the TEXT encoding support both octetstring ans charstring stream type
+        if(encoding_type == Common::Type::CT_TEXT) { // TEXT encoding supports both octetstring and charstring stream types
           Type *stream_type = Type::get_stream_type(encoding_type,0);
           Type *stream_type2 = Type::get_stream_type(encoding_type,1);
           if ( (!stream_type->is_identical(input_type)) && (!stream_type2->is_identical(input_type)) ) {
-            input_type->error("The input type of %s encoding should be `%s' or `%s' "
+            input_type->error("The input type of %s decoding should be `%s' or `%s' "
               "instead of `%s'", Type::get_encoding_name(encoding_type),
               stream_type->get_typename().c_str(),
               stream_type2->get_typename().c_str(),
@@ -6287,7 +6605,7 @@ namespace Ttcn {
         } else {
           Type *stream_type = Type::get_stream_type(encoding_type);
           if (!stream_type->is_identical(input_type)) {
-            input_type->error("The input type of %s encoding should be `%s' "
+            input_type->error("The input type of %s decoding should be `%s' "
               "instead of `%s'", Type::get_encoding_name(encoding_type),
               stream_type->get_typename().c_str(),
               input_type->get_typename().c_str());
@@ -6295,10 +6613,30 @@ namespace Ttcn {
         }
         
       }
-      if (output_type && !output_type->has_encoding(encoding_type)) {
-        output_type->error("Output type `%s' does not support %s encoding",
-          output_type->get_typename().c_str(),
-          Type::get_encoding_name(encoding_type));
+      if (output_type && !output_type->has_encoding(encoding_type, encoding_options)) {
+        if (Common::Type::CT_CUSTOM == encoding_type) {
+          output_type->error("Output type `%s' does not support custom encoding '%s'",
+            output_type->get_typename().c_str(), encoding_options->c_str());
+        }
+        else {
+          output_type->error("Output type `%s' does not support %s encoding",
+            output_type->get_typename().c_str(),
+            Type::get_encoding_name(encoding_type));
+        }
+      }
+      else {
+        if (Common::Type::CT_CUSTOM == encoding_type) {
+          if (PROTOTYPE_SLIDING != prototype) {
+            error("Only `prototype(sliding)' is allowed for custom decoding functions");
+          }
+          else if (output_type) {
+            // let the output type know that this is its decoding function
+            output_type->get_type_refd()->set_coding_function(false,
+              get_genname_from_scope(output_type->get_type_refd()->get_my_scope()));
+            // treat this as a manual external function during code generation
+            function_type = EXTFUNC_MANUAL;
+          }
+        }
       }
       if (eb_list) eb_list->chk();
       chk_allowed_encode();
@@ -6329,6 +6667,8 @@ namespace Ttcn {
     case Type::CT_JSON:
       if (enable_json()) return;
       break;
+    case Type::CT_CUSTOM:
+      return; // cannot be disabled
     default:
       FATAL_ERROR("Def_ExtFunction::chk_allowed_encode");
       break;
@@ -6510,7 +6850,14 @@ namespace Ttcn {
       "TTCN_Logger::end_event();\n"
       "}\n", result_name, function_name, result_name);
     // returning the result stream if necessary
-    if (prototype == PROTOTYPE_CONVERT) str = mputstr(str, "return ret_val;\n");
+    if (prototype == PROTOTYPE_CONVERT) {
+      if (debugger_active) {
+        str = mputstr(str,
+          "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
+          "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
+      }
+      str = mputstr(str, "return ret_val;\n");
+    }
     return str;
   }
 
@@ -6591,12 +6938,28 @@ namespace Ttcn {
         "}\n", input_type->get_genname_value(my_scope).c_str(), function_name);
       // closing the block and returning the appropriate result or status code
       if (prototype == PROTOTYPE_BACKTRACK) {
-        str = mputstr(str, "return 0;\n"
-          "} else return 1;\n");
+        if (debugger_active) {
+          str = mputstr(str, "ttcn3_debugger.set_return_value(\"0\");\n");
+        }
+        str = mputstr(str,
+          "return 0;\n"
+          "} else {\n");
+        if (debugger_active) {
+          str = mputstr(str, "ttcn3_debugger.set_return_value(\"1\");\n");
+        }
+        str = mputstr(str,  
+          "return 1;\n"
+          "}\n");
       } else {
         str = mputstr(str, "}\n");
-        if (prototype == PROTOTYPE_CONVERT)
+        if (prototype == PROTOTYPE_CONVERT) {
+          if (debugger_active) {
+            str = mputstr(str,
+              "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
+              "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
+          }
           str = mputstr(str, "return ret_val;\n");
+        }
       }
     } else {
       // result handling and debug printout for sliding decoders
@@ -6611,13 +6974,16 @@ namespace Ttcn {
         "%s.log();\n"
         "TTCN_Logger::end_event();\n"
         "}\n"
-        "return 0;\n"
+        "%sreturn 0;\n"
         "case TTCN_EncDec::ET_INCOMPL_MSG:\n"
         "case TTCN_EncDec::ET_LEN_ERR:\n"
-        "return 2;\n"
+        "%sreturn 2;\n"
         "default:\n"
-        "return 1;\n"
-        "}\n", first_par_name, function_name, first_par_name);
+        "%sreturn 1;\n"
+        "}\n", first_par_name, function_name, first_par_name,
+        debugger_active ? "ttcn3_debugger.set_return_value(\"0\");\n" : "",
+        debugger_active ? "ttcn3_debugger.set_return_value(\"2\");\n" : "",
+        debugger_active ? "ttcn3_debugger.set_return_value(\"1\");\n" : "");
     }
     return str;
   }
@@ -6641,7 +7007,7 @@ namespace Ttcn {
       FATAL_ERROR("Def_ExtFunction::generate_code()");
     }
     const char *return_type_str = return_type_name.c_str();
-    char *formal_par_list = fp_list->generate_code(memptystr());
+    char *formal_par_list = fp_list->generate_code(memptystr(), fp_list->get_nof_fps());
     fp_list->generate_code_defval(target);
     // function prototype
     target->header.function_prototypes =
@@ -6659,6 +7025,9 @@ namespace Ttcn {
         "%s %s(%s)\n"
         "{\n"
         , return_type_str, genname_str, formal_par_list);
+      if (debugger_active) {
+        body = generate_code_debugger_function_init(body, this);
+      }
       switch (function_type) {
       case EXTFUNC_ENCODE:
         body = generate_code_encode(body);
@@ -6934,6 +7303,18 @@ namespace Ttcn {
     const string& t_genname = get_genname();
     const char *genname_str = t_genname.c_str();
     const char *dispname_str = id->get_dispname().c_str();
+
+    // function for altstep instance:
+    // assemble the function body first (this also determines which parameters
+    // are never used)
+    char* body = create_location_object(memptystr(), "ALTSTEP", dispname_str);
+    body = fp_list->generate_shadow_objects(body);
+    if (debugger_active) {
+      body = generate_code_debugger_function_init(body, this);
+    }
+    body = sb->generate_code(body);
+    body = ags->generate_code_altstep(body);
+    // generate a smart formal parameter list (omits unused parameter names)
     char *formal_par_list = fp_list->generate_code(memptystr());
     fp_list->generate_code_defval(target);
 
@@ -6943,24 +7324,25 @@ namespace Ttcn {
         "extern alt_status %s_instance(%s);\n", genname_str, formal_par_list);
 
     // function for altstep instance: body
-    char *str = mprintf("alt_status %s_instance(%s)\n"
-      "{\n", genname_str, formal_par_list);
-    str = create_location_object(str, "ALTSTEP", dispname_str);
-    str = fp_list->generate_shadow_objects(str);
-    str = sb->generate_code(str);
-    str = ags->generate_code_altstep(str);
-    str = mputstr(str, "}\n\n");
-    target->source.function_bodies = mputstr(target->source.function_bodies,
-      str);
-    Free(str);
+    target->source.function_bodies = mputprintf(target->source.function_bodies,
+      "alt_status %s_instance(%s)\n"
+      "{\n"
+      "%s"
+      "}\n\n", genname_str, formal_par_list, body);
+    Free(formal_par_list);
+    Free(body);
 
     char *actual_par_list =
       fp_list->generate_code_actual_parlist(memptystr(), "");
+    
+    // use a full formal parameter list for the rest of the functions
+    char *full_formal_par_list = fp_list->generate_code(memptystr(),
+      fp_list->get_nof_fps());
 
     // wrapper function for stand-alone instantiation: prototype
     target->header.function_prototypes =
       mputprintf(target->header.function_prototypes,
-        "extern void %s(%s);\n", genname_str, formal_par_list);
+        "extern void %s(%s);\n", genname_str, full_formal_par_list);
 
     // wrapper function for stand-alone instantiation: body
     target->source.function_bodies =
@@ -6986,23 +7368,23 @@ namespace Ttcn {
         "TTCN_error(\"None of the branches can be chosen in altstep %s.\");\n"
         "else block_flag = TRUE;\n"
         "}\n"
-        "}\n\n", genname_str, formal_par_list, genname_str, actual_par_list,
+        "}\n\n", genname_str, full_formal_par_list, genname_str, actual_par_list,
         dispname_str);
 
     // class for keeping the altstep in the default context
     // the class is for internal use, we do not need to publish it in the
     // header file
-    str = mprintf("class %s_Default : public Default_Base {\n", genname_str);
+    char* str = mprintf("class %s_Default : public Default_Base {\n", genname_str);
     str = fp_list->generate_code_object(str, "par_");
     str = mputprintf(str, "public:\n"
       "%s_Default(%s);\n"
       "alt_status call_altstep();\n"
-      "};\n\n", genname_str, formal_par_list);
+      "};\n\n", genname_str, full_formal_par_list);
     target->source.class_defs = mputstr(target->source.class_defs, str);
     Free(str);
     // member functions of the class
     str = mprintf("%s_Default::%s_Default(%s)\n"
-        " : Default_Base(\"%s\")", genname_str, genname_str, formal_par_list,
+        " : Default_Base(\"%s\")", genname_str, genname_str, full_formal_par_list,
         dispname_str);
     for (size_t i = 0; i < fp_list->get_nof_fps(); i++) {
       const char *fp_name_str =
@@ -7024,18 +7406,18 @@ namespace Ttcn {
     target->header.function_prototypes =
       mputprintf(target->header.function_prototypes,
         "extern Default_Base *activate_%s(%s);\n", genname_str,
-        formal_par_list);
+        full_formal_par_list);
 
     // function for default activation: body
     str = mprintf("Default_Base *activate_%s(%s)\n"
-      "{\n", genname_str, formal_par_list);
+      "{\n", genname_str, full_formal_par_list);
     str = mputprintf(str, "return new %s_Default(%s);\n"
       "}\n\n", genname_str, actual_par_list);
     target->source.function_bodies = mputstr(target->source.function_bodies,
       str);
     Free(str);
 
-    Free(formal_par_list);
+    Free(full_formal_par_list);
     Free(actual_par_list);
 
     target->functions.pre_init = mputprintf(target->functions.pre_init,
@@ -7183,30 +7565,20 @@ namespace Ttcn {
     const string& t_genname = get_genname();
     const char *genname_str = t_genname.c_str();
     const char *dispname_str = id->get_dispname().c_str();
-    // formal parameter list
-    char *formal_par_list = fp_list->generate_code(memptystr());
-    fp_list->generate_code_defval(target);
-    if (fp_list->get_nof_fps() > 0)
-      formal_par_list = mputstr(formal_par_list, ", ");
-    formal_par_list = mputstr(formal_par_list,
-      "boolean has_timer, double timer_value");
-
-    // function prototype
-    target->header.function_prototypes =
-      mputprintf(target->header.function_prototypes,
-        "extern verdicttype testcase_%s(%s);\n", genname_str, formal_par_list);
-
-    // function body
-    char *body = mprintf("verdicttype testcase_%s(%s)\n"
-      "{\n", genname_str, formal_par_list);
-    Free(formal_par_list);
+    
+    // assemble the function body first (this also determines which parameters
+    // are never used)
+    
     // Checking whether the testcase was invoked from another one.
     // At this point the location information should refer to the execute()
     // statement rather than this testcase.
-    body = mputstr(body, "TTCN_Runtime::check_begin_testcase(has_timer, "
+    char* body = mputstr(memptystr(), "TTCN_Runtime::check_begin_testcase(has_timer, "
         "timer_value);\n");
     body = create_location_object(body, "TESTCASE", dispname_str);
     body = fp_list->generate_shadow_objects(body);
+    if (debugger_active) {
+      body = generate_code_debugger_function_init(body, this);
+    }
     body = mputprintf(body, "try {\n"
       "TTCN_Runtime::begin_testcase(\"%s\", \"%s\", ",
       my_scope->get_scope_mod()->get_modid().get_dispname().c_str(),
@@ -7224,10 +7596,28 @@ namespace Ttcn {
       "} catch (const TC_End& tc_end) {\n"
       "TTCN_Logger::log_str(TTCN_FUNCTION, \"Test case %s was stopped.\");\n"
       "}\n", dispname_str);
-    body = mputstr(body, "return TTCN_Runtime::end_testcase();\n"
-      "}\n\n");
-    target->source.function_bodies = mputstr(target->source.function_bodies,
-      body);
+    body = mputstr(body, "return TTCN_Runtime::end_testcase();\n");
+    
+    // smart formal parameter list (names of unused parameters are omitted)
+    char *formal_par_list = fp_list->generate_code(memptystr());
+    fp_list->generate_code_defval(target);
+    if (fp_list->get_nof_fps() > 0)
+      formal_par_list = mputstr(formal_par_list, ", ");
+    formal_par_list = mputstr(formal_par_list,
+      "boolean has_timer, double timer_value");
+
+    // function prototype
+    target->header.function_prototypes =
+      mputprintf(target->header.function_prototypes,
+        "extern verdicttype testcase_%s(%s);\n", genname_str, formal_par_list);
+
+    // function body
+    target->source.function_bodies = mputprintf(target->source.function_bodies,
+      "verdicttype testcase_%s(%s)\n"
+      "{\n"
+      "%s"
+      "}\n\n", genname_str, formal_par_list, body);
+    Free(formal_par_list);
     Free(body);
 
     if (fp_list->get_nof_fps() == 0) {
@@ -7345,7 +7735,7 @@ namespace Ttcn {
     TemplateInstance *p_defval, bool p_lazy_eval)
     : Definition(p_asstype, p_name), type(p_type), my_parlist(0),
     used_as_lvalue(false), template_restriction(TR_NONE),
-    lazy_eval(p_lazy_eval)
+    lazy_eval(p_lazy_eval), defval_generated(false), usage_found(false)
   {
     switch (p_asstype) {
     case A_PAR_VAL:
@@ -7371,7 +7761,7 @@ namespace Ttcn {
     Identifier* p_name, TemplateInstance *p_defval, bool p_lazy_eval)
     : Definition(p_asstype, p_name), type(p_type), my_parlist(0),
     used_as_lvalue(false), template_restriction(p_template_restriction),
-    lazy_eval(p_lazy_eval)
+    lazy_eval(p_lazy_eval), defval_generated(false), usage_found(false)
   {
     switch (p_asstype) {
     case A_PAR_TEMPL_IN:
@@ -7390,7 +7780,8 @@ namespace Ttcn {
   FormalPar::FormalPar(asstype_t p_asstype, Identifier* p_name,
     TemplateInstance *p_defval)
     : Definition(p_asstype, p_name), type(0), my_parlist(0),
-    used_as_lvalue(false), template_restriction(TR_NONE), lazy_eval(false)
+    used_as_lvalue(false), template_restriction(TR_NONE), lazy_eval(false),
+    defval_generated(false), usage_found(false)
   {
     if (p_asstype != A_PAR_TIMER)
       FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
@@ -7787,7 +8178,8 @@ namespace Ttcn {
     if (template_restriction!=TR_NONE) {
       bool needs_runtime_check =
         ret_val->get_TemplateInstance()->chk_restriction(
-          "template formal parameter", template_restriction);
+          "template formal parameter", template_restriction,
+          ret_val->get_TemplateInstance());
       if (needs_runtime_check)
         ret_val->set_gen_restriction_check(template_restriction);
     }
@@ -7887,7 +8279,7 @@ namespace Ttcn {
         case A_PAR_TEMPL_OUT:
         case A_PAR_TEMPL_INOUT: {
           FormalPar* fp = dynamic_cast<FormalPar*>(ass);
-          if (!fp) FATAL_ERROR("Template::chk_restriction_refd()");
+          if (!fp) FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
           refd_tr = fp->get_template_restriction();
         } break;
         default:
@@ -8062,34 +8454,23 @@ namespace Ttcn {
       }
     }
   }
-
-  void FormalPar::generate_code_defval(output_struct *target, bool)
+  
+  char* FormalPar::generate_code_defval(char* str)
   {
-    if (!defval.ap) return;
+    if (!defval.ap || defval_generated) return str;
+    defval_generated = true;
     switch (defval.ap->get_selection()) {
     case ActualPar::AP_VALUE: {
       Value *val = defval.ap->get_Value();
-      const_def cdef;
-      Code::init_cdef(&cdef);
-      type->generate_code_object(&cdef, val);
-      Code::merge_cdef(target, &cdef);
-      Code::free_cdef(&cdef);
       if (use_runtime_2 && TypeConv::needs_conv_refd(val)) {
-        target->functions.post_init = TypeConv::gen_conv_code_refd(target->
-          functions.post_init, val->get_lhs_name().c_str(), val);
+        str = TypeConv::gen_conv_code_refd(str, val->get_lhs_name().c_str(), val);
       } else {
-        target->functions.post_init = val->generate_code_init(
-          target->functions.post_init, val->get_lhs_name().c_str());
+        str = val->generate_code_init(str, val->get_lhs_name().c_str());
       }
       break; }
     case ActualPar::AP_TEMPLATE: {
       TemplateInstance *ti = defval.ap->get_TemplateInstance();
       Template *temp = ti->get_Template();
-      const_def cdef;
-      Code::init_cdef(&cdef);
-      type->generate_code_object(&cdef, temp);
-      Code::merge_cdef(target, &cdef);
-      Code::free_cdef(&cdef);
       Ref_base *dref = ti->get_DerivedRef();
       if (dref) {
         expression_struct expr;
@@ -8097,22 +8478,16 @@ namespace Ttcn {
         expr.expr = mputprintf(expr.expr, "%s = ",
                                temp->get_lhs_name().c_str());
         dref->generate_code(&expr);
-        target->functions.post_init =
-          Code::merge_free_expr(target->functions.post_init, &expr, false);
+        str = Code::merge_free_expr(str, &expr, false);
       }
       if (use_runtime_2 && TypeConv::needs_conv_refd(temp)) {
-        target->functions.post_init = TypeConv::gen_conv_code_refd(target->
-          functions.post_init, temp->get_lhs_name().c_str(), temp);
+        str = TypeConv::gen_conv_code_refd(str, temp->get_lhs_name().c_str(), temp);
       } else {
-        target->functions.post_init =
-          temp->generate_code_init(target->functions.post_init,
-                                   temp->get_lhs_name().c_str());
+        str = temp->generate_code_init(str, temp->get_lhs_name().c_str());
       }
       if (defval.ap->get_gen_restriction_check() != TR_NONE) {
-        target->functions.post_init =
-          Template::generate_restriction_check_code(
-            target->functions.post_init, temp->get_lhs_name().c_str(),
-            defval.ap->get_gen_restriction_check());
+        str = Template::generate_restriction_check_code(str,
+          temp->get_lhs_name().c_str(), defval.ap->get_gen_restriction_check());
       }
       break; }
     case ActualPar::AP_REF:
@@ -8120,11 +8495,45 @@ namespace Ttcn {
     default:
       FATAL_ERROR("FormalPar::generate_code()");
     }
+    return str;
   }
 
-  char *FormalPar::generate_code_fpar(char *str)
+  void FormalPar::generate_code_defval(output_struct *target, bool)
   {
-    const char *name_str = id->get_name().c_str();
+    if (!defval.ap) return;
+    switch (defval.ap->get_selection()) {
+    case ActualPar::AP_VALUE: {
+      Value *val = defval.ap->get_Value();
+      const_def cdef;
+      Code::init_cdef(&cdef);
+      type->generate_code_object(&cdef, val);
+      Code::merge_cdef(target, &cdef);
+      Code::free_cdef(&cdef);
+      break; }
+    case ActualPar::AP_TEMPLATE: {
+      TemplateInstance *ti = defval.ap->get_TemplateInstance();
+      Template *temp = ti->get_Template();
+      const_def cdef;
+      Code::init_cdef(&cdef);
+      type->generate_code_object(&cdef, temp);
+      Code::merge_cdef(target, &cdef);
+      Code::free_cdef(&cdef);
+      break; }
+    case ActualPar::AP_REF:
+      break;
+    default:
+      FATAL_ERROR("FormalPar::generate_code()");
+    }
+    target->functions.post_init = generate_code_defval(target->functions.post_init);
+  }
+
+  char *FormalPar::generate_code_fpar(char *str, bool display_unused /* = false */)
+  {
+    // the name of the parameter should not be displayed if the parameter is not
+    // used (to avoid a compiler warning)
+    bool display_name = (usage_found || display_unused || debugger_active ||
+      (!enable_set_bound_out_param && (asstype == A_PAR_VAL_OUT || asstype == A_PAR_TEMPL_OUT)));
+    const char *name_str = display_name ? id->get_name().c_str() : "";
     switch (asstype) {
     case A_PAR_VAL_IN:
       if (lazy_eval) {
@@ -8854,19 +9263,28 @@ namespace Ttcn {
     return ret_val;
   }
 
-  char *FormalParList::generate_code(char *str)
+  char *FormalParList::generate_code(char *str, size_t display_unused /* = 0 */)
   {
     for (size_t i = 0; i < pars_v.size(); i++) {
       if (i > 0) str = mputstr(str, ", ");
-      str = pars_v[i]->generate_code_fpar(str);
+      str = pars_v[i]->generate_code_fpar(str, i < display_unused);
+    }
+    return str;
+  }
+  
+  char* FormalParList::generate_code_defval(char* str)
+  {
+    for (size_t i = 0; i < pars_v.size(); i++) {
+      str = pars_v[i]->generate_code_defval(str);
     }
     return str;
   }
 
   void FormalParList::generate_code_defval(output_struct *target)
   {
-    for (size_t i = 0; i < pars_v.size(); i++)
+    for (size_t i = 0; i < pars_v.size(); i++) {
       pars_v[i]->generate_code_defval(target);
+    }
   }
 
   char *FormalParList::generate_code_actual_parlist(char *str,
@@ -9140,6 +9558,13 @@ namespace Ttcn {
         LazyParamData::init(used_as_lvalue);
         LazyParamData::generate_code(expr, val, my_scope);
         LazyParamData::clean();
+        if (val->get_valuetype() == Value::V_REFD) {
+          // check if the reference is a parameter, mark it as used if it is
+          Reference* ref = dynamic_cast<Reference*>(val->get_reference());
+          if (ref != NULL) {
+            ref->ref_usage_found();
+          }
+        }
       } else {
         if (copy_needed) expr->expr = mputprintf(expr->expr, "%s(",
           val->get_my_governor()->get_genname_value(my_scope).c_str());
@@ -9163,6 +9588,15 @@ namespace Ttcn {
         LazyParamData::init(used_as_lvalue);
         LazyParamData::generate_code(expr, temp, gen_restriction_check, my_scope);
         LazyParamData::clean();
+        if (temp->get_DerivedRef() != NULL ||
+            temp->get_Template()->get_templatetype() == Template::TEMPLATE_REFD) {
+          // check if the reference is a parameter, mark it as used if it is
+          Reference* ref = dynamic_cast<Reference*>(temp->get_DerivedRef() != NULL ?
+            temp->get_DerivedRef() : temp->get_Template()->get_reference());
+          if (ref != NULL) {
+            ref->ref_usage_found();
+          }
+        }
       } else {
         if (copy_needed)
           expr->expr = mputprintf(expr->expr, "%s(", temp->get_Template()
@@ -9250,18 +9684,18 @@ namespace Ttcn {
     }
   }
 
-  char *ActualPar::rearrange_init_code(char *str, bool is_local)
+  char *ActualPar::rearrange_init_code(char *str, Common::Module* usage_mod)
   {
     switch (selection) {
     case AP_VALUE:
-      str = val->rearrange_init_code(str);
+      str = val->rearrange_init_code(str, usage_mod);
       break;
     case AP_TEMPLATE:
-      str = temp->rearrange_init_code(str);
+      str = temp->rearrange_init_code(str, usage_mod);
     case AP_REF:
       break;
     case AP_DEFAULT:
-      if (is_local) str = act->rearrange_init_code_defval(str);
+      str = act->rearrange_init_code_defval(str, usage_mod);
       break;
     default:
       FATAL_ERROR("ActualPar::rearrange_init_code()");
@@ -9269,24 +9703,28 @@ namespace Ttcn {
     return str;
   }
 
-  char *ActualPar::rearrange_init_code_defval(char *str)
+  char *ActualPar::rearrange_init_code_defval(char *str, Common::Module* usage_mod)
   {
     switch (selection) {
     case AP_VALUE:
-      str = val->generate_code_init(str, val->get_lhs_name().c_str());
+      if (val->get_my_scope()->get_scope_mod_gen() == usage_mod) {
+        str = val->generate_code_init(str, val->get_lhs_name().c_str());
+      }
       break;
     case AP_TEMPLATE: {
-      str = temp->rearrange_init_code(str);
-      Ref_base *dref = temp->get_DerivedRef();
+      str = temp->rearrange_init_code(str, usage_mod);
       Template *t = temp->get_Template();
-      if (dref) {
-        expression_struct expr;
-        Code::init_expr(&expr);
-        expr.expr = mputprintf(expr.expr, "%s = ", t->get_lhs_name().c_str());
-        dref->generate_code(&expr);
-        str = Code::merge_free_expr(str, &expr, false);
+      if (t->get_my_scope()->get_scope_mod_gen() == usage_mod) {
+        Ref_base *dref = temp->get_DerivedRef();
+        if (dref) {
+          expression_struct expr;
+          Code::init_expr(&expr);
+          expr.expr = mputprintf(expr.expr, "%s = ", t->get_lhs_name().c_str());
+          dref->generate_code(&expr);
+          str = Code::merge_free_expr(str, &expr, false);
+        }
+        str = t->generate_code_init(str, t->get_lhs_name().c_str());
       }
-      str = t->generate_code_init(str, t->get_lhs_name().c_str());
       break; }
     default:
       FATAL_ERROR("ActualPar::rearrange_init_code_defval()");
@@ -9326,7 +9764,7 @@ namespace Ttcn {
       temp->dump(level + 1);
       break;
     case AP_REF:
-      DEBUG(level, "actual parameter: referecne");
+      DEBUG(level, "actual parameter: reference");
       ref->dump(level + 1);
       break;
     case AP_DEFAULT:
@@ -9564,10 +10002,10 @@ namespace Ttcn {
     template_refs.clear();
   }
 
-  char *ActualParList::rearrange_init_code(char *str, bool is_local)
+  char *ActualParList::rearrange_init_code(char *str, Common::Module* usage_mod)
   {
     for (size_t i = 0; i < params.size(); i++)
-      str = params[i]->rearrange_init_code(str, is_local);
+      str = params[i]->rearrange_init_code(str, usage_mod);
     return str;
   }
 
This page took 0.058139 seconds and 5 git commands to generate.