Sync with 5.3.0
authorerititan <elemer.lelik@ericsson.com>
Fri, 22 May 2015 08:58:38 +0000 (10:58 +0200)
committererititan <elemer.lelik@ericsson.com>
Fri, 22 May 2015 08:58:38 +0000 (10:58 +0200)
147 files changed:
common/version.h
compiler2/AST.cc
compiler2/Setting.cc
compiler2/Type.cc
compiler2/Type.hh
compiler2/Type_codegen.cc
compiler2/Value.cc
compiler2/Value.hh
compiler2/compiler.1
compiler2/datatypes.h
compiler2/main.cc
compiler2/main.hh
compiler2/record.c
compiler2/record_of.c
compiler2/subtype.cc
compiler2/ttcn3/AST_ttcn3.cc
compiler2/ttcn3/Makefile
compiler2/ttcn3/Statement.cc
compiler2/ttcn3/Statement.hh
compiler2/ttcn3/TtcnTemplate.cc
compiler2/ttcn3/compiler.c
compiler2/ttcn3/compiler.l
compiler2/ttcn3/compiler.y
compiler2/ttcn3/profiler.c [new file with mode: 0644]
compiler2/ttcn3/profiler.h [new file with mode: 0644]
core/ASN_CharacterString.cc
core/ASN_EmbeddedPDV.cc
core/ASN_External.cc
core/Array.hh
core/Basetype.cc
core/Basetype.hh
core/Component.cc
core/Float.cc
core/Float.hh
core/Makefile
core/Module_list.cc
core/Optional.hh
core/Parallel_main.cc
core/PreGenRecordOf.ttcn [new file with mode: 0644]
core/Profiler.cc
core/Profiler.hh
core/RAW.cc
core/RefdIndex.hh [new file with mode: 0644]
core/Runtime.cc
core/Single_main.cc
core/Snapshot.cc
core/TEXT.cc
core/TEXT.hh
core/TTCN3.hh
core/Template.hh
core/Universal_charstring.cc
core/Universal_charstring.hh
core/XER.hh
core/config_process.l
core/config_process.y
core2/Basetype2.cc
etc/xsd/TXD.xsd [deleted file]
function_test/BER_EncDec/BER_EncDec_TD.fast_script
function_test/Config_Parser/Logging_1_TD.script
function_test/Config_Parser/OrderedInclude.script
function_test/Config_Parser/PreprocessingCfgFiles_TD.script
function_test/RAW_EncDec/RAW_EncDec_TD.fast_script
function_test/Semantic_Analyser/ASN_SA_1_TD.script
function_test/Semantic_Analyser/ASN_SA_asn1adhoc_TD.script
function_test/Semantic_Analyser/TTCN3_SA_10_TD.script
function_test/Semantic_Analyser/TTCN3_SA_11_TD.script
function_test/Semantic_Analyser/TTCN3_SA_12_TD.script_not_running
function_test/Semantic_Analyser/TTCN3_SA_13_TD.script
function_test/Semantic_Analyser/TTCN3_SA_1_TD.script
function_test/Semantic_Analyser/TTCN3_SA_3_TD.script
function_test/Semantic_Analyser/TTCN3_SA_4_TD.script
function_test/Semantic_Analyser/TTCN3_SA_5_TD.script
function_test/Semantic_Analyser/TTCN3_SA_6_TD.script
function_test/Semantic_Analyser/TTCN3_SA_7_TD.script
function_test/Semantic_Analyser/TTCN3_SA_9_TD.script
function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script
function_test/Text_EncDec/TEXT_1_TD.fast_script
function_test/Tools/SAtester
function_test/XER_EncDec/XER_EncDec_TD.script
function_test/doc/TTCN3_Executor_TestReport.doc
help/Makefile
help/info/on.html
help/info/operators.html
help/info/optional.html
help/info/procedure.html
help/info/profiler.html [new file with mode: 0644]
help/info/public.html
help/info/running.html
help/info/start.html
help/info/stop.html
help/titan_index.html
help/titan_main.html
loggerplugins/JUnitLogger2/JUnitLogger2.cc [new file with mode: 0644]
loggerplugins/JUnitLogger2/JUnitLogger2.hh [new file with mode: 0644]
loggerplugins/JUnitLogger2/Makefile [new file with mode: 0644]
loggerplugins/Makefile
loggerplugins/TSTLogger/TSTLogger.cc
mctr2/cli/config_read.l
mctr2/cli/config_read.y
mctr2/mctr/MainController.cc
mctr2/mctr/ttcn3_start
regression_test/Makefile
regression_test/XML/EXER-whitepaper/EmbedValues.ttcnpp
regression_test/XML/TTCNandXML/Makefile
regression_test/XML/XER/checkit.pl
regression_test/all_from/all_from_subtype.ttcn [new file with mode: 0644]
regression_test/all_from/all_from_with_functions.ttcn
regression_test/all_from/types.ttcn
regression_test/boolOper/TboolOper.ttcn
regression_test/cfgFile/module_parameters/assignment/assignment.cfg
regression_test/cfgFile/module_parameters/assignment/assignment.ttcn
regression_test/compileonly/Makefile
regression_test/compileonly/selectCase/Makefile [new file with mode: 0644]
regression_test/compileonly/selectCase/selectCase.ttcn [new file with mode: 0644]
regression_test/negativeTest/Makefile
regression_test/profiler/Makefile [new file with mode: 0755]
regression_test/profiler/PIPEasp_PT.cc [new file with mode: 0644]
regression_test/profiler/PIPEasp_PT.hh [new file with mode: 0644]
regression_test/profiler/PIPEasp_PortType.ttcn [new file with mode: 0644]
regression_test/profiler/PIPEasp_Templates.ttcn [new file with mode: 0644]
regression_test/profiler/PIPEasp_Types.ttcn [new file with mode: 0644]
regression_test/profiler/Shell.ttcn [new file with mode: 0644]
regression_test/profiler/Testcases.ttcn [new file with mode: 0644]
regression_test/profiler/data_e.json [new file with mode: 0644]
regression_test/profiler/empty_e.stats [new file with mode: 0644]
regression_test/profiler/prof1.cfg [new file with mode: 0644]
regression_test/profiler/prof1.ttcn [new file with mode: 0644]
regression_test/profiler/prof1_e.stats [new file with mode: 0644]
regression_test/profiler/prof2.cfg [new file with mode: 0644]
regression_test/profiler/prof2.ttcn [new file with mode: 0644]
regression_test/profiler/prof3.cfg [new file with mode: 0644]
regression_test/profiler/prof3.ttcn [new file with mode: 0644]
regression_test/profiler/prof_files.txt [new file with mode: 0644]
regression_test/recofOper/Makefile
regression_test/recofOper/TrecofCompat.ttcn [new file with mode: 0644]
regression_test/recofOper/TrecofParamRef.ttcn
regression_test/recofOper/config.cfg
regression_test/recofOper/config_rt2.cfg
regression_test/testcase_defparam/Makefile
regression_test/ucharstrOper/cstr_content.ttcn
titan_executor_api/doc/Titan_Executor_API_User_Guide.doc
usrguide/PRI.doc
usrguide/apiguide.doc
usrguide/installationguide.doc
usrguide/referenceguide.doc
usrguide/releasenotes.doc
usrguide/userguide.doc

index a72a783c64b5e61a883c64e0f78016b29ae0837f..5ee2842915c4f4ecad04a27a35ba2814ef379946 100644 (file)
@@ -10,7 +10,7 @@
 
 /* Version numbers */
 #define TTCN3_MAJOR 5
-#define TTCN3_MINOR 2
+#define TTCN3_MINOR 3
 #define TTCN3_PATCHLEVEL 0
 //#define TTCN3_BUILDNUMBER 0
 
@@ -22,7 +22,7 @@
  * TTCN3_VERSION = TTCN3_MAJOR * 1000000 + TTCN3_MINOR * 10000 +
  *                 TTCN3_PATCHLEVEL * 100 + TTCN3_BUILDNUMBER
  */
-#define TTCN3_VERSION 50200
+#define TTCN3_VERSION 50300
 
 /* A monotonically increasing version number.
  * An official release is deemed to have the highest possible build number (99)
index 4cfcad260ae88a849d24f460d1d723f72b87bd29..202d282f25c1cab453ed741b0bd2f8b564699164 100644 (file)
@@ -23,6 +23,7 @@
 #include "../common/version.h"
 #include "CodeGenHelper.hh"
 #include <limits.h>
+#include "ttcn3/profiler.h"
 
 reffer::reffer(const char*) {}
 
@@ -774,7 +775,9 @@ namespace Common {
     }
     // pre_init function
     bool has_pre_init = false;
-    if (output->functions.pre_init) {
+    bool profiled = MOD_TTCN == get_moduletype() && is_file_profiled(get_filename());
+    // always generate pre_init_module if the file is profiled
+    if (output->functions.pre_init || profiled) {
       output->source.static_function_prototypes =
        mputstr(output->source.static_function_prototypes,
          "static void pre_init_module();\n");
@@ -800,11 +803,11 @@ namespace Common {
               mputprintf(effective_module_functions, "%s\"%s\"",
                           (effective_module_functions ? ", " : ""), get_modid().get_dispname().c_str());
         }
-        if (profiler_enabled && MOD_TTCN == get_moduletype()) {
+        if (profiled) {
           output->source.static_function_bodies = mputprintf(output->source.static_function_bodies,
+            "%s::init_ttcn3_profiler();\n"
             "TTCN3_Stack_Depth stack_depth;\n"
-            "ttcn3_prof.enter_function(\"%s\", 0, \"%s\");\n",
-            get_filename(), get_modid().get_dispname().c_str());
+            "ttcn3_prof.execute_line(\"%s\", 0);\n", get_modid().get_name().c_str(), get_filename());
         }
       }
       output->source.static_function_bodies =
@@ -843,11 +846,10 @@ namespace Common {
             mputprintf(effective_module_functions, "%s\"%s\"",
                           (effective_module_functions ? ", " : ""), get_modid().get_dispname().c_str());
         }
-        if (profiler_enabled && MOD_TTCN == get_moduletype()) {
+        if (MOD_TTCN == get_moduletype() && is_file_profiled(get_filename())) {
           output->source.static_function_bodies = mputprintf(output->source.static_function_bodies,
             "TTCN3_Stack_Depth stack_depth;\n"
-            "ttcn3_prof.enter_function(\"%s\", 0, \"%s\");\n",
-            get_filename(), get_modid().get_dispname().c_str());
+            "ttcn3_prof.execute_line(\"%s\", 0);\n", get_filename());
         }
       }
       output->source.static_function_bodies =
@@ -1482,13 +1484,38 @@ namespace Common {
     // language specific parts (definitions, imports, etc.)
     //generate_code_internal(&target);  <- needed to pass cgh
     generate_code_internal(cgh);
+    
+    output_struct* output = cgh.get_current_outputstruct();
 
     // string literals
-    generate_literals(cgh.get_current_outputstruct());
+    generate_literals(output);
     // module level entry points
-    generate_functions(cgh.get_current_outputstruct());
+    generate_functions(output);
     // type conversion functions for type compatibility
-    generate_conversion_functions(cgh.get_current_outputstruct());
+    generate_conversion_functions(output);
+    
+    /* generate the initializer function for the TTCN-3 profiler
+     * (this is done at the end of the code generation, to make sure all code 
+     * lines have been added to the profiler database) */
+    if (is_file_profiled(get_filename())) {
+      output->source.global_vars = mputstr(output->source.global_vars,
+        "\n/* Initializing TTCN-3 profiler */\n"
+        "void init_ttcn3_profiler()\n"
+        "{\n");
+      char* function_name = 0;
+      int line_no = -1;
+      while(get_profiler_code_line(get_filename(), &function_name, &line_no)) {
+        output->source.global_vars = mputprintf(output->source.global_vars,
+          "  ttcn3_prof.create_line(ttcn3_prof.get_element(\"%s\"), %d);\n",
+          get_filename(), line_no);
+        if (0 != function_name) {
+          output->source.global_vars = mputprintf(output->source.global_vars,
+            "  ttcn3_prof.create_function(ttcn3_prof.get_element(\"%s\"), %d, \"%s\");\n",
+            get_filename(), line_no, function_name);
+        }
+      }
+      output->source.global_vars = mputstr(output->source.global_vars, "}\n\n");
+    }
   }
 
   void Module::dump(unsigned level) const
index 1dae00b162f0c9a8ad4709e21d2846884bc4f7a5..47e5a736c04ef4f6a2927c62a4d828dfcbc118d2 100644 (file)
@@ -18,6 +18,7 @@
 #include "Value.hh"
 #include "Int.hh"
 #include "main.hh"
+#include "ttcn3/profiler.h"
 
 namespace Common {
 
@@ -232,11 +233,20 @@ namespace Common {
             mputprintf(effective_module_functions, "%s\"%s\"",
                           (effective_module_functions ? ", " : ""), entityname);
       }
-      if (profiler_enabled) {
+      if (is_file_profiled(filename)) {
+        // .ttcnpp -> .ttcn
+        size_t file_name_len = strlen(filename);
+        if ('p' == filename[file_name_len - 1] && 'p' == filename[file_name_len - 2]) {
+          file_name_len -= 2;
+        }
+        char* file_name2 = mcopystrn(filename, file_name_len);
         str = mputprintf(str,
           "TTCN3_Stack_Depth stack_depth;\n"
-          "ttcn3_prof.enter_function(\"%s\", %d, \"%s\");\n",
-          filename, yyloc.first_line, entityname);
+          "ttcn3_prof.enter_function(\"%s\", %d);\n", file_name2, yyloc.first_line);
+        insert_profiler_code_line(file_name2, 
+          (0 == strcmp(entitytype, "CONTROLPART") ? "control" : entityname),
+          yyloc.first_line);
+        Free(file_name2);
       }
     }
     return str;
@@ -248,11 +258,20 @@ namespace Common {
       if (include_location_info && !transparency) {
         str = mputprintf(str, "current_location.update_lineno(%d);\n",
                          yyloc.first_line);
-        if (profiler_enabled) {
+        const char* file_name = get_filename();
+        if (is_file_profiled(file_name)) {
+          // .ttcnpp -> .ttcn
+          size_t file_name_len = strlen(file_name);
+          if ('p' == file_name[file_name_len - 1] && 'p' == file_name[file_name_len - 2]) {
+            file_name_len -= 2;
+          }
+          char* file_name2 = mcopystrn(file_name, file_name_len);
           str = mputprintf(str, "ttcn3_prof.execute_line(\"%s\", %d);\n",
-                  get_filename(), yyloc.first_line);
+                  file_name2, yyloc.first_line);
+          insert_profiler_code_line(file_name2, NULL, yyloc.first_line);
+          Free(file_name2);
         }
-        if (tcov_file_name && in_tcov_files(get_filename())) {
+        if (tcov_file_name && in_tcov_files(file_name)) {
             effective_module_lines =
               mputprintf(effective_module_lines, "%s%d",
                           (effective_module_lines ? ", " : ""), yyloc.first_line);
index 2a9683d3c26f0e378f0a95a1ce36c9d6d10f5ada..fd06d5d4c4722ef2a7190c1783578f1ffe4f33db 100644 (file)
@@ -149,7 +149,7 @@ namespace Common {
     }
   }
 
-  Type *Type::get_stream_type(MessageEncodingType_t encoding_type)
+  Type *Type::get_stream_type(MessageEncodingType_t encoding_type, int stream_variant)
   {
     switch (encoding_type) {
     case CT_BER:
@@ -159,7 +159,11 @@ namespace Common {
     case CT_JSON:
       return get_pooltype(T_OSTR);
     case CT_TEXT:
-      return get_pooltype(T_CSTR);
+      if(stream_variant==0){
+        return get_pooltype(T_CSTR);
+      } else {
+        return get_pooltype(T_OSTR);
+      }
     default:
       FATAL_ERROR("Type::get_stream_type()");
       return 0;
@@ -3529,6 +3533,20 @@ namespace Common {
   {
     if (typetype != T_SEQOF) FATAL_ERROR("Type::is_compatible_record_of()");
     if (this == p_type) return true;
+    else if (T_SEQOF == p_type->get_type_refd_last()->typetype &&
+             is_pregenerated() && p_type->is_pregenerated() &&
+             get_ofType()->get_type_refd_last()->typetype ==
+             p_type->get_ofType()->get_type_refd_last()->typetype &&
+             (use_runtime_2 || get_optimize_attribute() == p_type->get_optimize_attribute())) {
+      // Pre-generated record-ofs of the same element type are compatible with 
+      // each other (in RT1 optimized record-ofs are not compatible with non-optimized ones)
+      if (!is_subtype_length_compatible(p_type)) {
+        p_info->set_is_erroneous(this, p_type, string("Incompatible "
+                                 "record of/SEQUENCE OF subtypes"));
+        return false;
+      }
+      return true;
+    }
     else if (!use_runtime_2 || !p_info
              || (p_info && p_info->is_strict())) return false;
     switch (p_type->typetype) {
@@ -3878,6 +3896,20 @@ namespace Common {
   {
     if (typetype != T_SETOF) FATAL_ERROR("Type::is_compatible_set_of()");
     if (this == p_type) return true;
+    else if (T_SETOF == p_type->get_type_refd_last()->typetype &&
+             is_pregenerated() && p_type->is_pregenerated() &&
+             get_ofType()->get_type_refd_last()->typetype ==
+             p_type->get_ofType()->get_type_refd_last()->typetype &&
+             (use_runtime_2 || get_optimize_attribute() == p_type->get_optimize_attribute())) {
+      // Pre-generated set-ofs of the same element type are compatible with 
+      // each other (in RT1 optimized set-ofs are not compatible with non-optimized ones)
+      if (!is_subtype_length_compatible(p_type)) {
+        p_info->set_is_erroneous(this, p_type, string("Incompatible "
+                                 "set of/SET OF subtypes"));
+        return false;
+      }
+      return true;
+    }
     else if (!use_runtime_2 || !p_info
              || (p_info && p_info->is_strict())) return false;
     Type *of_type = get_ofType();
@@ -5523,6 +5555,7 @@ end_ext:
           case T_INT:
           case T_OSTR:
           case T_CSTR:
+          case T_USTR:    // TTCN3 universal charstring
             // these basic types support TEXT encoding by default
             return true;
           default:
@@ -6833,6 +6866,50 @@ end_ext:
     }
     return dispname;
   }
+  
+  bool Type::is_pregenerated()
+  {
+    // records/sets of base types are already pre-generated, only a type alias will be generated
+    // exception: record of universal charstring with the XER coding instruction "anyElement"
+    if (!force_gen_seof && (T_SEQOF == get_type_refd_last()->typetype ||
+        T_SETOF == get_type_refd_last()->typetype) &&
+        (NULL == xerattrib || /* check for "anyElement" at the record of type */
+        NamespaceRestriction::UNUSED == xerattrib->anyElement_.type_) &&
+        (NULL == u.seof.ofType->xerattrib || /* check for "anyElement" at the element type */
+        NamespaceRestriction::UNUSED == u.seof.ofType->xerattrib->anyElement_.type_)) {
+      switch(u.seof.ofType->get_type_refd_last()->typetype) {
+      case T_BOOL:
+      case T_INT:
+      case T_INT_A:
+      case T_REAL:
+      case T_BSTR:
+      case T_BSTR_A:
+      case T_HSTR:
+      case T_OSTR:
+      case T_CSTR:
+      case T_NUMERICSTRING:
+      case T_PRINTABLESTRING:
+      case T_IA5STRING:
+      case T_VISIBLESTRING:
+      case T_UNRESTRICTEDSTRING:
+      case T_UTCTIME:
+      case T_GENERALIZEDTIME:
+      case T_USTR:
+      case T_UTF8STRING:
+      case T_TELETEXSTRING:
+      case T_VIDEOTEXSTRING:
+      case T_GRAPHICSTRING:
+      case T_GENERALSTRING:
+      case T_UNIVERSALSTRING:
+      case T_BMPSTRING:
+      case T_OBJECTDESCRIPTOR:
+        return true;
+      default:
+        return false;
+      }
+    }
+    return false;
+  }
 
 } // namespace Common
 
index 55737c94bb107fee57f4d9fd8e686bfe38bf31b7..29f85957b1e185c25e7d664f5a59fbc709b9406a 100644 (file)
@@ -244,7 +244,7 @@ namespace Common {
     static const char *get_encoding_name(MessageEncodingType_t encoding_type);
     /** Returns a pool type that represents the encoded stream of the given
      * \a encoding_type. */
-    static Type *get_stream_type(MessageEncodingType_t encoding_type);
+    static Type *get_stream_type(MessageEncodingType_t encoding_type, int stream_variant=0);
 
     enum truth {
       No, Maybe, Yes
@@ -1017,6 +1017,10 @@ namespace Common {
         otherwise returns false.  **/
     bool ispresent_anyvalue_embedded_field(Type* t,
       Ttcn::FieldOrArrayRefs *subrefs, size_t begin_index);
+    
+    /** Returns true if the C++ class for this type has already been pre-generated
+      * or false if it still needs to be generated */
+    bool is_pregenerated();
   public:
     /** Generates type specific call for the reference used in isbound call
      * into argument \a expr. Argument \a subrefs holds the reference path
index b6baffb615c9656ab6e0024d3fa098f0347b1dd1..5be67c25d2fd84d448bff456bcbe0959538c2e73 100644 (file)
@@ -382,6 +382,16 @@ void Type::generate_code_typedescriptor(output_struct *target)
           "NULL, ");
       }
     }
+    
+    if (T_SEQOF == get_type_refd_last()->typetype || 
+        T_SETOF == get_type_refd_last()->typetype) {
+      target->source.global_vars=mputprintf(target->source.global_vars,
+        "&%s_descr_, ", get_type_refd_last()->u.seof.ofType->get_genname_typedescriptor(my_scope).c_str());
+    }
+    else {
+      target->source.global_vars = mputstr(target->source.global_vars,
+        "NULL, ");
+    }
 
     target->source.global_vars=mputprintf(target->source.global_vars,
       "TTCN_Typedescriptor_t::%s };\n"
@@ -483,6 +493,7 @@ void Type::generate_code_xerdescriptor(output_struct* target)
   any_except=0, nof_ns_uris=0;
   const char* dfe_str = 0;
   char** ns_uris = 0;
+  char* oftype_descr_name = 0;
   if (xerattrib) {
     change_name(last_s, xerattrib->name_);
 
@@ -572,6 +583,12 @@ void Type::generate_code_xerdescriptor(output_struct* target)
   size_t last_len = 2 + last_s.size();    // 2 for > \n
   size_t bxer_len = 2 + bxer_name.size(); // 2 for > \n
   
+  if ((T_SEQOF == last->typetype || T_SETOF == last->typetype) &&
+      T_ANYTYPE != last->u.seof.ofType->get_type_refd_last()->typetype) {
+    // anytypes don't have XER descriptors
+    oftype_descr_name = mprintf("&%s_xer_", last->u.seof.ofType->get_genname_typedescriptor(my_scope).c_str());
+  }
+  
   // Generate a separate variable for the namespace URIs, if there are any
   char* ns_uris_var = 0;
   if (ns_uris && nof_ns_uris) {
@@ -591,7 +608,7 @@ void Type::generate_code_xerdescriptor(output_struct* target)
   target->source.global_vars = mputprintf(target->source.global_vars,
     "const XERdescriptor_t       %s_xer_ = { {\"%s>\\n\", \"%s>\\n\"},"
     " {%lu, %lu}, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s, WHITESPACE_%s, %c%s, "
-    "&%s, %ld, %u, %s };\n",
+    "&%s, %ld, %u, %s, %s };\n",
     gennameown_str,
     bxer_name.c_str(), last_s.c_str(), // names
     (unsigned long)bxer_len, (unsigned long)last_len, // lengths
@@ -618,10 +635,12 @@ void Type::generate_code_xerdescriptor(output_struct* target)
     "module_object",
     ns_index,
     nof_ns_uris,
-    (ns_uris_var ? ns_uris_var : "NULL")
+    (ns_uris_var ? ns_uris_var : "NULL"),
+    (oftype_descr_name ? oftype_descr_name : "NULL")
     );
   
   Free(ns_uris_var);
+  Free(oftype_descr_name);
 }
 
 void Type::generate_code_rawdescriptor(output_struct *target)
@@ -1471,6 +1490,7 @@ void Type::generate_code_Se(output_struct *target)
     cur.dispname = id.get_ttcnname().c_str();
     cur.isOptional = cf->get_is_optional();
     cur.isDefault = cf->has_default();
+    cur.optimizedMemAlloc = cur.of_type && (type->get_optimize_attribute() == "memalloc");
     if (cur.isDefault) {
       Value *defval = cf->get_defval();
       const_def cdef;
@@ -1810,6 +1830,41 @@ bool Type::is_untagged() const { return xerattrib && xerattrib->untagged_; }
 
 void Type::generate_code_SeOf(output_struct *target)
 {
+  const Type *oftypelast = u.seof.ofType->get_type_refd_last();
+  const string& oftypename = u.seof.ofType->get_genname_value(my_scope);
+  boolean optimized_memalloc = !use_runtime_2 && get_optimize_attribute() == "memalloc";
+  
+  if (is_pregenerated()) {
+    switch(oftypelast->typetype) {
+    case T_USTR:
+    case T_UTF8STRING:
+    case T_TELETEXSTRING:
+    case T_VIDEOTEXSTRING:
+    case T_GRAPHICSTRING:
+    case T_GENERALSTRING:
+    case T_UNIVERSALSTRING:
+    case T_BMPSTRING:
+    case T_OBJECTDESCRIPTOR:
+      target->header.typedefs = mputprintf(target->header.typedefs,
+        "typedef PreGenRecordOf::PREGEN__%s__OF__UNIVERSAL__CHARSTRING%s %s;\n"
+        "typedef PreGenRecordOf::PREGEN__%s__OF__UNIVERSAL__CHARSTRING%s_template %s_template;\n",
+        (typetype == T_SEQOF) ? "RECORD" : "SET",
+        optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str(),
+        (typetype == T_SEQOF) ? "RECORD" : "SET",
+        optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str());
+      return;
+    default:
+      target->header.typedefs = mputprintf(target->header.typedefs,
+        "typedef PreGenRecordOf::PREGEN__%s__OF__%s%s %s;\n"
+        "typedef PreGenRecordOf::PREGEN__%s__OF__%s%s_template %s_template;\n",
+        (typetype == T_SEQOF) ? "RECORD" : "SET", oftypename.c_str(), 
+        optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str(),
+        (typetype == T_SEQOF) ? "RECORD" : "SET", oftypename.c_str(),
+        optimized_memalloc ? "__OPTIMIZED" : "",  get_genname_own().c_str());
+      return;
+    }
+  }
+  
   stringpool pool;
   struct_of_def sofdef;
   memset(&sofdef, 0, sizeof(sofdef));
@@ -1826,10 +1881,8 @@ void Type::generate_code_SeOf(output_struct *target)
   }
   // If a record of UTF8String, we need to prepare for ANY-ATTRIBUTES and
   // ANY-ELEMENT
-  const Type *oftypelast = u.seof.ofType->get_type_refd_last();
   sofdef.xerAnyAttrElem = oftypelast->typetype == T_USTR
   ||                      oftypelast->typetype == T_UTF8STRING;
-  const string& oftypename = u.seof.ofType->get_genname_value(my_scope);
   sofdef.type = oftypename.c_str();
   sofdef.has_opentypes = get_has_opentypes();
   const string& oftypedescrname =
@@ -1895,7 +1948,7 @@ void Type::generate_code_SeOf(output_struct *target)
     sofdef.hasRaw=true;
   } else sofdef.hasRaw=false;
 
-  if (!use_runtime_2 && get_optimize_attribute()=="memalloc") {
+  if (optimized_memalloc) {
     defRecordOfClassMemAllocOptimized(&sofdef, target);
   } else {
     defRecordOfClass(&sofdef, target);
index a1c1c8a524120905f821fd0d40c3cf373f6d2134..7fb2f0b5d35f9603a6bbe8cea1c2daad72f9440e 100644 (file)
@@ -143,6 +143,7 @@ namespace Common {
       case OPTYPE_TMR_RUNNING_ANY:
       case OPTYPE_GETVERDICT:
       case OPTYPE_TESTCASENAME:
+      case OPTYPE_PROF_RUNNING:
         break;
       case OPTYPE_UNARYPLUS: // v1
       case OPTYPE_UNARYMINUS:
@@ -446,6 +447,7 @@ namespace Common {
     case OPTYPE_TMR_RUNNING_ANY:
     case OPTYPE_GETVERDICT:
     case OPTYPE_TESTCASENAME:
+    case OPTYPE_PROF_RUNNING:
       break;
     case OPTYPE_UNARYPLUS: // v1
     case OPTYPE_UNARYMINUS:
@@ -809,6 +811,7 @@ namespace Common {
     case OPTYPE_TMR_RUNNING_ANY:
     case OPTYPE_GETVERDICT:
     case OPTYPE_TESTCASENAME:
+    case OPTYPE_PROF_RUNNING:
       break;
     default:
       FATAL_ERROR("Value::Value()");
@@ -1388,6 +1391,7 @@ namespace Common {
     case OPTYPE_TMR_RUNNING_ANY:
     case OPTYPE_GETVERDICT:
     case OPTYPE_TESTCASENAME:
+    case OPTYPE_PROF_RUNNING:
       break;
     case OPTYPE_UNARYPLUS: // v1
     case OPTYPE_UNARYMINUS:
@@ -1567,6 +1571,7 @@ namespace Common {
     case OPTYPE_TMR_RUNNING_ANY:
     case OPTYPE_GETVERDICT:
     case OPTYPE_TESTCASENAME:
+    case OPTYPE_PROF_RUNNING:
       break;
     case OPTYPE_UNARYPLUS: // v1
     case OPTYPE_UNARYMINUS:
@@ -1876,6 +1881,7 @@ namespace Common {
       case OPTYPE_TMR_RUNNING_ANY:
       case OPTYPE_GETVERDICT:
       case OPTYPE_TESTCASENAME:
+      case OPTYPE_PROF_RUNNING:
         break;
       case OPTYPE_UNARYPLUS: // v1
       case OPTYPE_UNARYMINUS:
@@ -2765,6 +2771,7 @@ namespace Common {
       case OPTYPE_ISCHOSEN_T:
       case OPTYPE_ISVALUE:
       case OPTYPE_ISBOUND:
+      case OPTYPE_PROF_RUNNING:
         return Type::T_BOOL;
       case OPTYPE_GETVERDICT:
         return Type::T_VERDICT;
@@ -3448,6 +3455,8 @@ namespace Common {
       return "log2str()";
     case OPTYPE_TTCN2STRING:
       return "ttcn2string()";
+    case OPTYPE_PROF_RUNNING:
+      return "@profiler.running";
     default:
       FATAL_ERROR("Value::get_opname()");
     } // switch
@@ -6038,6 +6047,7 @@ error:
     switch (u.expr.v_optype) {
     case OPTYPE_COMP_NULL:
     case OPTYPE_TESTCASENAME:
+    case OPTYPE_PROF_RUNNING:
       break;
     case OPTYPE_COMP_MTC:
     case OPTYPE_COMP_SYSTEM:
@@ -6998,6 +7008,7 @@ error:
     case OPTYPE_COMP_ALIVE_ALL:
     case OPTYPE_TMR_RUNNING_ANY:
     case OPTYPE_GETVERDICT:
+    case OPTYPE_PROF_RUNNING:
     case OPTYPE_RNDWITHVAL: // v1
     case OPTYPE_COMP_RUNNING: // v1
     case OPTYPE_COMP_ALIVE:
@@ -8294,6 +8305,7 @@ error:
       case OPTYPE_TMR_RUNNING_ANY:
       case OPTYPE_GETVERDICT:
       case OPTYPE_TESTCASENAME:
+      case OPTYPE_PROF_RUNNING:
       case OPTYPE_RNDWITHVAL: // v1
       case OPTYPE_MATCH: // v1 t2
       case OPTYPE_UNDEF_RUNNING: // v1
@@ -9797,6 +9809,7 @@ error:
     case OPTYPE_COMP_ALIVE_ALL: // -
     case OPTYPE_TMR_RUNNING_ANY: // -
     case OPTYPE_GETVERDICT: // -
+    case OPTYPE_PROF_RUNNING: // -
       break; // nothing to do
 
     case OPTYPE_MATCH: // v1 t2
@@ -10496,6 +10509,8 @@ error:
         }
         ret_val += ')';
         return ret_val; }
+      case OPTYPE_PROF_RUNNING:
+        return string("@profiler.running");
       default:
         return string("<unsupported optype>");
       } // switch u.expr.v_optype
@@ -11771,6 +11786,9 @@ error:
       }
       expr->expr = mputstr(expr->expr, ")"); 
     } break;
+    case OPTYPE_PROF_RUNNING:
+      expr->expr = mputstr(expr->expr, "ttcn3_prof.is_running()");
+      break;
     default:
       FATAL_ERROR("Value::generate_code_expr_expr()");
     }
@@ -12857,6 +12875,7 @@ error:
     case OPTYPE_TMR_RUNNING_ANY:
     case OPTYPE_GETVERDICT:
     case OPTYPE_TESTCASENAME:
+    case OPTYPE_PROF_RUNNING:
       return true;
     case OPTYPE_ENCODE:
     case OPTYPE_DECODE:
@@ -13178,13 +13197,16 @@ error:
     if (t_subrefs) {
       // the evaluation of the reference does not have side effects
       // (i.e. false shall be returned) only if all sub-references point to
-      // mandatory fields of record/set types
+      // mandatory fields of record/set types, and neither sub-reference points
+      // to a field of a union type
       Type *t_type = t_ass->get_Type();
       for (size_t i = 0; i < t_subrefs->get_nof_refs(); i++) {
        Ttcn::FieldOrArrayRef *t_fieldref = t_subrefs->get_ref(i);
        if (t_fieldref->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF) {
          CompField *t_cf = t_type->get_comp_byName(*t_fieldref->get_id());
-         if (t_cf->get_is_optional()) return true;
+         if (Type::T_CHOICE_T == t_type->get_type_refd_last()->get_typetype() ||
+        Type::T_CHOICE_A == t_type->get_type_refd_last()->get_typetype() ||
+        t_cf->get_is_optional()) return true;
          t_type = t_cf->get_type();
        } else return true;
       }
index cfd3f796b5438d32da68e2cb74b0336f493d6a0b..61d324cf9cb2f74e0dfec040a04f6812fc0cab16 100644 (file)
@@ -238,7 +238,8 @@ namespace Common {
       OPTYPE_EXECUTE, // r1 [v2]
       OPTYPE_EXECUTE_REFD, // v1 t_list2 [v3]
 
-      OPTYPE_LOG2STR, // logagrs   98
+      OPTYPE_LOG2STR, // logagrs
+      OPTYPE_PROF_RUNNING, // -     99
 
       NUMBER_OF_OPTYPES // must be last
     };
@@ -369,7 +370,8 @@ namespace Common {
     Value(valuetype_t p_vt, Value *p_v, Ttcn::ParsedActualParameters *p_t_list);
     /** Constructor used by V_EXPR "-": RND, TESTCASENAME, COMP_NULL, COMP_MTC,
      *  COMP_SYSTEM, COMP_SELF, COMP_RUNNING_ANY, COMP_RUNNING_ALL,
-     *  COMP_ALIVE_ALL, COMP_ALIVE_ANY, TMR_RUNNING_ANY, GETVERDICT */
+     *  COMP_ALIVE_ALL, COMP_ALIVE_ANY, TMR_RUNNING_ANY, GETVERDICT,
+     *  PROF_RUNNING */
     Value(operationtype_t p_optype);
     /** Constructor used by V_EXPR "v1" */
     Value(operationtype_t p_optype, Value *p_v1);
index a3416e4b57b16edbc01adf7d6cc92ea89f8399ee..2df9a3418a128cca6aa79b8dbdd01ee5862d25df 100644 (file)
@@ -8,6 +8,8 @@ compiler \- TTCN-3 and ASN.1 to C++ translator
 .IR " verb_level" " \|]"
 .RB "[\| " \-K
 .IR " file" " \|]"
+.RB "[\| " \-z
+.IR " file" " \|]"
 .RB "[\| " \-o
 .IR " dir" " \|]"
 .RB "[\| " \-P
@@ -294,6 +296,11 @@ checking
 .B \-Y
 Enforces legacy behaviour of the "out" function parameters (see refguide).
 .TP
+.BI \-z " file"
+Enables profiling and code coverage in the selected TTCN-3 files. The
+.I file
+argument contains a list of TTCN-3 files separated by new lines. Each TTCN-3 file must be among the compiler's TTCN-3 file arguments.
+.TP
 .B \-
 The single dash character as command line argument controls the
 .I selective code generation
index a24cf63551086315333ca80af4769ad3389b76d6..a49fe4be86d507ef5e6e536595816cbe74ee7553 100644 (file)
@@ -70,6 +70,8 @@ typedef struct {
   boolean jsonOmitAsNull;
   const char* jsonAlias;
   const char* jsonDefaultValue;
+  /** true if the field is a record-of or set-of with optimized memory allocation */
+  boolean optimizedMemAlloc;
 } struct_field;
 
 /** Structure (record, set, union, anytype) descriptor for code generation */
index fd58f1a80e61eaf0ea53f552cc5eb84d367ac911..7a0d19b5ef4b9d779ae65fd23cc1b3a3373b66d1 100644 (file)
@@ -45,6 +45,8 @@
 
 #include "ttcn3/Ttcn2Json.hh"
 
+#include "ttcn3/profiler.h"
+
 #ifdef LICENSE
 #include "../common/license.h"
 #endif
@@ -53,6 +55,7 @@ using namespace Common;
 
 const char *output_dir = NULL;
 const char *tcov_file_name = NULL;
+const char *profiler_file_name = NULL;
 tcov_file_list *tcov_files = NULL;
 expstring_t effective_module_lines = NULL;
 expstring_t effective_module_functions = NULL;
@@ -68,7 +71,7 @@ boolean generate_skeleton = FALSE, force_overwrite = FALSE,
   use_runtime_2 = FALSE, gcc_compat = FALSE, asn1_xer = FALSE,
   check_subtype = TRUE, suppress_context = FALSE, display_up_to_date = FALSE,
   implicit_json_encoding = FALSE, json_refs_for_all_types = TRUE,
-  profiler_enabled = FALSE;
+  force_gen_seof = FALSE;
 
 // Default code splitting mode is set to 'no splitting'.
 CodeGenHelper::split_type code_splitting_mode = CodeGenHelper::SPLIT_NONE;
@@ -286,7 +289,8 @@ boolean in_tcov_files(const char *file_name)
   return get_tcov_file_name(file_name) ? TRUE : FALSE;
 }
 
-static bool check_file_list(const char *file_name, module_struct *module_list, size_t n_modules)
+static bool check_file_list(const char *file_name, module_struct *module_list,
+                            size_t n_modules, tcov_file_list *&file_list_head)
 {
   FILE *fp = fopen(file_name, "r");
   if (fp == NULL) {
@@ -316,11 +320,11 @@ static bool check_file_list(const char *file_name, module_struct *module_list, s
     for (; i < n_modules; ++i) {
       const module_struct *module = module_list + i;
       if (!strncmp(module->file_name, line, line_len)) {
-        tcov_file_list *next_file = new tcov_file_list;
-        next_file->next = tcov_files;
+        tcov_file_list *next_file = (tcov_file_list*)Malloc(sizeof(tcov_file_list));
+        next_file->next = file_list_head;
         // We'll need the `.ttcnpp' file name.
         next_file->file_name = mcopystr(line);
-        tcov_files = next_file;
+        file_list_head = next_file;
         break;
       }
     }
@@ -332,13 +336,13 @@ static bool check_file_list(const char *file_name, module_struct *module_list, s
   }
   fclose(fp);
   if (unlisted_files) {
-       while (tcov_files != NULL) {
-         tcov_file_list *next_file = tcov_files->next;
-         Free(tcov_files->file_name);
-         delete tcov_files;
-         tcov_files = next_file;
+       while (file_list_head != NULL) {
+         tcov_file_list *next_file = file_list_head->next;
+         Free(file_list_head->file_name);
+         Free(file_list_head);
+         file_list_head = next_file;
        }
-       tcov_files = NULL;
+       file_list_head = NULL;
   }
   return !unlisted_files;
 }
@@ -354,8 +358,8 @@ static boolean is_valid_asn1_filename(const char* file_name)
 static void usage()
 {
   fprintf(stderr, "\n"
-    "usage: %s [-abcdfgilLOpqrRsStuwxXjy] [-K file] [-V verb_level] [-o dir]\n"
-    "  [-U none|type] [-P modulename.top_level_pdu_name] [-Q number] ...\n"
+    "usage: %s [-abcdfgijlLOpqrRsStuwxXyY] [-K file] [-z file] [-V verb_level]\n"
+    "  [-o dir] [-U none|type] [-P modulename.top_level_pdu_name] [-Q number] ...\n"
     "  [-T] module.ttcn [-A] module.asn ...\n"
     "  or  %s -v\n"
     "  or  %s --ttcn2json [-jf] ... [-T] module.ttcn [-A] module.asn ... [- schema.json]\n"
@@ -390,7 +394,7 @@ static void usage()
     "  -X:             disable XER encoder/decoder functions\n"
     "  -y:             disable subtype checking\n"
     "  -Y:             Enforces legacy behaviour of the \"out\" function parameters (see refguide)\n"
-    //"        -z:             enable profiling and code coverage for TTCN-3 files\n" - not open to the public yet
+    "  -z file:        enable profiling and code coverage for the TTCN-3 files in the argument\n"
     "  -T file:        force interpretation of file as TTCN-3 module\n"
     "  -A file:        force interpretation of file as ASN.1 module\n"
     "  -v:             show version\n"
@@ -438,7 +442,7 @@ int main(int argc, char *argv[])
     usage();
     return EXIT_FAILURE;
   }
-
+  
   bool
     Aflag = false,  Lflag = false, Yflag = false,
     Pflag = false, Tflag = false, Vflag = false, bflag = false,
@@ -447,7 +451,7 @@ int main(int argc, char *argv[])
     tflag = false, uflag = false, vflag = false, wflag = false, xflag = false,
     dflag = false, Xflag = false, Rflag = false, gflag = false, aflag = false,
     s0flag = false, Cflag = false, yflag = false, Uflag = false, Qflag = false,
-    Sflag = false, Kflag = false, jflag = false, zflag = false,
+    Sflag = false, Kflag = false, jflag = false, zflag = false, Fflag = false,
     errflag = false, print_usage = false, ttcn2json = false;
 
   CodeGenHelper cgh;
@@ -540,7 +544,7 @@ int main(int argc, char *argv[])
 
   if (!ttcn2json) {
     for ( ; ; ) {
-      int c = getopt(argc, argv, "aA:C:K:LP:T:V:bcdfgilo:YpqQ:rRs0StuU:vwxXjyz-");
+      int c = getopt(argc, argv, "aA:C:K:LP:T:V:bcdfFgilo:YpqQ:rRs0StuU:vwxXjyz:-");
       if (c == -1) break;
       switch (c) {
       case 'a':
@@ -697,7 +701,11 @@ int main(int argc, char *argv[])
         break;
       case 'z':
         SET_FLAG(z);
-        profiler_enabled = TRUE;
+        profiler_file_name = optarg;
+        break;
+      case 'F':
+        SET_FLAG(F);
+        force_gen_seof = TRUE;
         break;
 
       case 'Q': {
@@ -722,8 +730,8 @@ int main(int argc, char *argv[])
 
         Error_Context::set_max_errors(max_errs);
         break; }
-      
-      case '-': 
+
+      case '-':
         if (!strcmp(argv[optind], "--ttcn2json")) {
           ERROR("Option `--ttcn2json' is only allowed as the first option");
         } else {
@@ -743,7 +751,7 @@ int main(int argc, char *argv[])
       if (Aflag || Lflag || Pflag || Tflag || Vflag || Yflag ||
         bflag || fflag || iflag || lflag || oflag || pflag || qflag ||
         rflag || sflag || tflag || uflag || wflag || xflag || Xflag || Rflag ||
-        Uflag || yflag || Kflag || jflag || zflag) {
+        Uflag || yflag || Kflag || jflag || zflag || Fflag) {
         errflag = true;
         print_usage = true;
       }
@@ -966,11 +974,20 @@ int main(int argc, char *argv[])
   has_xer_feature = check_feature(&lstr, FEATURE_XER);
   free_license(&lstr);
 #endif
-  if (Kflag && !check_file_list(tcov_file_name, module_list, n_modules)) {
+  if (Kflag && !check_file_list(tcov_file_name, module_list, n_modules, tcov_files)) {
        ERROR("Error while processing `%s' provided for code coverage data "
              "generation.", tcov_file_name);
        return EXIT_FAILURE;
   }
+  if (zflag) {
+    tcov_file_list *file_list_head = NULL;
+    if(!check_file_list(profiler_file_name, module_list, n_modules, file_list_head)) {
+      ERROR("Error while processing `%s' provided for profiling and code coverage.",
+        profiler_file_name);
+      return EXIT_FAILURE;
+    }
+    init_profiler_data(file_list_head);
+  }
   {
     STOPWATCH("Parsing modules");
 
@@ -1069,7 +1086,7 @@ int main(int argc, char *argv[])
     while (tcov_files != NULL) {
          tcov_file_list *next_file = tcov_files->next;
          Free(tcov_files->file_name);
-         delete tcov_files;
+         Free(tcov_files);
          tcov_files = next_file;
     }
     tcov_files = NULL;
@@ -1081,6 +1098,9 @@ int main(int argc, char *argv[])
   Common::Node::chk_counter();
   Location::delete_source_file_names();
   Free(json_schema_name);
+  if (zflag) {
+    free_profiler_data();
+  }
 
   // dbgnew.hh already does it: check_mem_leak(argv[0]);
 
index 18ec896018586b1989fa053938e0a20360f534b4..4e522034a52a595c28668cf7bfdcb6b516d6b0e3 100644 (file)
@@ -13,6 +13,7 @@ extern "C" {
 #endif
 
 #include "datatypes.h"
+#include "../common/memory.h"
 
 typedef struct tcov_file_list
 {
@@ -34,7 +35,7 @@ extern boolean generate_skeleton, force_overwrite, include_line_info,
   include_location_info, duplicate_underscores, parse_only, semantic_check_only,
   output_only_linenum, default_as_optional, use_runtime_2, gcc_compat, asn1_xer,
   check_subtype, suppress_context, enable_set_bound_out_param, display_up_to_date,
-  implicit_json_encoding, json_refs_for_all_types, profiler_enabled;
+  implicit_json_encoding, json_refs_for_all_types, force_gen_seof;
 
 extern const char *expected_platform;
 
index 79e914f389eb431f200ed97bd5a8e96df3739463..eeda1762889bd0bdd63dd12f4eb2c0bd4206b604 100644 (file)
@@ -2118,10 +2118,17 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc)
       "  embed_values_enc_struct_t* emb_val = 0;\n"
       "  if (e_xer && (p_td.xer_bits & EMBED_VALUES) && field_%s.size_of() > 1) {\n"
       "    emb_val = new embed_values_enc_struct_t;\n"
-      "    emb_val->embval_array = &field_%s;\n"
+      /* If the first field is a record of ANY-ELEMENTs, then it won't be a pre-generated
+       * record of universal charstring, so it needs a cast to avoid a compilation error */
+      "    emb_val->embval_array%s = (const PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING%s*)&field_%s;\n"
+      "    emb_val->embval_array%s = NULL;\n"
       "    emb_val->embval_index = 1;\n"
-      "    emb_val->embval_size = field_%s.size_of();\n"
-      "  }\n", sdef->elements[0].name, sdef->elements[0].name, sdef->elements[0].name);
+      "  }\n"
+      , sdef->elements[0].name
+      , sdef->elements[0].optimizedMemAlloc ? "_opt" : "_reg"
+      , sdef->elements[0].optimizedMemAlloc ? "__OPTIMIZED" : ""
+      , sdef->elements[0].name
+      , sdef->elements[0].optimizedMemAlloc ? "_reg" : "_opt");
   }
   
   if (sdef->xerUseOrderPossible) {
@@ -2223,12 +2230,12 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc)
     if (sdef->xerEmbedValuesPossible) {
       src = mputprintf(src,
         "    if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n"
-        "        emb_val->embval_index < emb_val->embval_size) { // embed-val\n"
+        "        emb_val->embval_index < field_%s.size_of()) { // embed-val\n"
         "      field_%s[emb_val->embval_index].XER_encode(\n"
         "        UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
         "      ++emb_val->embval_index;\n"
         "    }\n"
-        , sdef->elements[0].name);
+        , sdef->elements[0].name, sdef->elements[0].name);
     }
 
 
@@ -2255,27 +2262,27 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc)
       if (sdef->xerEmbedValuesPossible) {
         src = mputprintf(src,
           "  if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n"
-          "      emb_val->embval_index < emb_val->embval_size) {\n"
+          "      emb_val->embval_index < field_%s.size_of()) {\n"
           "    field_%s[emb_val->embval_index].XER_encode(\n"
           "      UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
           "    ++emb_val->embval_index;\n"
           "  }\n"
-          , sdef->elements[0].name);
+          , sdef->elements[0].name, sdef->elements[0].name);
       }
     } /* next field when not USE-ORDER */
 
   if (sdef->xerEmbedValuesPossible) {
     src = mputprintf(src,
       "  if (0 != emb_val) {\n"
-      "    if (emb_val->embval_index < emb_val->embval_size) {\n"
+      "    if (emb_val->embval_index < field_%s.size_of()) {\n"
       "      ec_1.set_msg(\"%s': \");\n"
       "      TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n"
       "        \"Too many EMBED-VALUEs specified: %%d (expected %%d or less)\",\n"
-      "        emb_val->embval_size, emb_val->embval_index);\n"
+      "        field_%s.size_of(), emb_val->embval_index);\n"
       "    }\n"
       "    delete emb_val;\n"
       "  }\n"
-      , sdef->elements[0].name);
+      , sdef->elements[0].name, sdef->elements[0].name, sdef->elements[0].name);
   }
 
   src = mputstr(src, "  } // QN?\n");
@@ -2636,10 +2643,18 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc)
       "  embed_values_dec_struct_t* emb_val = 0;\n"
       "  if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n"
       "    emb_val = new embed_values_dec_struct_t;\n"
-      "    emb_val->embval_array = &field_%s;\n"
+      /* If the first field is a record of ANY-ELEMENTs, then it won't be a pre-generated
+       * record of universal charstring, so it needs a cast to avoid a compilation error */
+      "    emb_val->embval_array%s = (PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING%s*)&field_%s;\n"
+      "    emb_val->embval_array%s = NULL;\n"
       "    emb_val->embval_index = 0;\n"
       "    field_%s.set_size(0);\n"
-      "  }\n", sdef->elements[0].name, sdef->elements[0].name);
+      "  }\n"
+      , sdef->elements[0].optimizedMemAlloc ? "_opt" : "_reg"
+      , sdef->elements[0].optimizedMemAlloc ? "__OPTIMIZED" : ""
+      , sdef->elements[0].name
+      , sdef->elements[0].optimizedMemAlloc ? "_reg" : "_opt"
+      , sdef->elements[0].name);
   }
 
   if (sdef->xerUseOrderPossible) {
index b820722e988d8c3bb1fe6cf705b62500ba558375..5f97b3d90634d15e4cd15670fef550ce496c0f74 100644 (file)
@@ -39,11 +39,11 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
   char *def = NULL, *src = NULL;
   const char *name = sdef->name, *dispname = sdef->dispname;
   const char *type = sdef->type;
-  boolean ber_needed = sdef->isASN1 && enable_ber();
-  boolean raw_needed = sdef->hasRaw && enable_raw();
-  boolean text_needed = sdef->hasText && enable_text();
-  boolean xer_needed = sdef->hasXer && enable_xer();
-  boolean json_needed = sdef->hasJson && enable_json();
+  boolean ber_needed = force_gen_seof || (sdef->isASN1 && enable_ber());
+  boolean raw_needed = force_gen_seof || (sdef->hasRaw && enable_raw());
+  boolean text_needed = force_gen_seof || (sdef->hasText && enable_text());
+  boolean xer_needed = force_gen_seof || (sdef->hasXer && enable_xer());
+  boolean json_needed = force_gen_seof || (sdef->hasJson && enable_json());
 
   /* Class definition and private data members */
   def = mputprintf(def,
@@ -723,7 +723,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "    p_buf.put_cs(*p_td.text->separator_encode);\n"
       "    encoded_length+=p_td.text->separator_encode->lengthof();\n"
       "   }\n"
-      "   encoded_length+=(*this)[a].TEXT_encode(%s_descr_,p_buf);\n"
+      "   encoded_length+=(*this)[a].TEXT_encode(*p_td.oftype_descr,p_buf);\n"
       "  }\n"
       "  if(p_td.text->end_encode){\n"
       "    p_buf.put_cs(*p_td.text->end_encode);\n"
@@ -731,7 +731,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "  }\n"
       "  return encoded_length;\n"
       "}\n"
-      ,name,sdef->oftypedescrname
+      ,name
       );
     src = mputprintf(src,
       "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
@@ -774,7 +774,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "  while(TRUE){\n"
       "    %s *val=new %s;\n"
       "    pos=p_buf.get_pos();\n"
-      "    int len=val->TEXT_decode(%s_descr_,p_buf,limit,TRUE);\n"
+      "    int len=val->TEXT_decode(*p_td.oftype_descr,p_buf,limit,TRUE);\n"
       "    if(len==-1 || (len==0 && !limit.has_token())){\n"
       "      p_buf.set_pos(pos);\n"
       "      delete val;\n"
@@ -816,7 +816,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "      }\n"
       "    }\n"
       "  }\n"
-      ,name,type,type,sdef->oftypedescrname,type
+      ,name,type,type,type
      );
     src = mputstr(src,
       "   limit.remove_tokens(ml);\n"
@@ -871,7 +871,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
        "    for(int elem_i=0; elem_i<val_ptr->n_elements; elem_i++) {\n"
        "      ec.set_msg(\"Component #%%d: \", elem_i);\n"
        "      new_tlv->add_TLV((*this)[elem_i].BER_encode_TLV"
-       "(%s_descr_, p_coding));\n"
+       "(*p_td.oftype_descr, p_coding));\n"
        "    }\n"
        "%s"
        "  }\n"
@@ -905,16 +905,16 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
        "val_ptr->n_elements + 1);\n"
        "    val_ptr->n_elements++;\n"
        "    val_ptr->value_elements[val_ptr->n_elements - 1] = new %s;\n"
-       "    val_ptr->value_elements[val_ptr->n_elements - 1]->BER_decode_TLV(%s_descr_, tmp_tlv, "
+       "    val_ptr->value_elements[val_ptr->n_elements - 1]->BER_decode_TLV(*p_td.oftype_descr, tmp_tlv, "
        "L_form);\n"
        "    ec_2.set_msg(\"%%d: \", val_ptr->n_elements);\n"
        "  }\n"
        "  return TRUE;\n"
        "}\n"
        "\n"
-       , name, sdef->oftypedescrname
+       , name
        , sdef->kind==SET_OF?"    new_tlv->sort_tlvs();\n":""
-       , name, type, type, sdef->oftypedescrname
+       , name, type, type
        );
 
     if(sdef->has_opentypes) {
@@ -966,7 +966,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
     "    int a=0;\n"
     "    if(sel_field==-1) sel_field=p_td.raw->fieldlength;\n"
     "    for(a=0;a<sel_field;a++){\n"
-    "      decoded_field_length=(*this)[a+start_field].RAW_decode(%s_descr_,"
+    "      decoded_field_length=(*this)[a+start_field].RAW_decode(*p_td.oftype_descr,"
     "p_buf,limit,top_bit_ord,TRUE);\n"
     "      if(decoded_field_length < 0) return decoded_field_length;\n"
     "      decoded_length+=decoded_field_length;\n"
@@ -983,7 +983,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
     "    }\n"
     "    while(limit>0){\n"
     "      start_of_field=p_buf.get_pos_bit();\n"
-    "      decoded_field_length=(*this)[a].RAW_decode(%s_descr_,p_buf,limit,"
+    "      decoded_field_length=(*this)[a].RAW_decode(*p_td.oftype_descr,p_buf,limit,"
     "top_bit_ord,TRUE);\n"
     "      if(decoded_field_length < 0){\n"
     "        delete &(*this)[a];\n"
@@ -997,13 +997,16 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
     "      decoded_length+=decoded_field_length;\n"
     "      limit-=decoded_field_length;\n"
     "      a++;\n"
-    ,name,sdef->oftypedescrname,sdef->oftypedescrname
+    ,name
     );
-    if(sdef->raw.extension_bit!=XDEFNO && sdef->raw.extension_bit!=XDEFDEFAULT){
+    if (force_gen_seof || (sdef->raw.extension_bit!=XDEFNO && sdef->raw.extension_bit!=XDEFDEFAULT)){
       src=mputprintf(src,
-    "      if (%sp_buf.get_last_bit())\n"
+    "      if (%s%sp_buf.get_last_bit()%s)\n"
     "        return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)"
-    "+prepaddlength;\n", sdef->raw.extension_bit == XDEFYES ? "" : "!");
+    "+prepaddlength;\n"
+    , force_gen_seof ? "EXT_BIT_NO != p_td.raw->extension_bit && ((EXT_BIT_YES != p_td.raw->extension_bit) ^ " : ""
+    , (force_gen_seof || sdef->raw.extension_bit == XDEFYES) ? "" : "!"
+    , force_gen_seof ? ")" : "");
     }
       src=mputprintf(src,
     "    }\n"
@@ -1023,12 +1026,12 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
     "  myleaf.body.node.nodes=init_nodes_of_enc_tree(encoded_num_of_records);\n"
     "  for(int a=0;a<encoded_num_of_records;a++){\n"
     "    myleaf.body.node.nodes[a]=new RAW_enc_tree(TRUE,&myleaf,"
-    "&(myleaf.curr_pos),a,%s_descr_.raw);\n"
-    "    encoded_length+=(*this)[a].RAW_encode(%s_descr_,"
+    "&(myleaf.curr_pos),a,p_td.oftype_descr->raw);\n"
+    "    encoded_length+=(*this)[a].RAW_encode(*p_td.oftype_descr,"
     "*myleaf.body.node.nodes[a]);\n"
     "  }\n"
     " return myleaf.length=encoded_length;\n}\n\n"
-    , name, sdef->oftypedescrname, sdef->oftypedescrname
+    , name
     );
   }
 
@@ -1042,10 +1045,12 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "boolean %s::can_start(const char *name, const char *uri, "
       "XERdescriptor_t const& xd, unsigned int flavor) {\n"
       "  boolean e_xer = is_exer(flavor);\n"
-      "  if (e_xer && (xd.xer_bits & ANY_ELEMENT)) "
+      "  if ((!e_xer || !(xd.xer_bits & UNTAGGED)) && !(flavor & XER_RECOF)) return "
+      "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
+      "  if (e_xer && (xd.oftype_descr->xer_bits & ANY_ELEMENT)) "
       , name
       );
-    if (sdef->nFollowers) {
+    if (!force_gen_seof && sdef->nFollowers) {
       /* If there are optional fields following the record-of, then seeing
        * {any XML tag that belongs to those fields} where the record-of may be
        * means that the record-of is empty. */
@@ -1065,12 +1070,9 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
     else src = mputstr(src, "return TRUE;\n");
 
     src = mputprintf(src,
-      "  if ((!e_xer || !(xd.xer_bits & UNTAGGED)) && !(flavor & XER_RECOF)) return "
-      "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
-      "  else return %s::can_start(name, uri, %s_xer_, flavor | XER_RECOF);\n"
+      "  return %s::can_start(name, uri, *xd.oftype_descr, flavor | XER_RECOF);\n"
       "}\n\n"
       , sdef->type
-      , sdef->oftypedescrname
       );
 
     src = mputprintf(src,
@@ -1083,7 +1085,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "    size_t num_new;\n"
       "    for (int i = 0; i < val_ptr->n_elements; ++i) {\n"
       "      bool def_ns_1 = false;"
-      "      new_ns = (*this)[i].collect_ns(%s_xer_, num_new, def_ns_1);\n"
+      "      new_ns = (*this)[i].collect_ns(*p_td.oftype_descr, num_new, def_ns_1);\n"
       "      merge_ns(collected_ns, num_collected, new_ns, num_new);\n"
       "      def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */
       "    }\n"
@@ -1098,7 +1100,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "  num = num_collected;\n"
       "  return collected_ns;\n"
       "}\n\n"
-      , name, sdef->oftypedescrname);
+      , name);
 
     src=mputprintf(src,
       "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
@@ -1112,16 +1114,18 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "%s" /* Factor out p_indent if not attribute */
       "  if (val_ptr->n_elements==0) {\n" /* Empty record of */
       , name
-      , sdef->xerAttribute ? "" : "  if (indenting) do_indent(p_buf, p_indent);\n"
+      , force_gen_seof ? "  if (indenting && !(p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
+      : (sdef->xerAttribute ? "" : "  if (indenting) do_indent(p_buf, p_indent);\n")
       );
-    if (sdef->xerAttribute) {
-      src=mputstr(src,
-        "    if (e_xer) {\n" /* Empty attribute. */
+    if (force_gen_seof || sdef->xerAttribute) {
+      src=mputprintf(src,
+        "    if (e_xer%s) {\n" /* Empty attribute. */
         "      begin_attribute(p_td, p_buf);\n"
         "      p_buf.put_c('\\'');\n"
-        "    } else\n");
+        "    } else\n"
+        , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
     }
-    else {
+    if (force_gen_seof || !sdef->xerAttribute) {
       src = mputstr(src,
         "    if (own_tag)");
     }
@@ -1149,7 +1153,8 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "    }\n"
       "  }\n"
       "  else {\n" /* Not empty record of. Start tag or attribute */
-      , sdef->xerAttribute ? "      if (indenting) do_indent(p_buf, p_indent);\n" : ""
+      , force_gen_seof ? "      if (indenting && (p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
+      : (sdef->xerAttribute ? "      if (indenting) do_indent(p_buf, p_indent);\n" : "")
       );
     if (sdef->xerAnyAttrElem) {
       src = mputstr(src,
@@ -1236,11 +1241,12 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
         "      p_buf.put_s(shorter, saved);\n" /* restore the '>' and anything after */
         "    } else {\n");
     }
-    if (sdef->xerAttribute) {
-      src=mputstr(src,
-        "    if (e_xer) {\n"
+    if (force_gen_seof || sdef->xerAttribute) {
+      src=mputprintf(src,
+        "    if (e_xer%s) {\n"
         "      begin_attribute(p_td, p_buf);\n"
-        "    } else\n");
+        "    } else\n"
+        , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
     }
     src=mputprintf(src,
       "    if (own_tag) {\n"
@@ -1266,7 +1272,8 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "        Free(collected_ns);\n"
       "        p_buf.put_s(1 + keep_newline, (cbyte*)\">\\n\");\n"
       "      }\n"
-      , sdef->xerAttribute ? "      if (indenting) do_indent(p_buf, p_indent);\n" : ""
+      , force_gen_seof ? "      if (indenting && (p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
+      : (sdef->xerAttribute ? "      if (indenting) do_indent(p_buf, p_indent);\n" : "")
       );
     if (sdef->xmlValueList) {
       src=mputstr(src, "      if (indenting && !e_xer) do_indent(p_buf, p_indent+1);\n"); /* !e_xer or GDMO */
@@ -1277,20 +1284,26 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "    TTCN_EncDec_ErrorContext ec_0(\"Index \");\n"
       "    TTCN_EncDec_ErrorContext ec_1;\n"
       );
-    src=mputprintf(src,
+    src=mputstr(src,
       "    for (int i = 0; i < val_ptr->n_elements; ++i) {\n"
-      /*"      if (i > 0 && !own_tag && 0 != emb_val &&\n"
-      "          emb_val->embval_index < emb_val->embval_size) {\n"
-      "        emb_val->embval_array->get_embedded_value(emb_val->embval_index).XER_encode(\n"
-      "          UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
+      "      if (i > 0 && !own_tag && 0 != emb_val &&\n"
+      "          emb_val->embval_index < (0 != emb_val->embval_array_reg ?\n"
+      "          emb_val->embval_array_reg->size_of() : emb_val->embval_array_opt->size_of())) {\n"
+      "        if (0 != emb_val->embval_array_reg) {\n"
+      "          (*emb_val->embval_array_reg)[emb_val->embval_index].XER_encode(\n"
+      "            UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
+      "        }\n"
+      "        else {\n"
+      "          (*emb_val->embval_array_opt)[emb_val->embval_index].XER_encode(\n"
+      "            UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
+      "        }\n"
       "        ++emb_val->embval_index;\n"
-      "      }\n" - temporarily removed in RT1 */
-      "      ec_1.set_msg(\"%%d: \", i);\n"
+      "      }\n"
+      "      ec_1.set_msg(\"%d: \", i);\n"
       "      if (e_xer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');\n"
-      "      (*this)[i].XER_encode(%s_xer_, p_buf, p_flavor, p_indent+own_tag, emb_val);\n"
+      "      (*this)[i].XER_encode(*p_td.oftype_descr, p_buf, p_flavor, p_indent+own_tag, emb_val);\n"
       "    }\n"
-      "    if (indenting && !is_exerlist(p_flavor)) {\n",
-      sdef->oftypedescrname
+      "    if (indenting && !is_exerlist(p_flavor)) {\n"
     );
     if (sdef->xmlValueList) {
       src=mputstr(src, "      if (!e_xer) p_buf.put_c('\\n');\n"); /* !e_xer or GDMO */
@@ -1298,10 +1311,11 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
     src=mputstr(src,
       "      do_indent(p_buf, p_indent);\n"
       "    }\n");
-    if (sdef->xerAttribute) {
-      src=mputstr(src,
-        "    if (e_xer) p_buf.put_c('\\'');\n"
-        "    else\n");
+    if (force_gen_seof || sdef->xerAttribute) {
+      src=mputprintf(src,
+        "    if (e_xer%s) p_buf.put_c('\\'');\n"
+        "    else\n"
+        , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
     }
     src=mputstr(src,
       "    if (own_tag){\n"
@@ -1357,13 +1371,15 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "  }\n" /* next read */
       "  else xml_depth = p_reader.Depth();\n"
       "  p_flavor |= XER_RECOF;\n"
+      "  TTCN_EncDec_ErrorContext ec_0(\"Index \");\n"
+      "  TTCN_EncDec_ErrorContext ec_1;\n"
 #ifndef NDEBUG
       , __FUNCTION__, __LINE__
 #endif
       , name
       );
 
-    src = mputprintf(src,
+    src = mputstr(src,
       "  if (e_xer && (p_td.xer_bits & XER_LIST)) {\n" /* LIST decoding*/
       "    char *x_val = (char*)p_reader.NewValue();\n" /* we own it */
       "    size_t x_pos = 0;\n"
@@ -1377,13 +1393,13 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "      x_pos += strlen(str) + 1;\n"
       "      TTCN_Buffer buf_2;\n"
       "      buf_2.put_c('<');\n"
-      "      write_ns_prefix(%s_xer_, buf_2);\n"
-      "      const char * const exer_name = %s_xer_.names[1];\n"
-      "      boolean i_can_has_ns = %s_xer_.my_module != 0 && %s_xer_.ns_index != -1;\n"
+      "      write_ns_prefix(*p_td.oftype_descr, buf_2);\n"
+      "      const char * const exer_name = p_td.oftype_descr->names[1];\n"
+      "      boolean i_can_has_ns = p_td.oftype_descr->my_module != 0 && p_td.oftype_descr->ns_index != -1;\n"
       /* If it has a namespace, chop off the '>' from the end */
-      "      buf_2.put_s((size_t)%s_xer_.namelens[1]-1-i_can_has_ns, (cbyte*)exer_name);\n"
+      "      buf_2.put_s((size_t)p_td.oftype_descr->namelens[1]-1-i_can_has_ns, (cbyte*)exer_name);\n"
       "      if (i_can_has_ns) {\n"
-      "        const namespace_t * const pns = %s_xer_.my_module->get_ns(%s_xer_.ns_index);\n"
+      "        const namespace_t * const pns = p_td.oftype_descr->my_module->get_ns(p_td.oftype_descr->ns_index);\n"
       "        buf_2.put_s(7 - (*pns->px == 0), (cbyte*)\" xmlns:\");\n"
       "        buf_2.put_s(strlen(pns->px), (cbyte*)pns->px);\n"
       "        buf_2.put_s(2, (cbyte*)\"='\");\n"
@@ -1394,14 +1410,15 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "      buf_2.put_s(strlen(str), (cbyte*)str);\n"
       "      buf_2.put_c('<');\n"
       "      buf_2.put_c('/');\n"
-      "      write_ns_prefix(%s_xer_, buf_2);\n"
-      "      buf_2.put_s((size_t)%s_xer_.namelens[1], (cbyte*)exer_name);\n"
+      "      write_ns_prefix(*p_td.oftype_descr, buf_2);\n"
+      "      buf_2.put_s((size_t)p_td.oftype_descr->namelens[1], (cbyte*)exer_name);\n"
       "      XmlReaderWrap reader_2(buf_2);\n"
       "      rd_ok = reader_2.Read();\n" /* Move to the start element. */
+      "      ec_1.set_msg(\"%d: \", val_ptr->n_elements);\n"
       /* Don't move to the #text, that's the callee's responsibility. */
       /* The call to the non-const operator[] creates a new element object,
        * then we call its XER_decode with the temporary XML reader. */
-      "      (*this)[val_ptr->n_elements].XER_decode(%s_xer_, reader_2, p_flavor, 0);\n"
+      "      (*this)[val_ptr->n_elements].XER_decode(*p_td.oftype_descr, reader_2, p_flavor, 0);\n"
       "      if (p_flavor & EXIT_ON_ERROR && !(*this)[val_ptr->n_elements - 1].is_bound()) {\n"
       "        if (1 == val_ptr->n_elements) {\n"
       // Failed to decode even the first element
@@ -1423,11 +1440,6 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "      p_reader.Read();\n" /* past it */
       "    }\n"
       "  }\n"
-      , sdef->oftypedescrname, sdef->oftypedescrname
-      , sdef->oftypedescrname, sdef->oftypedescrname
-      , sdef->oftypedescrname, sdef->oftypedescrname
-      , sdef->oftypedescrname, sdef->oftypedescrname
-      , sdef->oftypedescrname, sdef->oftypedescrname
     );
 
     src = mputprintf(src,
@@ -1457,17 +1469,18 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
         "            if (p_reader.NodeType() != XML_READER_TYPE_ELEMENT) rd_ok = p_reader.Read();\n"
         "          } else");
     }
-    src = mputprintf(src,
+    src = mputstr(src,
       "          {\n"
       /* An untagged record-of ends if it encounters an element with a name
        * that doesn't match its component */
       "            if (!own_tag && !can_start((const char*)p_reader.LocalName(), "
-      "(const char*)p_reader.NamespaceUri(), %s_xer_, p_flavor)) {\n"
+      "(const char*)p_reader.NamespaceUri(), p_td, p_flavor)) {\n"
       "              for (; rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
       "              break;\n"
       "            }\n"
+      "            ec_1.set_msg(\"%d: \", val_ptr->n_elements);\n"
       /* The call to the non-const operator[] creates the element */
-      "            (*this)[val_ptr->n_elements].XER_decode(%s_xer_, p_reader, p_flavor, emb_val);\n"
+      "            (*this)[val_ptr->n_elements].XER_decode(*p_td.oftype_descr, p_reader, p_flavor, emb_val);\n"
       "            if (0 != emb_val && !own_tag && val_ptr->n_elements > 1) {\n"
       "              ++emb_val->embval_index;\n"
       "            }\n"      
@@ -1481,11 +1494,16 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "          }\n"
       "          break;\n"
       "        }\n"
-      /*"        else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && get_nof_elements() > 0) {\n"
+      "        else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && val_ptr->n_elements > 0) {\n"
       "          UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
-      "          emb_val->embval_array->set_embedded_value(emb_val->embval_index, emb_ustr);\n"
+      "          if (0 != emb_val->embval_array_reg) {\n"
+      "            (*emb_val->embval_array_reg)[emb_val->embval_index] = emb_ustr;\n"
+      "          }\n"
+      "          else {\n"
+      "            (*emb_val->embval_array_opt)[emb_val->embval_index] = emb_ustr;\n"
+      "          }\n"
       "          rd_ok = p_reader.Read();\n"
-      "        }\n" - temporarily removed in RT1 */
+      "        }\n"
       "        else {\n"
       "          rd_ok = p_reader.Read();\n"
       "        }\n"
@@ -1494,13 +1512,12 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "  }\n" /* if not LIST */
       "  return 1;\n"
       "}\n\n"
-      , sdef->oftypedescrname, sdef->oftypedescrname
     );
   }
   if (json_needed) {
     // JSON encode, RT1
     src = mputprintf(src,
-      "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
+      "int %s::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const\n"
       "{\n"
       "  if (!is_bound()) {\n"
       "    TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
@@ -1509,18 +1526,18 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "  }\n\n"
       "  int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);\n"
       "  for(int i = 0; i < val_ptr->n_elements; ++i) {\n"
-      "    int ret_val = (*this)[i].JSON_encode(%s_descr_, p_tok);\n"
+      "    int ret_val = (*this)[i].JSON_encode(*p_td.oftype_descr, p_tok);\n"
       "    if (0 > ret_val) break;\n"
       "    enc_len += ret_val;\n"
       "  }\n"
       "  enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);\n"
       "  return enc_len;\n"
       "}\n\n"
-      , name, dispname, sdef->oftypedescrname);
+      , name, dispname);
     
     // JSON decode, RT1
     src = mputprintf(src,
-      "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
+      "int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)\n"
       "{\n"
       "  json_token_t token = JSON_TOKEN_NONE;\n"
       "  int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
@@ -1535,7 +1552,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "  while (true) {\n"
       "    size_t buf_pos = p_tok.get_buf_pos();\n"
       "    %s* val = new %s;\n"
-      "    int ret_val = val->JSON_decode(%s_descr_, p_tok, p_silent);\n"
+      "    int ret_val = val->JSON_decode(*p_td.oftype_descr, p_tok, p_silent);\n"
       "    if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n"
       "      p_tok.set_buf_pos(buf_pos);\n"
       "      delete val;\n"
@@ -1564,7 +1581,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "  }\n\n"
       "  return dec_len;\n"
       "}\n\n"
-      , name, type, type, sdef->oftypedescrname, type);
+      , name, type, type, type);
   }
   /* end of class */
   def = mputstr(def, "};\n\n");
@@ -1604,11 +1621,11 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
   char *def = NULL, *src = NULL;
   const char *name = sdef->name, *dispname = sdef->dispname;
   const char *type = sdef->type;
-  boolean ber_needed = sdef->isASN1 && enable_ber();
-  boolean raw_needed = sdef->hasRaw && enable_raw();
-  boolean text_needed = sdef->hasText && enable_text();
-  boolean xer_needed = sdef->hasXer && enable_xer();
-  boolean json_needed = sdef->hasJson && enable_json();
+  boolean ber_needed = force_gen_seof || (sdef->isASN1 && enable_ber());
+  boolean raw_needed = force_gen_seof || (sdef->hasRaw && enable_raw());
+  boolean text_needed = force_gen_seof || (sdef->hasText && enable_text());
+  boolean xer_needed = force_gen_seof || (sdef->hasXer && enable_xer());
+  boolean json_needed = force_gen_seof || (sdef->hasJson && enable_json());
 
   /* Class definition and private data members */
   def = mputprintf(def,
@@ -1684,7 +1701,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
   /* constructors */
   def = mputprintf(def, "%s(): n_elements(-1), value_elements(NULL) {}\n", name);
 
-  def = mputprintf(def, "%s(null_type other_value): n_elements(0), value_elements(NULL) {}\n", name);
+  def = mputprintf(def, "%s(null_type): n_elements(0), value_elements(NULL) {}\n", name);
 
   /* copy constructor */
   def = mputprintf(def, "%s(const %s& other_value) { copy_value(other_value); }\n", name, name);
@@ -2176,7 +2193,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "    p_buf.put_cs(*p_td.text->separator_encode);\n"
       "    encoded_length+=p_td.text->separator_encode->lengthof();\n"
       "   }\n"
-      "   encoded_length+=value_elements[a].TEXT_encode(%s_descr_,p_buf);\n"
+      "   encoded_length+=value_elements[a].TEXT_encode(*p_td.oftype_descr,p_buf);\n"
       "  }\n"
       "  if(p_td.text->end_encode){\n"
       "    p_buf.put_cs(*p_td.text->end_encode);\n"
@@ -2184,7 +2201,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "  }\n"
       "  return encoded_length;\n"
       "}\n"
-      ,name,sdef->oftypedescrname
+      ,name
       );
     src = mputprintf(src,
       "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
@@ -2223,7 +2240,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "  while(TRUE){\n"
       "    %s val;\n"
       "    pos=p_buf.get_pos();\n"
-      "    int len=val.TEXT_decode(%s_descr_,p_buf,limit,TRUE);\n"
+      "    int len=val.TEXT_decode(*p_td.oftype_descr,p_buf,limit,TRUE);\n"
       "    if(len==-1 || (len==0 && !limit.has_token())){\n"
       "      p_buf.set_pos(pos);\n"
       "      if(sep_found){\n"
@@ -2261,7 +2278,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "      }\n"
       "    }\n"
       "  }\n"
-      ,name,type,sdef->oftypedescrname
+      ,name,type
      );
     src = mputstr(src,
       "   limit.remove_tokens(ml);\n"
@@ -2315,7 +2332,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
        "    for(int elem_i=0; elem_i<n_elements; elem_i++) {\n"
        "      ec.set_msg(\"Component #%%d: \", elem_i);\n"
        "      new_tlv->add_TLV(value_elements[elem_i].BER_encode_TLV"
-       "(%s_descr_, p_coding));\n"
+       "(*p_td.oftype_descr, p_coding));\n"
        "    }\n"
        "%s"
        "  }\n"
@@ -2341,16 +2358,16 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
        "  while(BER_decode_constdTLV_next(stripped_tlv, V_pos, L_form, "
        "tmp_tlv)) {\n"
        "  set_size(n_elements+1);\n"
-       "  value_elements[n_elements-1].BER_decode_TLV(%s_descr_, tmp_tlv, "
+       "  value_elements[n_elements-1].BER_decode_TLV(*p_td.oftype_descr, tmp_tlv, "
          "L_form);\n"
        "  ec_2.set_msg(\"%%d: \", n_elements);\n"
        "  }\n"
        "  return TRUE;\n"
        "}\n"
        "\n"
-       , name, sdef->oftypedescrname
+       , name
        , sdef->kind==SET_OF?"    new_tlv->sort_tlvs();\n":""
-       , name, sdef->oftypedescrname
+       , name
        );
 
     if(sdef->has_opentypes) {
@@ -2396,7 +2413,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
     "    int a=0;\n"
     "    if(sel_field==-1) sel_field=p_td.raw->fieldlength;\n"
     "    for(a=0;a<sel_field;a++){\n"
-    "      decoded_field_length=(*this)[a+start_field].RAW_decode(%s_descr_,"
+    "      decoded_field_length=(*this)[a+start_field].RAW_decode(*p_td.oftype_descr,"
     "p_buf,limit,top_bit_ord,TRUE);\n"
     "      if(decoded_field_length < 0) return decoded_field_length;\n"
     "      decoded_length+=decoded_field_length;\n"
@@ -2413,7 +2430,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
     "    }\n"
     "    while(limit>0){\n"
     "      start_of_field=p_buf.get_pos_bit();\n"
-    "      decoded_field_length=(*this)[a].RAW_decode(%s_descr_,p_buf,limit,"
+    "      decoded_field_length=(*this)[a].RAW_decode(*p_td.oftype_descr,p_buf,limit,"
     "top_bit_ord,TRUE);\n"
     "      if(decoded_field_length < 0){\n"
     /*"        delete &(*this)[a];\n"*/
@@ -2427,7 +2444,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
     "      decoded_length+=decoded_field_length;\n"
     "      limit-=decoded_field_length;\n"
     "      a++;\n"
-    ,name,sdef->oftypedescrname,sdef->oftypedescrname
+    ,name
     );
     if(sdef->raw.extension_bit!=XDEFNO && sdef->raw.extension_bit!=XDEFDEFAULT){
       src=mputprintf(src,
@@ -2452,12 +2469,12 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
     "  myleaf.body.node.nodes=init_nodes_of_enc_tree(encoded_num_of_records);\n"
     "  for(int a=0;a<encoded_num_of_records;a++){\n"
     "    myleaf.body.node.nodes[a]=new RAW_enc_tree(TRUE,&myleaf,"
-    "&(myleaf.curr_pos),a,%s_descr_.raw);\n"
-    "    encoded_length+=(*this)[a].RAW_encode(%s_descr_,"
+    "&(myleaf.curr_pos),a,p_td.oftype_descr->raw);\n"
+    "    encoded_length+=(*this)[a].RAW_encode(*p_td.oftype_descr,"
     "*myleaf.body.node.nodes[a]);\n"
     "  }\n"
     " return myleaf.length=encoded_length;\n}\n\n"
-    , name, sdef->oftypedescrname, sdef->oftypedescrname
+    , name
     );
   }
 
@@ -2471,10 +2488,12 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "boolean %s::can_start(const char *name, const char *uri, "
       "XERdescriptor_t const& xd, unsigned int flavor) {\n"
       "  boolean e_xer = is_exer(flavor);\n"
-      "  if (e_xer && (xd.xer_bits & ANY_ELEMENT)) "
+      "  if ((!e_xer || !(xd.xer_bits & UNTAGGED)) && !(flavor & XER_RECOF)) return "
+      "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
+      "  if (e_xer && (xd.oftype_descr->xer_bits & ANY_ELEMENT)) "
       , name
       );
-    if (sdef->nFollowers) {
+    if (!force_gen_seof && sdef->nFollowers) {
       /* If there are optional fields following the record-of, then seeing
        * {any XML tag that belongs to those fields} where the record-of may be
        * means that the record-of is empty. */
@@ -2494,12 +2513,9 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
     else src = mputstr(src, "return TRUE;\n");
 
     src = mputprintf(src,
-      "  if ((!e_xer || !(xd.xer_bits & UNTAGGED)) && !(flavor & XER_RECOF)) return "
-      "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
-      "  else return %s::can_start(name, uri, %s_xer_, flavor | XER_RECOF);\n"
+      "  return %s::can_start(name, uri, *xd.oftype_descr, flavor | XER_RECOF);\n"
       "}\n\n"
       , sdef->type
-      , sdef->oftypedescrname
       );
 
     src = mputprintf(src,
@@ -2512,7 +2528,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "    size_t num_new;\n"
       "    for (int i = 0; i < n_elements; ++i) {\n"
       "      bool def_ns_1 = false;"
-      "      new_ns = value_elements[i].collect_ns(%s_xer_, num_new, def_ns_1);\n"
+      "      new_ns = value_elements[i].collect_ns(*p_td.oftype_descr, num_new, def_ns_1);\n"
       "      merge_ns(collected_ns, num_collected, new_ns, num_new);\n"
       "      def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */
       "    }\n"
@@ -2527,7 +2543,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "  num = num_collected;\n"
       "  return collected_ns;\n"
       "}\n\n"
-      , name, sdef->oftypedescrname);
+      , name);
 
     src=mputprintf(src,
       "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
@@ -2541,16 +2557,18 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "%s" /* Factor out p_indent if not attribute */
       "  if (n_elements==0) {\n" /* Empty record of */
       , name
-      , sdef->xerAttribute ? "" : "  if (indenting) do_indent(p_buf, p_indent);\n"
+      , force_gen_seof ? "  if (indenting && !(p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
+      : (sdef->xerAttribute ? "" : "  if (indenting) do_indent(p_buf, p_indent);\n")
       );
-    if (sdef->xerAttribute) {
-      src=mputstr(src,
-        "    if (e_xer) {\n" /* Empty attribute. */
+    if (force_gen_seof || sdef->xerAttribute) {
+      src=mputprintf(src,
+        "    if (e_xer%s) {\n" /* Empty attribute. */
         "      begin_attribute(p_td, p_buf);\n"
         "      p_buf.put_c('\\'');\n"
-        "    } else\n");
+        "    } else\n"
+        , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
     }
-    else {
+    if (force_gen_seof || !sdef->xerAttribute) {
       src = mputstr(src,
         "    if (own_tag)");
     }
@@ -2578,7 +2596,8 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "    }\n"
       "  }\n"
       "  else {\n" /* Not empty record of. Start tag or attribute */
-      , sdef->xerAttribute ? "      if (indenting) do_indent(p_buf, p_indent);\n" : ""
+      , force_gen_seof ? "  if (indenting && !(p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
+      : (sdef->xerAttribute ? "" : "  if (indenting) do_indent(p_buf, p_indent);\n")
       );
     if (sdef->xerAnyAttrElem) {
       src = mputstr(src,
@@ -2660,11 +2679,12 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
         "      p_buf.put_s(shorter, saved);\n" /* restore the '>' and anything after */
         "    } else {\n");
     }
-    if (sdef->xerAttribute) {
-      src=mputstr(src,
-        "    if (e_xer) {\n"
+    if (force_gen_seof || sdef->xerAttribute) {
+      src=mputprintf(src,
+        "    if (e_xer%s) {\n"
         "      begin_attribute(p_td, p_buf);\n"
-        "    } else\n");
+        "    } else\n"
+        , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
     }
     src=mputprintf(src,
       "    if (own_tag) {\n"
@@ -2690,7 +2710,8 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "        Free(collected_ns);\n"
       "        p_buf.put_s(1 + keep_newline, (cbyte*)\">\\n\");\n"
       "      }\n"
-      , sdef->xerAttribute ? "      if (indenting) do_indent(p_buf, p_indent);\n" : ""
+      , force_gen_seof ? "      if (indenting && (p_td.xer_bits & XER_ATTRIBUTE)) do_indent(p_buf, p_indent);\n"
+      : (sdef->xerAttribute ? "      if (indenting) do_indent(p_buf, p_indent);\n" : "")
       );
     if (sdef->xmlValueList) {
       src=mputstr(src, "      if (indenting && !e_xer) do_indent(p_buf, p_indent+1);\n"); /* !e_xer or GDMO */
@@ -2701,20 +2722,26 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "    TTCN_EncDec_ErrorContext ec_0(\"Index \");\n"
       "    TTCN_EncDec_ErrorContext ec_1;\n"
       );
-    src=mputprintf(src,
+    src=mputstr(src,
       "    for (int i = 0; i < n_elements; ++i) {\n"
-      /*"      if (i > 0 && !own_tag && 0 != emb_val &&\n"
-      "          emb_val->embval_index < emb_val->embval_size) {\n"
-      "        emb_val->embval_array->get_embedded_value(emb_val->embval_index).XER_encode(\n"
-      "          UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
+      "      if (i > 0 && !own_tag && 0 != emb_val &&\n"
+      "          emb_val->embval_index < (0 != emb_val->embval_array_reg ?\n"
+      "          emb_val->embval_array_reg->size_of() : emb_val->embval_array_opt->size_of())) {\n"
+      "        if (0 != emb_val->embval_array_reg) {\n"
+      "          (*emb_val->embval_array_reg)[emb_val->embval_index].XER_encode(\n"
+      "            UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
+      "        }\n"
+      "        else {\n"
+      "          (*emb_val->embval_array_opt)[emb_val->embval_index].XER_encode(\n"
+      "            UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
+      "        }\n"
       "        ++emb_val->embval_index;\n"
-      "      }\n" - temporarily removed in RT1 */
-      "      ec_1.set_msg(\"%%d: \", i);\n"
+      "      }\n"
+      "      ec_1.set_msg(\"%d: \", i);\n"
       "      if (e_xer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');\n"
-      "      value_elements[i].XER_encode(%s_xer_, p_buf, p_flavor, p_indent+own_tag, emb_val);\n"
+      "      value_elements[i].XER_encode(*p_td.oftype_descr, p_buf, p_flavor, p_indent+own_tag, emb_val);\n"
       "    }\n"
-      "    if (indenting && !is_exerlist(p_flavor)) {\n",
-      sdef->oftypedescrname
+      "    if (indenting && !is_exerlist(p_flavor)) {\n"
     );
     if (sdef->xmlValueList) {
       src=mputstr(src, "      if (!e_xer) p_buf.put_c('\\n');\n"); /* !e_xer or GDMO */
@@ -2722,10 +2749,11 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
     src=mputstr(src,
       "      do_indent(p_buf, p_indent);\n"
       "    }\n");
-    if (sdef->xerAttribute) {
-      src=mputstr(src,
-        "    if (e_xer) p_buf.put_c('\\'');\n"
-        "    else\n");
+    if (force_gen_seof || sdef->xerAttribute) {
+      src=mputprintf(src,
+        "    if (e_xer%s) p_buf.put_c('\\'');\n"
+        "    else\n"
+        , force_gen_seof ? " && (p_td.xer_bits & XER_ATTRIBUTE)" : "");
     }
     src=mputstr(src,
       "    if (own_tag){\n"
@@ -2787,7 +2815,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       , name
       );
 
-    src = mputprintf(src,
+    src = mputstr(src,
       "  if (e_xer && (p_td.xer_bits & XER_LIST)) {\n" /* LIST decoding*/
       "    char *x_val = (char*)p_reader.NewValue();\n" /* we own it */
       "    size_t x_pos = 0;\n"
@@ -2801,13 +2829,13 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "      x_pos += strlen(str) + 1;\n"
       "      TTCN_Buffer buf_2;\n"
       "      buf_2.put_c('<');\n"
-      "      write_ns_prefix(%s_xer_, buf_2);\n"
-      "      const char * const exer_name = %s_xer_.names[1];\n"
-      "      boolean i_can_has_ns = %s_xer_.my_module != 0 && %s_xer_.ns_index != -1;\n"
+      "      write_ns_prefix(*p_td.oftype_descr, buf_2);\n"
+      "      const char * const exer_name = p_td.oftype_descr->names[1];\n"
+      "      boolean i_can_has_ns = p_td.oftype_descr->my_module != 0 && p_td.oftype_descr->ns_index != -1;\n"
       /* If it has a namespace, chop off the '>' from the end */
-      "      buf_2.put_s((size_t)%s_xer_.namelens[1]-1-i_can_has_ns, (cbyte*)exer_name);\n"
+      "      buf_2.put_s((size_t)p_td.oftype_descr->namelens[1]-1-i_can_has_ns, (cbyte*)exer_name);\n"
       "      if (i_can_has_ns) {\n"
-      "        const namespace_t * const pns = %s_xer_.my_module->get_ns(%s_xer_.ns_index);\n"
+      "        const namespace_t * const pns = p_td.oftype_descr->my_module->get_ns(p_td.oftype_descr->ns_index);\n"
       "        buf_2.put_s(7 - (*pns->px == 0), (cbyte*)\" xmlns:\");\n"
       "        buf_2.put_s(strlen(pns->px), (cbyte*)pns->px);\n"
       "        buf_2.put_s(2, (cbyte*)\"='\");\n"
@@ -2818,14 +2846,14 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "      buf_2.put_s(strlen(str), (cbyte*)str);\n"
       "      buf_2.put_c('<');\n"
       "      buf_2.put_c('/');\n"
-      "      write_ns_prefix(%s_xer_, buf_2);\n"
-      "      buf_2.put_s((size_t)%s_xer_.namelens[1], (cbyte*)exer_name);\n"
+      "      write_ns_prefix(*p_td.oftype_descr, buf_2);\n"
+      "      buf_2.put_s((size_t)p_td.oftype_descr->namelens[1], (cbyte*)exer_name);\n"
       "      XmlReaderWrap reader_2(buf_2);\n"
       "      rd_ok = reader_2.Read();\n" /* Move to the start element. */
       /* Don't move to the #text, that's the callee's responsibility. */
       /* The call to the non-const operator[] creates a new element object,
        * then we call its XER_decode with the temporary XML reader. */
-      "      (*this)[n_elements].XER_decode(%s_xer_, reader_2, p_flavor, 0);\n"
+      "      (*this)[n_elements].XER_decode(*p_td.oftype_descr, reader_2, p_flavor, 0);\n"
       "      if (p_flavor & EXIT_ON_ERROR && !(*this)[n_elements - 1].is_bound()) {\n"
       "        if (1 == n_elements) {\n"
       // Failed to decode even the first element
@@ -2847,11 +2875,6 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "      p_reader.Read();\n" /* past it */
       "    }\n"
       "  }\n"
-      , sdef->oftypedescrname, sdef->oftypedescrname
-      , sdef->oftypedescrname, sdef->oftypedescrname
-      , sdef->oftypedescrname, sdef->oftypedescrname
-      , sdef->oftypedescrname, sdef->oftypedescrname
-      , sdef->oftypedescrname, sdef->oftypedescrname
     );
 
     src = mputprintf(src,
@@ -2881,17 +2904,17 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
         "            if (p_reader.NodeType() != XML_READER_TYPE_ELEMENT) rd_ok = p_reader.Read();\n"
         "          } else");
     }
-    src = mputprintf(src,
+    src = mputstr(src,
       "          {\n"
       /* An untagged record-of ends if it encounters an element with a name
        * that doesn't match its component */
       "            if (!own_tag && !can_start((const char*)p_reader.LocalName(), "
-      "(const char*)p_reader.NamespaceUri(), %s_xer_, p_flavor)) {\n"
+      "(const char*)p_reader.NamespaceUri(), p_td, p_flavor)) {\n"
       "              for (; rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
       "              break;\n"
       "            }\n"
       /* The call to the non-const operator[] creates the element */
-      "            operator [](n_elements).XER_decode(%s_xer_, p_reader, p_flavor, emb_val);\n"
+      "            operator [](n_elements).XER_decode(*p_td.oftype_descr, p_reader, p_flavor, emb_val);\n"
       "            if (0 != emb_val && !own_tag && n_elements > 1) {\n"
       "              ++emb_val->embval_index;\n"
       "            }\n"
@@ -2905,11 +2928,16 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "          }\n"
       "          break;\n"
       "        }\n"
-      /*"        else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && n_elements > 0) {\n"
+      "        else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && n_elements > 0) {\n"
       "          UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
-      "          emb_val->embval_array->set_embedded_value(emb_val->embval_index, emb_ustr);\n"
+      "          if (0 != emb_val->embval_array_reg) {\n"
+      "            (*emb_val->embval_array_reg)[emb_val->embval_index] = emb_ustr;\n"
+      "          }\n"
+      "          else {\n"
+      "            (*emb_val->embval_array_opt)[emb_val->embval_index] = emb_ustr;\n"
+      "          }\n"
       "          rd_ok = p_reader.Read();\n"
-      "        }\n" - temporarily removed in RT1 */
+      "        }\n"
       "        else {\n"
       "          rd_ok = p_reader.Read();\n"
       "        }\n"
@@ -2918,13 +2946,12 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "  }\n" /* if not LIST */
       "  return 1;\n"
       "}\n\n"
-      , sdef->oftypedescrname, sdef->oftypedescrname
     );
   }
   if (json_needed) {
     // JSON encode, RT1, mem. alloc. optimised
     src = mputprintf(src,
-      "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
+      "int %s::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const\n"
       "{\n"
       "  if (!is_bound()) {\n"
       "    TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
@@ -2933,18 +2960,18 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "  }\n\n"
       "  int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);\n"
       "  for(int i = 0; i < n_elements; ++i) {\n"
-      "    int ret_val = value_elements[i].JSON_encode(%s_descr_, p_tok);\n"
+      "    int ret_val = value_elements[i].JSON_encode(*p_td.oftype_descr, p_tok);\n"
       "    if (0 > ret_val) break;\n"
       "    enc_len += ret_val;\n"
       "  }\n"
       "  enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);\n"
       "  return enc_len;\n"
       "}\n\n"
-      , name, dispname, sdef->oftypedescrname);
+      , name, dispname);
     
     // JSON decode, RT1, mem. alloc. optimised
     src = mputprintf(src,
-      "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
+      "int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)\n"
       "{\n"
       "  json_token_t token = JSON_TOKEN_NONE;\n"
       "  int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
@@ -2959,7 +2986,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "  while (true) {\n"
       "    size_t buf_pos = p_tok.get_buf_pos();\n"
       "    %s val;\n"
-      "    int ret_val = val.JSON_decode(%s_descr_, p_tok, p_silent);\n"
+      "    int ret_val = val.JSON_decode(*p_td.oftype_descr, p_tok, p_silent);\n"
       "    if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n"
       "      p_tok.set_buf_pos(buf_pos);\n"
       "      break;\n"
@@ -2984,7 +3011,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       "  }\n\n"
       "  return dec_len;\n"
       "}\n\n"
-      , name, type, sdef->oftypedescrname);
+      , name, type);
   }
   /* end of class */
   def = mputstr(def, "};\n\n");
@@ -3024,8 +3051,8 @@ void defRecordOfClass2(const struct_of_def *sdef, output_struct *output)
   char *def = NULL, *src = NULL;
   const char *name = sdef->name;
   const char *type = sdef->type;
-  boolean raw_needed = sdef->hasRaw && enable_raw();
-  boolean xer_needed = sdef->hasXer && enable_xer();
+  boolean raw_needed = force_gen_seof || (sdef->hasRaw && enable_raw());
+  boolean xer_needed = force_gen_seof || (sdef->hasXer && enable_xer());
 
   /* Class definition */
   def = mputprintf(def,
@@ -3164,12 +3191,10 @@ void defRecordOfClass2(const struct_of_def *sdef, output_struct *output)
   src = mputprintf(src,
     "Base_Type* %s::create_elem() const { return new %s; }\n"
     "const Base_Type* %s::get_unbound_elem() const { return &UNBOUND_ELEM; }\n"
-    "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n"
-    "const TTCN_Typedescriptor_t* %s::get_elem_descr() const { return &%s_descr_; }\n\n",
+    "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n",
     name, type,
     name,
-    name, name,
-    name, sdef->oftypedescrname);
+    name, name);
 
   /* helper functions called by enc/dec members of the ancestor class */
   if (raw_needed) {
@@ -3194,13 +3219,20 @@ void defRecordOfClass2(const struct_of_def *sdef, output_struct *output)
       "boolean %s::can_start(const char *name, const char *uri, "
       "XERdescriptor_t const& xd, unsigned int flavor) {\n"
       "  boolean e_xer = is_exer(flavor);\n"
+      /* if EXER and UNTAGGED, it can begin with the tag of the element,
+       * otherwise it must be the tag of the type itself,
+       * specified in the supplied parameter.
+       * If flavor contains UNTAGGED, that's a signal to go directly
+       * to the embedded type. */
+      "  if (!e_xer || !((xd.xer_bits|flavor) & UNTAGGED)) return "
+      "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
       /* a record-of with ANY-ELEMENT can start with any tag
        * :-( with some exceptions )-: */
-      "  if (e_xer && (xd.xer_bits & ANY_ELEMENT)) "
+      "  if (e_xer && (xd.oftype_descr->xer_bits & ANY_ELEMENT)) "
       , name, name
       );
 
-    if (sdef->nFollowers) {
+    if (!force_gen_seof && sdef->nFollowers) {
       size_t f;
       src = mputstr(src, "{\n");
       for (f = 0; f < sdef->nFollowers; ++f) {
@@ -3218,15 +3250,8 @@ void defRecordOfClass2(const struct_of_def *sdef, output_struct *output)
       src = mputstr(src, "return TRUE;\n");
     }
     src = mputprintf(src,
-      /* if EXER and UNTAGGED, it can begin with the tag of the element,
-       * otherwise it must be the tag of the type itself,
-       * specified in the supplied parameter.
-       * If flavor contains UNTAGGED, that's a signal to go directly
-       * to the embedded type. */
-      "  if (!e_xer || !((xd.xer_bits|flavor) & UNTAGGED)) return "
-      "check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
-      "  else return %s::can_start(name, uri, %s_xer_, flavor | XER_RECOF);\n"
-      "}\n\n", sdef->type, sdef->oftypedescrname);
+      "  return %s::can_start(name, uri, *xd.oftype_descr, flavor | XER_RECOF);\n"
+      "}\n\n", sdef->type);
     def = mputprintf(def, "boolean isXmlValueList() const { return %s; }\n\n",
       sdef->xmlValueList ? "TRUE" : "FALSE");
   }
index 29b0232209e81b958d1b3af0aa73370d5751a592..60f81ae5b29a34321fa734ef800d5d874d17575f 100644 (file)
@@ -1930,6 +1930,9 @@ void SubType::chk_this_template(Template *templ)
   case Template::VALUE_RANGE:
     /* Should be canonical before */
     break;
+  case Template::ALL_FROM:
+  case Template::VALUE_LIST_ALL_FROM:
+    break;
   case Template::SUPERSET_MATCH:
   case Template::SUBSET_MATCH:
     if (subtype!=ST_SETOF){
index 7b0a70c772029a794009e687918ee49f395483de..8449e696bcd62947a0bdd1b3dac1a9ae6a5a4895 100644 (file)
@@ -205,7 +205,7 @@ namespace Ttcn {
     Node::set_fullname(p_fullname);
     for (size_t i = 0; i < refs.size(); i++)
       refs[i]->set_fullname(p_fullname +
-       ".<sub_reference" + Int2string(i + 1) + ">");
+        ".<sub_reference" + Int2string(i + 1) + ">");
   }
 
   void FieldOrArrayRefs::set_my_scope(Scope *p_scope)
@@ -218,9 +218,9 @@ namespace Ttcn {
     for (size_t i = 0; i < refs.size(); i++) {
       FieldOrArrayRef *ref = refs[i];
       if (ref->get_type() == FieldOrArrayRef::ARRAY_REF) {
-       Value *v = ref->get_val();
-       v->set_lowerid_to_ref();
-       if (v->is_unfoldable()) return true;
+        Value *v = ref->get_val();
+        v->set_lowerid_to_ref();
+        if (v->is_unfoldable()) return true;
       }
     }
     return false;
@@ -312,38 +312,38 @@ namespace Ttcn {
         expr->expr = mputprintf(expr->expr, ".%s%s()",
           ((type!=0 && type->get_typetype()==Type::T_ANYTYPE) ? "AT_" : ""),
           id.get_name().c_str());
-       if (type) {
-         CompField *cf = type->get_comp_byName(id);
-         // If the field is optional, the return type of the accessor is an
-         // OPTIONAL<T>. Write a call to OPTIONAL<T>::operator(),
-         // which "reaches into" the OPTIONAL to get the contained type T.
-         // Don't do this at the end of the reference chain.
-         // Accessor methods for a foo_template return a bar_template
-         // and OPTIONAL<> is not involved, hence no "()".
-         if (!is_template && i < n_refs - 1 && cf->get_is_optional())
-           expr->expr = mputstr(expr->expr, "()");
+        if (type) {
+          CompField *cf = type->get_comp_byName(id);
+          // If the field is optional, the return type of the accessor is an
+          // OPTIONAL<T>. Write a call to OPTIONAL<T>::operator(),
+          // which "reaches into" the OPTIONAL to get the contained type T.
+          // Don't do this at the end of the reference chain.
+          // Accessor methods for a foo_template return a bar_template
+          // and OPTIONAL<> is not involved, hence no "()".
+          if (!is_template && i < n_refs - 1 && cf->get_is_optional())
+            expr->expr = mputstr(expr->expr, "()");
           // Follow the field type.
-         type = cf->get_type();
-       }
+          type = cf->get_type();
+        }
       } else {
         // Generate code for array reference.
         expr->expr = mputc(expr->expr, '[');
-       ref->get_val()->generate_code_expr(expr);
+        ref->get_val()->generate_code_expr(expr);
         expr->expr = mputc(expr->expr, ']');
-       if (type) {
+        if (type) {
           // Follow the embedded type.
-         switch (type->get_typetype()) {
-         case Type::T_SEQOF:
-         case Type::T_SETOF:
-         case Type::T_ARRAY:
-           type = type->get_ofType();
-           break;
-         default:
-           // The index points to a string element.
-           // There are no further sub-references.
-           type = 0;
-         } // switch
-       } // if (type)
+          switch (type->get_typetype()) {
+          case Type::T_SEQOF:
+          case Type::T_SETOF:
+          case Type::T_ARRAY:
+            type = type->get_ofType();
+            break;
+          default:
+            // The index points to a string element.
+            // There are no further sub-references.
+            type = 0;
+          } // switch
+        } // if (type)
       } // if (ref->get_type)
     } // next reference
   }
@@ -451,10 +451,10 @@ namespace Ttcn {
   }
 
   /* Called by:
-   *   Common::PortTypeBody::PortTypeBody
-   *   Common::Type::Type
-   *   Common::TypeMappingTarget::TypeMappingTarget
-   *   Common::PatternString::ps_elem_t::chk_ref */
+   *         Common::PortTypeBody::PortTypeBody
+   *         Common::Type::Type
+   *         Common::TypeMappingTarget::TypeMappingTarget
+   *         Common::PatternString::ps_elem_t::chk_ref */
   Reference *Reference::clone() const
   {
     return new Reference(*this);
@@ -465,8 +465,8 @@ namespace Ttcn {
     string ret_val;
     if (id) {
       if (modid) {
-       ret_val += modid->get_dispname();
-       ret_val += '.';
+        ret_val += modid->get_dispname();
+        ret_val += '.';
       }
       ret_val += id->get_dispname();
       subrefs.append_stringRepr(ret_val);
@@ -498,7 +498,7 @@ namespace Ttcn {
           parlist->set_my_scope(my_scope);
         } else {
           error("Reference to parameterized definition `%s' without "
-           "actual parameter list", ass->get_id().get_dispname().c_str());
+            "actual parameter list", ass->get_id().get_dispname().c_str());
         }
       }
     }
@@ -531,7 +531,7 @@ namespace Ttcn {
       break;
     default:
       error("Reference to a variable or value parameter was "
-       "expected instead of %s", t_ass->get_description().c_str());
+        "expected instead of %s", t_ass->get_description().c_str());
       return 0;
     }
     FieldOrArrayRefs *t_subrefs = get_subrefs();
@@ -539,7 +539,7 @@ namespace Ttcn {
       Type::EXPECTED_DYNAMIC_VALUE);
     if (ret_val && t_subrefs && t_subrefs->refers_to_string_element()) {
       error("Reference to a string element of type `%s' cannot be used in "
-       "this context", ret_val->get_typename().c_str());
+        "this context", ret_val->get_typename().c_str());
     }
     return ret_val;
   }
@@ -550,19 +550,19 @@ namespace Ttcn {
     if (ass) {
       if (ass->get_asstype() == Common::Assignment::A_TYPE) {
         Type *t = ass->get_Type()->get_type_refd_last();
-       switch (t->get_typetype()) {
-       case Type::T_ERROR:
-         // remain silent
-         break;
-       case Type::T_COMPONENT:
-         return t;
-       default:
-         error("Reference `%s' does not refer to a component type",
-           get_dispname().c_str());
-       }
+        switch (t->get_typetype()) {
+        case Type::T_ERROR:
+          // remain silent
+          break;
+        case Type::T_COMPONENT:
+          return t;
+        default:
+          error("Reference `%s' does not refer to a component type",
+            get_dispname().c_str());
+        }
       } else {
-       error("Reference `%s' does not refer to a type",
-         get_dispname().c_str());
+        error("Reference `%s' does not refer to a type",
+          get_dispname().c_str());
       }
     }
     return 0;
@@ -720,21 +720,21 @@ namespace Ttcn {
       FieldOrArrayRef *second_ref = subrefs.get_ref(1);
       if (second_ref->get_type() == FieldOrArrayRef::FIELD_REF) {
         // the reference begins with <id>.<id> (most complicated case)
-       // there are 3 possible situations:
-       // 1. first_id points to a local definition (this has the priority)
-       //      modid: 0, id: first_id
-       // 2. first_id points to an imported module (trivial case)
-       //      modid: first_id, id: second_id
-       // 3. none of the above (first_id might be an imported symbol)
-       //      modid: 0, id: first_id
-       // Note: Rule 1 has the priority because it can be overridden using
-       // the notation <id>.objid { ... }.<id> (modid and id are set in the
-       // constructor), but there is no work-around in the reverse way.
-       if (!my_scope->has_ass_withId(*first_id)
-           && my_scope->is_valid_moduleid(*first_id)) {
-         // rule 1 is not fulfilled, but rule 2 is fulfilled
-         second_id = second_ref->get_id();
-       }
+        // there are 3 possible situations:
+        // 1. first_id points to a local definition (this has the priority)
+        //      modid: 0, id: first_id
+        // 2. first_id points to an imported module (trivial case)
+        //      modid: first_id, id: second_id
+        // 3. none of the above (first_id might be an imported symbol)
+        //      modid: 0, id: first_id
+        // Note: Rule 1 has the priority because it can be overridden using
+        // the notation <id>.objid { ... }.<id> (modid and id are set in the
+        // constructor), but there is no work-around in the reverse way.
+        if (!my_scope->has_ass_withId(*first_id)
+            && my_scope->is_valid_moduleid(*first_id)) {
+          // rule 1 is not fulfilled, but rule 2 is fulfilled
+          second_id = second_ref->get_id();
+        }
       } // else: the reference begins with <id>[<arrayref>] -> there is no modid
     } // else: the reference consists of a single <id>  -> there is no modid
     if (second_id) {
@@ -804,14 +804,14 @@ namespace Ttcn {
     if (params_checked) {
       // used after semantic analysis
       for (size_t i = 0; i < parlist.get_nof_pars(); i++) {
-       if (i > 0) ret_val += ", ";
-       parlist.get_par(i)->append_stringRepr(ret_val);
+        if (i > 0) ret_val += ", ";
+        parlist.get_par(i)->append_stringRepr(ret_val);
       }
     } else {
       // used before semantic analysis
       for (size_t i = 0; i < params->get_nof_tis(); i++) {
-       if (i > 0) ret_val += ", ";
-       params->get_ti_byIndex(i)->append_stringRepr(ret_val);
+        if (i > 0) ret_val += ", ";
+        params->get_ti_byIndex(i)->append_stringRepr(ret_val);
       }
     }
     ret_val += ')';
@@ -826,17 +826,17 @@ namespace Ttcn {
       params_checked = true;
       FormalParList *fplist = ass->get_FormalParList();
       if (fplist) {
-       Error_Context cntxt(params, "In actual parameter list of %s",
-         ass->get_description().c_str());
-       is_erroneous = fplist->fold_named_and_chk(params, &parlist);
-       parlist.set_fullname(get_fullname());
-       parlist.set_my_scope(my_scope);
-       // the parsed parameter list is no longer needed
-       delete params;
-       params = 0;
+        Error_Context cntxt(params, "In actual parameter list of %s",
+          ass->get_description().c_str());
+        is_erroneous = fplist->fold_named_and_chk(params, &parlist);
+        parlist.set_fullname(get_fullname());
+        parlist.set_my_scope(my_scope);
+        // the parsed parameter list is no longer needed
+        delete params;
+        params = 0;
       } else {
         params->error("The referenced %s cannot have actual parameters",
-         ass->get_description().c_str());
+          ass->get_description().c_str());
       }
     }
     return ass;
@@ -864,7 +864,7 @@ namespace Ttcn {
     if (!t_ass) return false;
     if (t_ass->get_asstype() != Common::Assignment::A_ALTSTEP) {
       error("Reference to an altstep was expected in the argument instead of "
-       "%s", t_ass->get_description().c_str());
+        "%s", t_ass->get_description().c_str());
       return false;
     }
     my_scope->chk_runs_on_clause(t_ass, *this, "activate");
@@ -1048,11 +1048,11 @@ namespace Ttcn {
       const Identifier& id = comp_def->get_id();
       if (parent_scope->has_ass_withId(id)) {
         comp_def->warning("Imported component element definition `%s' hides a "
-         "definition at module scope", comp_def->get_fullname().c_str());
-       Reference ref(0, id.clone());
-       Common::Assignment *hidden_ass = parent_scope->get_ass_bySRef(&ref);
-       hidden_ass->warning("Hidden definition `%s' is here",
-         hidden_ass->get_fullname().c_str());
+          "definition at module scope", comp_def->get_fullname().c_str());
+        Reference ref(0, id.clone());
+        Common::Assignment *hidden_ass = parent_scope->get_ass_bySRef(&ref);
+        hidden_ass->warning("Hidden definition `%s' is here",
+          hidden_ass->get_fullname().c_str());
       }
 
     }
@@ -1424,12 +1424,12 @@ namespace Ttcn {
       duplicate_underscores ? module_name : modid->get_ttcnname().c_str());
 
     target->functions.pre_init = mputprintf(target->functions.pre_init,
-       "%s%s.pre_init_module();\n", module_name,
+        "%s%s.pre_init_module();\n", module_name,
   "::module_object");
 
     if (mod->get_moduletype() == Common::Module::MOD_TTCN) {
       target->functions.post_init = mputprintf(target->functions.post_init,
-         "%s%s.post_init_module();\n", module_name,
+          "%s%s.post_init_module();\n", module_name,
     "::module_object");
 
     }
@@ -1441,8 +1441,8 @@ namespace Ttcn {
     if (w_attrib_path) {
       MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
       if (attrib) {
-       DEBUG(level + 1, "Attributes:");
-       attrib->dump(level + 2);
+        DEBUG(level + 1, "Attributes:");
+        attrib->dump(level + 2);
       }
     }
   }
@@ -1614,19 +1614,19 @@ namespace Ttcn {
       // imported module that imports m
       bool covered = false;
       for (size_t j = 0; j < impmods_v.size(); j++) {
-       // skip over the same import definition
-       if (j == i) continue;
-       ImpMod *im2 = impmods_v[j];
-       Common::Module *m2 = im2->get_mod();
-       // a module that is equivalent to the current module due to
-       // circular imports cannot be used to cover anything
-       if (m2->is_visible(my_mod)) continue;
-       if (m2->is_visible(m) && !m->is_visible(m2)) {
-         // m2 covers m (i.e. m is visible from m2)
-         // and they are not in the same import loop
-         covered = true;
-         break;
-       }
+        // skip over the same import definition
+        if (j == i) continue;
+        ImpMod *im2 = impmods_v[j];
+        Common::Module *m2 = im2->get_mod();
+        // a module that is equivalent to the current module due to
+        // circular imports cannot be used to cover anything
+        if (m2->is_visible(my_mod)) continue;
+        if (m2->is_visible(m) && !m->is_visible(m2)) {
+          // m2 covers m (i.e. m is visible from m2)
+          // and they are not in the same import loop
+          covered = true;
+          break;
+        }
       }
       // do not generate the #include if a covering module is found
       if (!covered) im->generate_code(target);
@@ -1729,11 +1729,11 @@ namespace Ttcn {
         ass->error("Duplicate definition with name `%s'", dispname_str);
         ass_m[name]->note("Previous definition of `%s' is here", dispname_str);
       } else {
-       ass_m.add(name, ass);
-       if (parent_scope->is_valid_moduleid(id)) {
-         ass->warning("Definition with name `%s' hides a module identifier",
-           id.get_dispname().c_str());
-       }
+        ass_m.add(name, ass);
+        if (parent_scope->is_valid_moduleid(id)) {
+          ass->warning("Definition with name `%s' hides a module identifier",
+            id.get_dispname().c_str());
+        }
       }
     }
     checked = true;
@@ -1756,26 +1756,26 @@ namespace Ttcn {
       const Identifier& id = def->get_id();
       const string& name = id.get_name();
       if (ass_m.has_key(name)) {
-       const char *dispname_str = id.get_dispname().c_str();
-       def->error("Duplicate definition with name `%s'", dispname_str);
-       ass_m[name]->note("Previous definition of `%s' is here", dispname_str);
+        const char *dispname_str = id.get_dispname().c_str();
+        def->error("Duplicate definition with name `%s'", dispname_str);
+        ass_m[name]->note("Previous definition of `%s' is here", dispname_str);
       } else {
-       ass_m.add(name, def);
-       if (parent_scope) {
-         if (parent_scope->has_ass_withId(id)) {
-           const char *dispname_str = id.get_dispname().c_str();
-           def->error("Definition with identifier `%s' is not unique in the "
-             "scope hierarchy", dispname_str);
-           Reference ref(0, id.clone());
-           Common::Assignment *ass = parent_scope->get_ass_bySRef(&ref);
-           if (!ass) FATAL_ERROR("OtherDefinitions::chk_for()");
-           ass->note("Previous definition with identifier `%s' in higher "
-             "scope unit is here", dispname_str);
-         } else if (parent_scope->is_valid_moduleid(id)) {
-           def->warning("Definition with name `%s' hides a module identifier",
-             id.get_dispname().c_str());
-         }
-       }
+        ass_m.add(name, def);
+        if (parent_scope) {
+          if (parent_scope->has_ass_withId(id)) {
+            const char *dispname_str = id.get_dispname().c_str();
+            def->error("Definition with identifier `%s' is not unique in the "
+              "scope hierarchy", dispname_str);
+            Reference ref(0, id.clone());
+            Common::Assignment *ass = parent_scope->get_ass_bySRef(&ref);
+            if (!ass) FATAL_ERROR("OtherDefinitions::chk_for()");
+            ass->note("Previous definition with identifier `%s' in higher "
+              "scope unit is here", dispname_str);
+          } else if (parent_scope->is_valid_moduleid(id)) {
+            def->warning("Definition with name `%s' hides a module identifier",
+              id.get_dispname().c_str());
+          }
+        }
       }
       def->chk();
     }
@@ -1914,15 +1914,15 @@ namespace Ttcn {
       const string& group_name = group_id.get_name();
       if (ass_m.has_key(group_name)) {
         group->error("Group name `%s' clashes with a definition",
-         group_id.get_dispname().c_str());
+          group_id.get_dispname().c_str());
         ass_m[group_name]->note("Definition of `%s' is here",
-         group_id.get_dispname().c_str());
+          group_id.get_dispname().c_str());
       }
       if (group_m.has_key(group_name)) {
         group->error("Duplicate group with name `%s'",
-         group_id.get_dispname().c_str());
+          group_id.get_dispname().c_str());
         group_m[group_name]->note("Group `%s' is already defined here",
-         group_id.get_dispname().c_str());
+          group_id.get_dispname().c_str());
       } else group_m.add(group_name, group);
     }
     checked = true;
@@ -1969,8 +1969,8 @@ namespace Ttcn {
     if (w_attrib_path) {
       MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
       if (attrib) {
-       DEBUG(level + 1, "Group Attributes:");
-       attrib->dump(level + 2);
+        DEBUG(level + 1, "Group Attributes:");
+        attrib->dump(level + 2);
       }
     }
   }
@@ -2063,8 +2063,8 @@ namespace Ttcn {
     if (w_attrib_path) {
       MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
       if (attrib) {
-       DEBUG(level + 1, "Attributes:");
-       attrib->dump(level + 2);
+        DEBUG(level + 1, "Attributes:");
+        attrib->dump(level + 2);
       }
     }
   }
@@ -2583,16 +2583,16 @@ namespace Ttcn {
       if(ass_m.has_key(group_name))
       {
         group->error("Group name `%s' clashes with a definition",
-         group_id.get_dispname().c_str());
+          group_id.get_dispname().c_str());
         ass_m[group_name]->note("Definition of `%s' is here",
-         group_id.get_dispname().c_str());
+          group_id.get_dispname().c_str());
       }
       if(group_m.has_key(group_name))
       {
         group->error("Duplicate group with name `%s'",
-         group_id.get_dispname().c_str());
+          group_id.get_dispname().c_str());
         group_m[group_name]->note("Group `%s' is already defined here",
-         group_id.get_dispname().c_str());
+          group_id.get_dispname().c_str());
       }else{
         group_m.add(group_name,group_v[i]);
       }
@@ -2645,8 +2645,8 @@ namespace Ttcn {
     if (w_attrib_path) {
       MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
       if (attrib) {
-       DEBUG(level, "Module Attributes:");
-       attrib->dump(level + 1);
+        DEBUG(level, "Module Attributes:");
+        attrib->dump(level + 1);
       }
     }
   }
@@ -2920,8 +2920,8 @@ namespace Ttcn {
     if (w_attrib_path) {
       MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
       if (attrib) {
-       DEBUG(level + 1, "Definition Attributes:");
-       attrib->dump(level + 2);
+        DEBUG(level + 1, "Definition Attributes:");
+        attrib->dump(level + 2);
       }
     }
     if (erroneous_attrs) erroneous_attrs->dump(level+1);
@@ -3260,7 +3260,7 @@ namespace Ttcn {
     if (p_def->get_asstype() != A_CONST) {
       const char *dispname_str = id->get_dispname().c_str();
       error("Local definition `%s' is a constant, but the definition "
-       "inherited from component type `%s' is a %s", dispname_str,
+        "inherited from component type `%s' is a %s", dispname_str,
         p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
       p_def->note("The inherited definition of `%s' is here", dispname_str);
       return false;
@@ -3270,16 +3270,16 @@ namespace Ttcn {
     if (!type->is_identical(p_def_const->type)) {
       const char *dispname_str = id->get_dispname().c_str();
       type->error("Local constant `%s' has type `%s', but the constant "
-       "inherited from component type `%s' has type `%s'", dispname_str,
-       type->get_typename().c_str(),
+        "inherited from component type `%s' has type `%s'", dispname_str,
+        type->get_typename().c_str(),
         p_def_const->get_my_scope()->get_fullname().c_str(),
-       p_def_const->type->get_typename().c_str());
+        p_def_const->type->get_typename().c_str());
       p_def_const->note("The inherited constant `%s' is here", dispname_str);
       return false;
     } else if (!(*value == *p_def_const->value)) {
       const char *dispname_str = id->get_dispname().c_str();
       value->error("Local constant `%s' and the constant inherited from "
-       "component type `%s' have different values", dispname_str,
+        "component type `%s' have different values", dispname_str,
         p_def_const->get_my_scope()->get_fullname().c_str());
       p_def_const->note("The inherited constant `%s' is here", dispname_str);
       return false;
@@ -3515,8 +3515,6 @@ namespace Ttcn {
     map<Type*,void> type_chain;
     map<Type::typetype_t, void> not_allowed;
     not_allowed.add(Type::T_PORT, 0);
-    not_allowed.add(Type::T_COMPONENT, 0);
-    not_allowed.add(Type::T_DEFAULT, 0);
     Type *t = type->get_type_refd_last();
     // if the type is valid the original will be returned
     Type::typetype_t tt = t->search_for_not_allowed_type(type_chain, not_allowed);
@@ -3531,14 +3529,6 @@ namespace Ttcn {
       error("Type of module parameter cannot be signature `%s'",
         t->get_fullname().c_str());
       break;
-    case Type::T_COMPONENT:
-        error("Type of module parameter cannot be or embed component `%s'",
-          t->get_fullname().c_str());
-        break;
-    case Type::T_DEFAULT:
-        error("Type of module parameter cannot be or embed default `%s'",
-          t->get_fullname().c_str());
-        break;
     case Type::T_FUNCTION:
     case Type::T_ALTSTEP:
     case Type::T_TESTCASE:
@@ -3599,11 +3589,11 @@ namespace Ttcn {
     if (target->functions.log_param) {
       // this is not the first modulepar
       target->functions.log_param = mputprintf(target->functions.log_param,
-       "TTCN_Logger::log_event_str(\", %s := \");\n", dispname);
+        "TTCN_Logger::log_event_str(\", %s := \");\n", dispname);
     } else {
       // this is the first modulepar
       target->functions.log_param = mputprintf(target->functions.log_param,
-       "TTCN_Logger::log_event_str(\"%s := \");\n", dispname);
+        "TTCN_Logger::log_event_str(\"%s := \");\n", dispname);
     }
     target->functions.log_param = mputprintf(target->functions.log_param,
       "%s.log();\n", name);
@@ -3767,11 +3757,11 @@ namespace Ttcn {
     if (target->functions.log_param) {
       // this is not the first modulepar
       target->functions.log_param = mputprintf(target->functions.log_param,
-       "TTCN_Logger::log_event_str(\", %s := \");\n", dispname);
+        "TTCN_Logger::log_event_str(\", %s := \");\n", dispname);
     } else {
       // this is the first modulepar
       target->functions.log_param = mputprintf(target->functions.log_param,
-       "TTCN_Logger::log_event_str(\"%s := \");\n", dispname);
+        "TTCN_Logger::log_event_str(\"%s := \");\n", dispname);
     }
     target->functions.log_param = mputprintf(target->functions.log_param,
       "%s.log();\n", name);
@@ -4148,8 +4138,8 @@ namespace Ttcn {
       {
         if (iter->recurs_deriv_checked) break;
         else if (refch.add(iter->get_fullname()))
-         iter->recurs_deriv_checked = true;
-       else break;
+          iter->recurs_deriv_checked = true;
+        else break;
       }
     }
     recurs_deriv_checked = true;
@@ -4170,8 +4160,8 @@ namespace Ttcn {
       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);
+          "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",
@@ -4179,24 +4169,24 @@ namespace Ttcn {
       if (base_template) {
         // modified template
         function_body = mputprintf(function_body, "%s ret_val(%s",
-         type_genname_str,
-         base_template->get_genname_from_scope(my_scope).c_str());
-       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();
-         for (size_t i = 0; i < nof_base_pars; i++) {
-           if (i > 0) function_body = mputstr(function_body, ", ");
-           function_body = mputstr(function_body,
-             fp_list->get_fp_byIndex(i)->get_id().get_name().c_str());
-         }
-         function_body = mputc(function_body, ')');
-       }
-       function_body = mputstr(function_body, ");\n");
+          type_genname_str,
+          base_template->get_genname_from_scope(my_scope).c_str());
+        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();
+          for (size_t i = 0; i < nof_base_pars; i++) {
+            if (i > 0) function_body = mputstr(function_body, ", ");
+            function_body = mputstr(function_body,
+              fp_list->get_fp_byIndex(i)->get_id().get_name().c_str());
+          }
+          function_body = mputc(function_body, ')');
+        }
+        function_body = mputstr(function_body, ");\n");
       } else {
         // simple template
         function_body = mputprintf(function_body, "%s ret_val;\n",
-         type_genname_str);
+          type_genname_str);
       }
       if (erroneous_attrs && erroneous_attrs->get_err_descr()) {
         function_body = erroneous_attrs->get_err_descr()->
@@ -4347,19 +4337,19 @@ namespace Ttcn {
     if (fp_list) {
       const char *dispname_str = id->get_dispname().c_str();
       NOTSUPP("Code generation for parameterized local template `%s'",
-       dispname_str);
+        dispname_str);
       def = mputprintf(def, "/* NOT SUPPORTED: template %s */\n", dispname_str);
       init = mputprintf(init, "/* NOT SUPPORTED: template %s */\n",
-       dispname_str);
+        dispname_str);
     } else {
       // non-parameterized template
       // use the default constructor for initialization
       def = mputprintf(def, "%s %s;\n",
-       type->get_genname_template(my_scope).c_str(), genname_str);
+        type->get_genname_template(my_scope).c_str(), genname_str);
       if (base_template) {
-       // copy the base template with an assignment
-       init = mputprintf(init, "%s = %s;\n", genname_str,
-         base_template->get_genname_from_scope(my_scope).c_str());
+        // copy the base template with an assignment
+        init = mputprintf(init, "%s = %s;\n", genname_str,
+          base_template->get_genname_from_scope(my_scope).c_str());
       }
       // finally assign the body
       init = body->generate_code_init(init, genname_str);
@@ -4471,7 +4461,7 @@ namespace Ttcn {
     if (p_def->get_asstype() != A_VAR) {
       const char *dispname_str = id->get_dispname().c_str();
       error("Local definition `%s' is a variable, but the definition "
-       "inherited from component type `%s' is a %s", dispname_str,
+        "inherited from component type `%s' is a %s", dispname_str,
         p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
       p_def->note("The inherited definition of `%s' is here", dispname_str);
       return false;
@@ -4481,36 +4471,36 @@ namespace Ttcn {
     if (!type->is_identical(p_def_var->type)) {
       const char *dispname_str = id->get_dispname().c_str();
       type->error("Local variable `%s' has type `%s', but the variable "
-       "inherited from component type `%s' has type `%s'", dispname_str,
-       type->get_typename().c_str(),
+        "inherited from component type `%s' has type `%s'", dispname_str,
+        type->get_typename().c_str(),
         p_def_var->get_my_scope()->get_fullname().c_str(),
-       p_def_var->type->get_typename().c_str());
+        p_def_var->type->get_typename().c_str());
       p_def_var->note("The inherited variable `%s' is here", dispname_str);
       return false;
     }
     if (initial_value) {
       if (p_def_var->initial_value) {
         if (!initial_value->is_unfoldable() &&
-           !p_def_var->initial_value->is_unfoldable() &&
-           !(*initial_value == *p_def_var->initial_value)) {
-         const char *dispname_str = id->get_dispname().c_str();
-         initial_value->warning("Local variable `%s' and the variable "
-           "inherited from component type `%s' have different initial values",
-           dispname_str, p_def_var->get_my_scope()->get_fullname().c_str());
-         p_def_var->note("The inherited variable `%s' is here", dispname_str);
-       }
+            !p_def_var->initial_value->is_unfoldable() &&
+            !(*initial_value == *p_def_var->initial_value)) {
+          const char *dispname_str = id->get_dispname().c_str();
+          initial_value->warning("Local variable `%s' and the variable "
+            "inherited from component type `%s' have different initial values",
+            dispname_str, p_def_var->get_my_scope()->get_fullname().c_str());
+          p_def_var->note("The inherited variable `%s' is here", dispname_str);
+        }
       } else {
-       const char *dispname_str = id->get_dispname().c_str();
-       initial_value->warning("Local variable `%s' has initial value, but "
-         "the variable inherited from component type `%s' does not",
-         dispname_str, p_def_var->get_my_scope()->get_fullname().c_str());
-       p_def_var->note("The inherited variable `%s' is here", dispname_str);
+        const char *dispname_str = id->get_dispname().c_str();
+        initial_value->warning("Local variable `%s' has initial value, but "
+          "the variable inherited from component type `%s' does not",
+          dispname_str, p_def_var->get_my_scope()->get_fullname().c_str());
+        p_def_var->note("The inherited variable `%s' is here", dispname_str);
       }
     } else if (p_def_var->initial_value) {
       const char *dispname_str = id->get_dispname().c_str();
       warning("Local variable `%s' does not have initial value, but the "
-       "variable inherited from component type `%s' has", dispname_str,
-       p_def_var->get_my_scope()->get_fullname().c_str());
+        "variable inherited from component type `%s' has", dispname_str,
+        p_def_var->get_my_scope()->get_fullname().c_str());
       p_def_var->note("The inherited variable `%s' is here", dispname_str);
     }
     return true;
@@ -4547,15 +4537,15 @@ namespace Ttcn {
       // the initial value can be represented by a single C++ expression
       // the object is initialized by the constructor
       str = mputprintf(str, "%s %s(%s);\n",
-       type->get_genname_value(my_scope).c_str(), genname_str,
-       initial_value->get_single_expr().c_str());
+        type->get_genname_value(my_scope).c_str(), genname_str,
+        initial_value->get_single_expr().c_str());
     } else {
       // use the default constructor
       str = mputprintf(str, "%s %s;\n",
-       type->get_genname_value(my_scope).c_str(), genname_str);
+        type->get_genname_value(my_scope).c_str(), genname_str);
       if (initial_value) {
-       // the initial value is assigned using subsequent statements
-       str = initial_value->generate_code_init(str, genname_str);
+        // the initial value is assigned using subsequent statements
+        str = initial_value->generate_code_init(str, genname_str);
       }
     }
     return str;
@@ -4577,7 +4567,7 @@ namespace Ttcn {
   {
     if (initial_value) {
       str = initial_value->generate_code_init(str,
-       base_defn->get_genname_from_scope(my_scope).c_str());
+        base_defn->get_genname_from_scope(my_scope).c_str());
     }
     return str;
   }
@@ -4685,7 +4675,7 @@ namespace Ttcn {
     if (p_def->get_asstype() != A_VAR_TEMPLATE) {
       const char *dispname_str = id->get_dispname().c_str();
       error("Local definition `%s' is a template variable, but the definition "
-       "inherited from component type `%s' is a %s", dispname_str,
+        "inherited from component type `%s' is a %s", dispname_str,
         p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
       p_def->note("The inherited definition of `%s' is here", dispname_str);
       return false;
@@ -4696,32 +4686,32 @@ namespace Ttcn {
     if (!type->is_identical(p_def_var_template->type)) {
       const char *dispname_str = id->get_dispname().c_str();
       type->error("Local template variable `%s' has type `%s', but the "
-       "template variable inherited from component type `%s' has type `%s'",
-       dispname_str, type->get_typename().c_str(),
+        "template variable inherited from component type `%s' has type `%s'",
+        dispname_str, type->get_typename().c_str(),
         p_def_var_template->get_my_scope()->get_fullname().c_str(),
-       p_def_var_template->type->get_typename().c_str());
+        p_def_var_template->type->get_typename().c_str());
       p_def_var_template->note("The inherited template variable `%s' is here",
-       dispname_str);
+        dispname_str);
       return false;
     }
     if (initial_value) {
       if (!p_def_var_template->initial_value) {
-       const char *dispname_str = id->get_dispname().c_str();
-       initial_value->warning("Local template variable `%s' has initial "
-         "value, but the template variable inherited from component type "
-         "`%s' does not", dispname_str,
-         p_def_var_template->get_my_scope()->get_fullname().c_str());
-       p_def_var_template->note("The inherited template variable `%s' is here",
-         dispname_str);
+        const char *dispname_str = id->get_dispname().c_str();
+        initial_value->warning("Local template variable `%s' has initial "
+          "value, but the template variable inherited from component type "
+          "`%s' does not", dispname_str,
+          p_def_var_template->get_my_scope()->get_fullname().c_str());
+        p_def_var_template->note("The inherited template variable `%s' is here",
+          dispname_str);
       }
     } else if (p_def_var_template->initial_value) {
       const char *dispname_str = id->get_dispname().c_str();
       warning("Local template variable `%s' does not have initial value, but "
-       "the template variable inherited from component type `%s' has",
-       dispname_str,
-       p_def_var_template->get_my_scope()->get_fullname().c_str());
+        "the template variable inherited from component type `%s' has",
+        dispname_str,
+        p_def_var_template->get_my_scope()->get_fullname().c_str());
       p_def_var_template->note("The inherited template variable `%s' is here",
-       dispname_str);
+        dispname_str);
     }
     return true;
   }
@@ -4809,7 +4799,7 @@ namespace Ttcn {
   {
     if (initial_value) {
       str = initial_value->generate_code_init(str,
-       base_defn->get_genname_from_scope(my_scope).c_str());
+        base_defn->get_genname_from_scope(my_scope).c_str());
       if (template_restriction != TR_NONE && gen_restriction_check)
         str = Template::generate_restriction_check_code(str,
                 base_defn->get_genname_from_scope(my_scope).c_str(),
@@ -4892,7 +4882,7 @@ namespace Ttcn {
     if (p_def->get_asstype() != A_TIMER) {
       const char *dispname_str = id->get_dispname().c_str();
       error("Local definition `%s' is a timer, but the definition inherited "
-       "from component type `%s' is a %s", dispname_str,
+        "from component type `%s' is a %s", dispname_str,
         p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
       p_def->note("The inherited definition of `%s' is here", dispname_str);
       return false;
@@ -4902,25 +4892,25 @@ namespace Ttcn {
     if (dimensions) {
       if (p_def_timer->dimensions) {
         if (!dimensions->is_identical(p_def_timer->dimensions)) {
-         const char *dispname_str = id->get_dispname().c_str();
-         error("Local timer `%s' and the timer inherited from component type "
-           "`%s' have different array dimensions", dispname_str,
+          const char *dispname_str = id->get_dispname().c_str();
+          error("Local timer `%s' and the timer inherited from component type "
+            "`%s' have different array dimensions", dispname_str,
             p_def_timer->get_my_scope()->get_fullname().c_str());
-         p_def_timer->note("The inherited timer `%s' is here", dispname_str);
-         return false;
-       }
+          p_def_timer->note("The inherited timer `%s' is here", dispname_str);
+          return false;
+        }
       } else {
-       const char *dispname_str = id->get_dispname().c_str();
-       error("Local definition `%s' is a timer array, but the definition "
-         "inherited from component type `%s' is a single timer", dispname_str,
+        const char *dispname_str = id->get_dispname().c_str();
+        error("Local definition `%s' is a timer array, but the definition "
+          "inherited from component type `%s' is a single timer", dispname_str,
           p_def_timer->get_my_scope()->get_fullname().c_str());
-       p_def_timer->note("The inherited timer `%s' is here", dispname_str);
-       return false;
+        p_def_timer->note("The inherited timer `%s' is here", dispname_str);
+        return false;
       }
     } else if (p_def_timer->dimensions) {
       const char *dispname_str = id->get_dispname().c_str();
       error("Local definition `%s' is a single timer, but the definition "
-       "inherited from component type `%s' is a timer array", dispname_str,
+        "inherited from component type `%s' is a timer array", dispname_str,
         p_def_timer->get_my_scope()->get_fullname().c_str());
       p_def_timer->note("The inherited timer `%s' is here", dispname_str);
       return false;
@@ -4928,27 +4918,27 @@ namespace Ttcn {
     if (default_duration) {
       if (p_def_timer->default_duration) {
         if (!default_duration->is_unfoldable() &&
-           !p_def_timer->default_duration->is_unfoldable() &&
-           !(*default_duration == *p_def_timer->default_duration)) {
-         const char *dispname_str = id->get_dispname().c_str();
-         default_duration->warning("Local timer `%s' and the timer inherited "
-           "from component type `%s' have different default durations",
-           dispname_str, p_def_timer->get_my_scope()->get_fullname().c_str());
-         p_def_timer->note("The inherited timer `%s' is here", dispname_str);
-       }
+            !p_def_timer->default_duration->is_unfoldable() &&
+            !(*default_duration == *p_def_timer->default_duration)) {
+          const char *dispname_str = id->get_dispname().c_str();
+          default_duration->warning("Local timer `%s' and the timer inherited "
+            "from component type `%s' have different default durations",
+            dispname_str, p_def_timer->get_my_scope()->get_fullname().c_str());
+          p_def_timer->note("The inherited timer `%s' is here", dispname_str);
+        }
       } else {
-       const char *dispname_str = id->get_dispname().c_str();
-       default_duration->error("Local timer `%s' has default duration, but "
-         "the timer inherited from component type `%s' does not", dispname_str,
+        const char *dispname_str = id->get_dispname().c_str();
+        default_duration->error("Local timer `%s' has default duration, but "
+          "the timer inherited from component type `%s' does not", dispname_str,
           p_def_timer->get_my_scope()->get_fullname().c_str());
-       p_def_timer->note("The inherited timer `%s' is here", dispname_str);
-       return false;
+        p_def_timer->note("The inherited timer `%s' is here", dispname_str);
+        return false;
       }
     } else if (p_def_timer->default_duration) {
       const char *dispname_str = id->get_dispname().c_str();
       error("Local timer `%s' does not have default duration, but the timer "
-       "inherited from component type `%s' has", dispname_str,
-       p_def_timer->get_my_scope()->get_fullname().c_str());
+        "inherited from component type `%s' has", dispname_str,
+        p_def_timer->get_my_scope()->get_fullname().c_str());
       p_def_timer->note("The inherited timer `%s' is here", dispname_str);
       return false;
     }
@@ -5094,49 +5084,49 @@ namespace Ttcn {
       const string& array_type = dimensions->get_timer_type();
       const char *array_type_str = array_type.c_str();
       target->header.global_vars = mputprintf(target->header.global_vars,
-       "extern %s %s;\n", array_type_str, genname_str);
+        "extern %s %s;\n", array_type_str, genname_str);
       target->source.global_vars = mputprintf(target->source.global_vars,
-       "%s %s;\n", array_type_str, genname_str);
+        "%s %s;\n", array_type_str, genname_str);
       target->functions.pre_init = mputstr(target->functions.pre_init, "{\n"
-       "static const char * const timer_name = \"");
+        "static const char * const timer_name = \"");
       target->functions.pre_init = mputstr(target->functions.pre_init,
-       dispname.c_str());
+        dispname.c_str());
       target->functions.pre_init = mputprintf(target->functions.pre_init,
-       "\";\n"
+        "\";\n"
         "%s.set_name(timer_name);\n"
-       "}\n", genname_str);
+        "}\n", genname_str);
       if (default_duration) target->functions.post_init =
-       generate_code_array_duration(target->functions.post_init, genname_str,
-         default_duration);
+        generate_code_array_duration(target->functions.post_init, genname_str,
+          default_duration);
     } else {
       // single timer
       target->header.global_vars = mputprintf(target->header.global_vars,
-       "extern TIMER %s;\n", genname_str);
+        "extern TIMER %s;\n", genname_str);
       if (default_duration) {
-       // has default duration
-       Value *v = default_duration->get_value_refd_last();
-       if (v->get_valuetype() == Value::V_REAL) {
-         // duration is known at compilation time -> set in the constructor
-         target->source.global_vars = mputprintf(target->source.global_vars,
-           "TIMER %s(\"%s\", %s);\n", genname_str, dispname.c_str(),
-           v->get_single_expr().c_str());
-       } else {
-         // duration is known only at runtime -> set in post_init
-         target->source.global_vars = mputprintf(target->source.global_vars,
-           "TIMER %s(\"%s\");\n", genname_str, dispname.c_str());
-         expression_struct expr;
-         Code::init_expr(&expr);
-         expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
-           genname_str);
-         default_duration->generate_code_expr(&expr);
-         expr.expr = mputc(expr.expr, ')');
-         target->functions.post_init =
-           Code::merge_free_expr(target->functions.post_init, &expr);
-       }
+        // has default duration
+        Value *v = default_duration->get_value_refd_last();
+        if (v->get_valuetype() == Value::V_REAL) {
+          // duration is known at compilation time -> set in the constructor
+          target->source.global_vars = mputprintf(target->source.global_vars,
+            "TIMER %s(\"%s\", %s);\n", genname_str, dispname.c_str(),
+            v->get_single_expr().c_str());
+        } else {
+          // duration is known only at runtime -> set in post_init
+          target->source.global_vars = mputprintf(target->source.global_vars,
+            "TIMER %s(\"%s\");\n", genname_str, dispname.c_str());
+          expression_struct expr;
+          Code::init_expr(&expr);
+          expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
+            genname_str);
+          default_duration->generate_code_expr(&expr);
+          expr.expr = mputc(expr.expr, ')');
+          target->functions.post_init =
+            Code::merge_free_expr(target->functions.post_init, &expr);
+        }
       } else {
-       // does not have default duration
-       target->source.global_vars = mputprintf(target->source.global_vars,
-         "TIMER %s(\"%s\");\n", genname_str, dispname.c_str());
+        // does not have default duration
+        target->source.global_vars = mputprintf(target->source.global_vars,
+          "TIMER %s(\"%s\");\n", genname_str, dispname.c_str());
       }
     }
   }
@@ -5274,33 +5264,33 @@ namespace Ttcn {
       const char *array_type_str = array_type.c_str();
       str = mputprintf(str, "%s %s;\n", array_type_str, genname_str);
       str = mputstr(str, "{\n"
-       "static const char * const timer_name =  \"");
+        "static const char * const timer_name =  \"");
       str = mputstr(str, dispname.c_str());
       str = mputprintf(str, "\";\n"
         "%s.set_name(timer_name);\n"
-       "}\n", genname_str);
+        "}\n", genname_str);
       if (default_duration) str = generate_code_array_duration(str,
-       genname_str, default_duration);
+        genname_str, default_duration);
     } else {
       // single timer
       if (default_duration && default_duration->has_single_expr()) {
-       // the default duration can be passed to the constructor
-       str = mputprintf(str, "TIMER %s(\"%s\", %s);\n", genname_str,
-         dispname.c_str(), default_duration->get_single_expr().c_str());
+        // the default duration can be passed to the constructor
+        str = mputprintf(str, "TIMER %s(\"%s\", %s);\n", genname_str,
+          dispname.c_str(), default_duration->get_single_expr().c_str());
       } else {
-       // only the name is passed to the constructor
-       str = mputprintf(str, "TIMER %s(\"%s\");\n", genname_str,
-         dispname.c_str());
-       if (default_duration) {
-         // the default duration is set explicitly
-         expression_struct expr;
-         Code::init_expr(&expr);
-         expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
-           genname_str);
-         default_duration->generate_code_expr(&expr);
-         expr.expr = mputc(expr.expr, ')');
-         str = Code::merge_free_expr(str, &expr);
-       }
+        // only the name is passed to the constructor
+        str = mputprintf(str, "TIMER %s(\"%s\");\n", genname_str,
+          dispname.c_str());
+        if (default_duration) {
+          // the default duration is set explicitly
+          expression_struct expr;
+          Code::init_expr(&expr);
+          expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
+            genname_str);
+          default_duration->generate_code_expr(&expr);
+          expr.expr = mputc(expr.expr, ')');
+          str = Code::merge_free_expr(str, &expr);
+        }
       }
     }
     return str;
@@ -5321,39 +5311,39 @@ namespace Ttcn {
       const char *array_type_str = array_type.c_str();
       def = mputprintf(def, "%s %s;\n", array_type_str, genname_str);
       def = mputstr(def, "{\n"
-       "static const char * const timer_names[] = { ");
+        "static const char * const timer_names[] = { ");
       def = dimensions->generate_element_names(def, dispname);
       def = mputprintf(def, " };\n"
         "%s.set_name(%lu, timer_names);\n"
-       "}\n", genname_str, (unsigned long) dimensions->get_array_size());
+        "}\n", genname_str, (unsigned long) dimensions->get_array_size());
       if (default_duration) init = generate_code_array_duration(init,
-       genname_str, default_duration);
+        genname_str, default_duration);
     } else {
       // single timer
       if (default_duration) {
-       // has default duration
-       Value *v = default_duration->get_value_refd_last();
-       if (v->get_valuetype() == Value::V_REAL) {
-         // duration is known at compilation time -> set in the constructor
-         def = mputprintf(def, "TIMER %s(\"%s\", %s);\n", genname_str,
-           dispname.c_str(), v->get_single_expr().c_str());
-       } else {
-         // duration is known only at runtime -> set when control reaches the
-         // timer definition
-         def = mputprintf(def, "TIMER %s(\"%s\");\n", genname_str,
-           dispname.c_str());
+        // has default duration
+        Value *v = default_duration->get_value_refd_last();
+        if (v->get_valuetype() == Value::V_REAL) {
+          // duration is known at compilation time -> set in the constructor
+          def = mputprintf(def, "TIMER %s(\"%s\", %s);\n", genname_str,
+            dispname.c_str(), v->get_single_expr().c_str());
+        } else {
+          // duration is known only at runtime -> set when control reaches the
+          // timer definition
+          def = mputprintf(def, "TIMER %s(\"%s\");\n", genname_str,
+            dispname.c_str());
           expression_struct expr;
           Code::init_expr(&expr);
-         expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
-           genname_str);
-         default_duration->generate_code_expr(&expr);
-         expr.expr = mputc(expr.expr, ')');
-         init = Code::merge_free_expr(init, &expr);
-       }
+          expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
+            genname_str);
+          default_duration->generate_code_expr(&expr);
+          expr.expr = mputc(expr.expr, ')');
+          init = Code::merge_free_expr(init, &expr);
+        }
       } else {
-       // does not have default duration
-       def = mputprintf(def, "TIMER %s(\"%s\");\n", genname_str,
-         dispname.c_str());
+        // does not have default duration
+        def = mputprintf(def, "TIMER %s(\"%s\");\n", genname_str,
+          dispname.c_str());
       }
     }
   }
@@ -5363,25 +5353,25 @@ namespace Ttcn {
     if (default_duration) {
       Def_Timer *base_timer_defn = dynamic_cast<Def_Timer*>(base_defn);
       if (!base_timer_defn || !base_timer_defn->default_duration)
-       FATAL_ERROR("Def_Timer::generate_code_init_comp()");
+        FATAL_ERROR("Def_Timer::generate_code_init_comp()");
       // initializer is not needed if the default durations are the same
       // constants in both timers
       if (default_duration->is_unfoldable() ||
-         base_timer_defn->default_duration->is_unfoldable() ||
-         !(*default_duration == *base_timer_defn->default_duration)) {
-       if (dimensions) {
-         str = generate_code_array_duration(str,
-           base_timer_defn->get_genname_from_scope(my_scope).c_str(),
-           default_duration);
-       } else {
-         expression_struct expr;
-         Code::init_expr(&expr);
-         expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
-           base_timer_defn->get_genname_from_scope(my_scope).c_str());
-         default_duration->generate_code_expr(&expr);
-         expr.expr = mputc(expr.expr, ')');
-         str = Code::merge_free_expr(str, &expr);
-       }
+          base_timer_defn->default_duration->is_unfoldable() ||
+          !(*default_duration == *base_timer_defn->default_duration)) {
+        if (dimensions) {
+          str = generate_code_array_duration(str,
+            base_timer_defn->get_genname_from_scope(my_scope).c_str(),
+            default_duration);
+        } else {
+          expression_struct expr;
+          Code::init_expr(&expr);
+          expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
+            base_timer_defn->get_genname_from_scope(my_scope).c_str());
+          default_duration->generate_code_expr(&expr);
+          expr.expr = mputc(expr.expr, ')');
+          str = Code::merge_free_expr(str, &expr);
+        }
       }
     }
     return str;
@@ -5456,9 +5446,9 @@ namespace Ttcn {
     if (ass) {
       if (ass->get_asstype() == A_TYPE) {
         Type *t = ass->get_Type()->get_type_refd_last();
-       if (t->get_typetype() == Type::T_PORT) port_type = t;
-       else type_ref->error("Type reference `%s' does not refer to a "
-         "port type", type_ref->get_dispname().c_str());
+        if (t->get_typetype() == Type::T_PORT) port_type = t;
+        else type_ref->error("Type reference `%s' does not refer to a "
+          "port type", type_ref->get_dispname().c_str());
       } else type_ref->error("Reference `%s' does not refer to a "
         "type", type_ref->get_dispname().c_str());
     }
@@ -5476,7 +5466,7 @@ namespace Ttcn {
     if (p_def->get_asstype() != A_PORT) {
       const char *dispname_str = id->get_dispname().c_str();
       error("Local definition `%s' is a port, but the definition inherited "
-       "from component type `%s' is a %s", dispname_str,
+        "from component type `%s' is a %s", dispname_str,
         p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
       p_def->note("The inherited definition of `%s' is here", dispname_str);
       return false;
@@ -5484,38 +5474,38 @@ namespace Ttcn {
     Def_Port *p_def_port = dynamic_cast<Def_Port*>(p_def);
     if (!p_def_port) FATAL_ERROR("Def_Port::chk_identical()");
     if (port_type && p_def_port->port_type &&
-       port_type != p_def_port->port_type) {
+        port_type != p_def_port->port_type) {
       const char *dispname_str = id->get_dispname().c_str();
       type_ref->error("Local port `%s' has type `%s', but the port inherited "
-       "from component type `%s' has type `%s'", dispname_str,
-       port_type->get_typename().c_str(),
+        "from component type `%s' has type `%s'", dispname_str,
+        port_type->get_typename().c_str(),
         p_def_port->get_my_scope()->get_fullname().c_str(),
-       p_def_port->port_type->get_typename().c_str());
+        p_def_port->port_type->get_typename().c_str());
       p_def_port->note("The inherited port `%s' is here", dispname_str);
       return false;
     }
     if (dimensions) {
       if (p_def_port->dimensions) {
         if (!dimensions->is_identical(p_def_port->dimensions)) {
-         const char *dispname_str = id->get_dispname().c_str();
-         error("Local port `%s' and the port inherited from component type "
-           "`%s' have different array dimensions", dispname_str,
+          const char *dispname_str = id->get_dispname().c_str();
+          error("Local port `%s' and the port inherited from component type "
+            "`%s' have different array dimensions", dispname_str,
             p_def_port->get_my_scope()->get_fullname().c_str());
-         p_def_port->note("The inherited port `%s' is here", dispname_str);
-         return false;
-       }
+          p_def_port->note("The inherited port `%s' is here", dispname_str);
+          return false;
+        }
       } else {
-       const char *dispname_str = id->get_dispname().c_str();
-       error("Local definition `%s' is a port array, but the definition "
-         "inherited from component type `%s' is a single port", dispname_str,
+        const char *dispname_str = id->get_dispname().c_str();
+        error("Local definition `%s' is a port array, but the definition "
+          "inherited from component type `%s' is a single port", dispname_str,
           p_def_port->get_my_scope()->get_fullname().c_str());
-       p_def_port->note("The inherited port `%s' is here", dispname_str);
-       return false;
+        p_def_port->note("The inherited port `%s' is here", dispname_str);
+        return false;
       }
     } else if (p_def_port->dimensions) {
       const char *dispname_str = id->get_dispname().c_str();
       error("Local definition `%s' is a single port, but the definition "
-       "inherited from component type `%s' is a port array", dispname_str,
+        "inherited from component type `%s' is a port array", dispname_str,
         p_def_port->get_my_scope()->get_fullname().c_str());
       p_def_port->note("The inherited port `%s' is here", dispname_str);
       return false;
@@ -5534,24 +5524,24 @@ namespace Ttcn {
       const string& array_type = dimensions->get_port_type(type_genname);
       const char *array_type_str = array_type.c_str();
       target->header.global_vars = mputprintf(target->header.global_vars,
-       "extern %s %s;\n", array_type_str, genname_str);
+        "extern %s %s;\n", array_type_str, genname_str);
       target->source.global_vars = mputprintf(target->source.global_vars,
-       "%s %s;\n", array_type_str, genname_str);
+        "%s %s;\n", array_type_str, genname_str);
       target->functions.pre_init = mputstr(target->functions.pre_init, "{\n"
-       "static const char * const port_name = \"");
+        "static const char * const port_name = \"");
       target->functions.pre_init = mputstr(target->functions.pre_init,
-       dispname.c_str());
+        dispname.c_str());
       target->functions.pre_init = mputprintf(target->functions.pre_init,
-       "\";\n"
+        "\";\n"
         "%s.set_name(port_name);\n"
-       "}\n", genname_str);
+        "}\n", genname_str);
     } else {
       // single port
       const char *type_genname_str = type_genname.c_str();
       target->header.global_vars = mputprintf(target->header.global_vars,
-       "extern %s %s;\n", type_genname_str, genname_str);
+        "extern %s %s;\n", type_genname_str, genname_str);
       target->source.global_vars = mputprintf(target->source.global_vars,
-       "%s %s(\"%s\");\n", type_genname_str, genname_str, dispname.c_str());
+        "%s %s(\"%s\");\n", type_genname_str, genname_str, dispname.c_str());
     }
     target->functions.init_comp = mputprintf(target->functions.init_comp,
       "%s.activate_port();\n", genname_str);
@@ -5584,21 +5574,21 @@ namespace Ttcn {
   {
     if (is_external) {
       if (has_return_type) {
-       if (returns_template) return A_EXT_FUNCTION_RTEMP;
-       else return A_EXT_FUNCTION_RVAL;
+        if (returns_template) return A_EXT_FUNCTION_RTEMP;
+        else return A_EXT_FUNCTION_RVAL;
       } else {
-       if (returns_template)
-         FATAL_ERROR("Def_Function_Base::determine_asstype()");
-       return A_EXT_FUNCTION;
+        if (returns_template)
+          FATAL_ERROR("Def_Function_Base::determine_asstype()");
+        return A_EXT_FUNCTION;
       }
     } else { // not an external function
       if (has_return_type) {
-       if (returns_template) return A_FUNCTION_RTEMP;
-       else return A_FUNCTION_RVAL;
+        if (returns_template) return A_FUNCTION_RTEMP;
+        else return A_FUNCTION_RVAL;
       } else {
-       if (returns_template)
-         FATAL_ERROR("Def_Function_Base::determine_asstype()");
-       return A_FUNCTION;
+        if (returns_template)
+          FATAL_ERROR("Def_Function_Base::determine_asstype()");
+        return A_FUNCTION;
       }
     }
   }
@@ -5616,8 +5606,8 @@ namespace Ttcn {
     FormalParList *p_fpl, Type *p_return_type, bool returns_template,
     template_restriction_t p_template_restriction)
     : Definition(determine_asstype(is_external, p_return_type != 0,
-       returns_template), p_id), fp_list(p_fpl), return_type(p_return_type),
-       prototype(PROTOTYPE_NONE), input_type(0), output_type(0),
+        returns_template), p_id), fp_list(p_fpl), return_type(p_return_type),
+        prototype(PROTOTYPE_NONE), input_type(0), output_type(0),
         template_restriction(p_template_restriction)
   {
     if (!p_fpl) FATAL_ERROR("Def_Function_Base::Def_Function_Base()");
@@ -5693,100 +5683,100 @@ namespace Ttcn {
     // checking the formal parameter list
     if (prototype == PROTOTYPE_CONVERT) {
       if (fp_list->get_nof_fps() == 1) {
-       FormalPar *par = fp_list->get_fp_byIndex(0);
-       if (par->get_asstype() == A_PAR_VAL_IN) {
-         input_type = par->get_Type();
-       } else {
-         par->error("The parameter must be an `in' value parameter for "
-           "attribute `prototype(%s)' instead of %s", get_prototype_name(),
-           par->get_assname());
-       }
+        FormalPar *par = fp_list->get_fp_byIndex(0);
+        if (par->get_asstype() == A_PAR_VAL_IN) {
+          input_type = par->get_Type();
+        } else {
+          par->error("The parameter must be an `in' value parameter for "
+            "attribute `prototype(%s)' instead of %s", get_prototype_name(),
+            par->get_assname());
+        }
       } else {
-       fp_list->error("The function must have one parameter instead of %lu "
-         "for attribute `prototype(%s)'", (unsigned long) fp_list->get_nof_fps(),
-         get_prototype_name());
+        fp_list->error("The function must have one parameter instead of %lu "
+          "for attribute `prototype(%s)'", (unsigned long) fp_list->get_nof_fps(),
+          get_prototype_name());
       }
     } else { // not PROTOTYPE_CONVERT
       if (fp_list->get_nof_fps() == 2) {
-       FormalPar *first_par = fp_list->get_fp_byIndex(0);
-       if (prototype == PROTOTYPE_SLIDING) {
-         if (first_par->get_asstype() == A_PAR_VAL_INOUT) {
-           Type *first_par_type = first_par->get_Type();
-           switch (first_par_type->get_type_refd_last()
-                   ->get_typetype_ttcn3()) {
-           case Type::T_ERROR:
-           case Type::T_OSTR:
-           case Type::T_CSTR:
-           case Type::T_BSTR:
-             input_type = first_par_type;
-             break;
-           default:
-             first_par_type->error("The type of the first parameter must be "
-               "`octetstring' or `charstring' or `bitstring' for attribute "
-               "`prototype(%s)' instead of `%s'", get_prototype_name(),
-               first_par_type->get_typename().c_str());
-           }
-         } else {
-           first_par->error("The first parameter must be an `inout' value "
-             "parameter for attribute `prototype(%s)' instead of %s",
-             get_prototype_name(), first_par->get_assname());
-         }
-       } else {
-         if (first_par->get_asstype() == A_PAR_VAL_IN) {
-           input_type = first_par->get_Type();
-         } else {
-           first_par->error("The first parameter must be an `in' value "
-             "parameter for attribute `prototype(%s)' instead of %s",
-             get_prototype_name(), first_par->get_assname());
-         }
-       }
-       FormalPar *second_par = fp_list->get_fp_byIndex(1);
-       if (second_par->get_asstype() == A_PAR_VAL_OUT) {
-         output_type = second_par->get_Type();
-       } else {
-         second_par->error("The second parameter must be an `out' value "
-           "parameter for attribute `prototype(%s)' instead of %s",
-           get_prototype_name(), second_par->get_assname());
-       }
+        FormalPar *first_par = fp_list->get_fp_byIndex(0);
+        if (prototype == PROTOTYPE_SLIDING) {
+          if (first_par->get_asstype() == A_PAR_VAL_INOUT) {
+            Type *first_par_type = first_par->get_Type();
+            switch (first_par_type->get_type_refd_last()
+                    ->get_typetype_ttcn3()) {
+            case Type::T_ERROR:
+            case Type::T_OSTR:
+            case Type::T_CSTR:
+            case Type::T_BSTR:
+              input_type = first_par_type;
+              break;
+            default:
+              first_par_type->error("The type of the first parameter must be "
+                "`octetstring' or `charstring' or `bitstring' for attribute "
+                "`prototype(%s)' instead of `%s'", get_prototype_name(),
+                first_par_type->get_typename().c_str());
+            }
+          } else {
+            first_par->error("The first parameter must be an `inout' value "
+              "parameter for attribute `prototype(%s)' instead of %s",
+              get_prototype_name(), first_par->get_assname());
+          }
+        } else {
+          if (first_par->get_asstype() == A_PAR_VAL_IN) {
+            input_type = first_par->get_Type();
+          } else {
+            first_par->error("The first parameter must be an `in' value "
+              "parameter for attribute `prototype(%s)' instead of %s",
+              get_prototype_name(), first_par->get_assname());
+          }
+        }
+        FormalPar *second_par = fp_list->get_fp_byIndex(1);
+        if (second_par->get_asstype() == A_PAR_VAL_OUT) {
+          output_type = second_par->get_Type();
+        } else {
+          second_par->error("The second parameter must be an `out' value "
+            "parameter for attribute `prototype(%s)' instead of %s",
+            get_prototype_name(), second_par->get_assname());
+        }
       } else {
-       fp_list->error("The function must have two parameters for attribute "
-         "`prototype(%s)' instead of %lu", get_prototype_name(),
-         (unsigned long) fp_list->get_nof_fps());
+        fp_list->error("The function must have two parameters for attribute "
+          "`prototype(%s)' instead of %lu", get_prototype_name(),
+          (unsigned long) fp_list->get_nof_fps());
       }
     }
     // checking the return type
     if (prototype == PROTOTYPE_FAST) {
       if (return_type) {
-       return_type->error("The function cannot have return type for "
-         "attribute `prototype(%s)'", get_prototype_name());
+        return_type->error("The function cannot have return type for "
+          "attribute `prototype(%s)'", get_prototype_name());
       }
     } else {
       if (return_type) {
-       if (asstype == A_FUNCTION_RTEMP || asstype == A_EXT_FUNCTION_RTEMP)
-         return_type->error("The function must return a value instead of a "
-           "template for attribute `prototype(%s)'", get_prototype_name());
-       if (prototype == PROTOTYPE_CONVERT) {
-         output_type = return_type;
-       } else {
-         switch (return_type->get_type_refd_last()->get_typetype_ttcn3()) {
-         case Type::T_ERROR:
-         case Type::T_INT:
-           break;
-         default:
-           return_type->error("The return type of the function must be "
-             "`integer' instead of `%s' for attribute `prototype(%s)'",
-             return_type->get_typename().c_str(), get_prototype_name());
-         }
-       }
+        if (asstype == A_FUNCTION_RTEMP || asstype == A_EXT_FUNCTION_RTEMP)
+          return_type->error("The function must return a value instead of a "
+            "template for attribute `prototype(%s)'", get_prototype_name());
+        if (prototype == PROTOTYPE_CONVERT) {
+          output_type = return_type;
+        } else {
+          switch (return_type->get_type_refd_last()->get_typetype_ttcn3()) {
+          case Type::T_ERROR:
+          case Type::T_INT:
+            break;
+          default:
+            return_type->error("The return type of the function must be "
+              "`integer' instead of `%s' for attribute `prototype(%s)'",
+              return_type->get_typename().c_str(), get_prototype_name());
+          }
+        }
       } else {
-       error("The function must have return type for attribute "
-         "`prototype(%s)'", get_prototype_name());
+        error("The function must have return type for attribute "
+          "`prototype(%s)'", get_prototype_name());
       }
     }
     // checking the 'runs on' clause
     if (get_RunsOnType()) {
       error("The function cannot have `runs on' clause for attribute "
-       "`prototype(%s)'", get_prototype_name());
+        "`prototype(%s)'", get_prototype_name());
     }
   }
 
@@ -5814,8 +5804,8 @@ namespace Ttcn {
                              StatementBlock *p_block)
     : Def_Function_Base(false, p_id, p_fpl, p_return_type, returns_template,
         p_template_restriction),
-       runs_on_ref(p_runs_on_ref), runs_on_type(0), block(p_block),
-       is_startable(false), transparent(false)
+        runs_on_ref(p_runs_on_ref), runs_on_type(0), block(p_block),
+        is_startable(false), transparent(false)
   {
     if (!p_block) FATAL_ERROR("Def_Function::Def_Function()");
     block->set_my_def(this);
@@ -5891,7 +5881,7 @@ namespace Ttcn {
     is_startable = runs_on_ref != 0;
     if (is_startable && !fp_list->get_startability()) is_startable = false;
     if (is_startable && return_type && return_type->is_component_internal())
-         is_startable = false;
+          is_startable = false;
     // checking of statement block
     block->chk();
     if (return_type) {
@@ -5899,13 +5889,13 @@ namespace Ttcn {
       switch (block->has_return()) {
       case StatementBlock::RS_NO:
         error("The function has return type, but it does not have any return "
-         "statement");
+          "statement");
         break;
       case StatementBlock::RS_MAYBE:
-       error("The function has return type, but control might leave it "
-         "without reaching a return statement");
+            error("The function has return type, but control might leave it "
+          "without reaching a return statement");
       default:
-       break;
+        break;
       }
     }
     if (!semantic_check_only) {
@@ -6002,7 +5992,7 @@ namespace Ttcn {
     // function prototype
     target->header.function_prototypes =
       mputprintf(target->header.function_prototypes, "extern %s %s(%s);\n",
-       return_type_str, genname_str, formal_par_list);
+        return_type_str, genname_str, formal_par_list);
 
     // function body
     char *body = mprintf("%s %s(%s)\n"
@@ -6020,107 +6010,107 @@ namespace Ttcn {
     if (is_startable) {
       size_t nof_fps = fp_list->get_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);
-       // 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);
-       for (size_t i = 0; i < nof_fps; i++) {
-         if (i > 0) body = mputstr(body,
+        // 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);
+        // 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);
+        for (size_t i = 0; i < nof_fps; i++) {
+          if (i > 0) body = mputstr(body,
              "TTCN_Logger::log_event_str(\", \");\n");
-         body = mputprintf(body, "%s.log();\n",
-           fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
-       }
-       body = mputprintf(body,
-         "TTCN_Logger::log_event_str(\") on component \");\n"
-         "component_reference.log();\n"
-         "TTCN_Logger::log_char('.');\n"
-         "TTCN_Logger::end_event();\n"
-         "Text_Buf text_buf;\n"
-         "TTCN_Runtime::prepare_start_component(component_reference, "
-           "\"%s\", \"%s\", text_buf);\n",
-         my_scope->get_scope_mod()->get_modid().get_dispname().c_str(),
-         dispname_str);
-       for (size_t i = 0; i < nof_fps; i++) {
-         body = mputprintf(body, "%s.encode_text(text_buf);\n",
-           fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
-       }
-       body = mputstr(body, "TTCN_Runtime::send_start_component(text_buf);\n"
-         "}\n\n");
-       target->source.function_bodies = mputstr(target->source.function_bodies,
-         body);
-       Free(body);
+          body = mputprintf(body, "%s.log();\n",
+            fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
+        }
+        body = mputprintf(body,
+          "TTCN_Logger::log_event_str(\") on component \");\n"
+          "component_reference.log();\n"
+          "TTCN_Logger::log_char('.');\n"
+          "TTCN_Logger::end_event();\n"
+          "Text_Buf text_buf;\n"
+          "TTCN_Runtime::prepare_start_component(component_reference, "
+            "\"%s\", \"%s\", text_buf);\n",
+          my_scope->get_scope_mod()->get_modid().get_dispname().c_str(),
+          dispname_str);
+        for (size_t i = 0; i < nof_fps; i++) {
+          body = mputprintf(body, "%s.encode_text(text_buf);\n",
+            fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
+        }
+        body = mputstr(body, "TTCN_Runtime::send_start_component(text_buf);\n"
+          "}\n\n");
+        target->source.function_bodies = mputstr(target->source.function_bodies,
+          body);
+        Free(body);
 
       // an entry in start_ptc_function
       body = mprintf("if (!strcmp(function_name, \"%s\")) {\n",
-       dispname_str);
+        dispname_str);
       if (nof_fps > 0) {
-       body = fp_list->generate_code_object(body, "", ' ');
-       for (size_t i = 0; i < nof_fps; i++) {
-         body = mputprintf(body, "%s.decode_text(function_arguments);\n",
-           fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
-       }
-       body = mputprintf(body,
-         "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
-         "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
-         dispname_str);
-       for (size_t i = 0; i < nof_fps; i++) {
-         if (i > 0) body = mputstr(body,
+        body = fp_list->generate_code_object(body, "", ' ');
+        for (size_t i = 0; i < nof_fps; i++) {
+          body = mputprintf(body, "%s.decode_text(function_arguments);\n",
+            fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
+        }
+        body = mputprintf(body,
+          "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
+          "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
+          dispname_str);
+        for (size_t i = 0; i < nof_fps; i++) {
+          if (i > 0) body = mputstr(body,
              "TTCN_Logger::log_event_str(\", \");\n");
-         body = mputprintf(body, "%s.log();\n",
-           fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
-       }
-       body = mputstr(body, "TTCN_Logger::log_event_str(\").\");\n"
-         "TTCN_Logger::end_event();\n");
+          body = mputprintf(body, "%s.log();\n",
+            fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
+        }
+        body = mputstr(body, "TTCN_Logger::log_event_str(\").\");\n"
+          "TTCN_Logger::end_event();\n");
       } else {
-       body = mputprintf(body,
-         "TTCN_Logger::log_str(TTCN_Logger::PARALLEL_PTC, \"Starting function "
+        body = mputprintf(body,
+          "TTCN_Logger::log_str(TTCN_Logger::PARALLEL_PTC, \"Starting function "
           "%s().\");\n", dispname_str);
       }
       body = mputstr(body,
-       "TTCN_Runtime::function_started(function_arguments);\n");
+        "TTCN_Runtime::function_started(function_arguments);\n");
       char *actual_par_list =
-       fp_list->generate_code_actual_parlist(memptystr(), "");
+        fp_list->generate_code_actual_parlist(memptystr(), "");
       bool return_value_kept = false;
       if (asstype == A_FUNCTION_RVAL) {
-       // the return value is kept only if the function returns a value
-       // (rather than a template) and the return type has the "done"
-       // extension attribute
-       for (Type *t = return_type; ; t = t->get_type_refd()) {
-         if (t->has_done_attribute()) {
-           return_value_kept = true;
-           break;
-         } else if (!t->is_ref()) break;
-       }
+        // the return value is kept only if the function returns a value
+        // (rather than a template) and the return type has the "done"
+        // extension attribute
+        for (Type *t = return_type; ; t = t->get_type_refd()) {
+          if (t->has_done_attribute()) {
+            return_value_kept = true;
+            break;
+          } else if (!t->is_ref()) break;
+        }
       }
       if (return_value_kept) {
-       const string& return_type_dispname = return_type->get_typename();
-       const char *return_type_dispname_str = return_type_dispname.c_str();
-       body = mputprintf(body, "%s ret_val(%s(%s));\n"
-         "TTCN_Logger::begin_event(TTCN_PARALLEL);\n"
-         "TTCN_Logger::log_event_str(\"Function %s returned %s : \");\n"
-         "ret_val.log();\n"
-         "Text_Buf text_buf;\n"
-         "TTCN_Runtime::prepare_function_finished(\"%s\", text_buf);\n"
-         "ret_val.encode_text(text_buf);\n"
-         "TTCN_Runtime::send_function_finished(text_buf);\n",
-         return_type_str, genname_str, actual_par_list, dispname_str,
-         return_type_dispname_str, return_type_dispname_str);
+        const string& return_type_dispname = return_type->get_typename();
+        const char *return_type_dispname_str = return_type_dispname.c_str();
+        body = mputprintf(body, "%s ret_val(%s(%s));\n"
+          "TTCN_Logger::begin_event(TTCN_PARALLEL);\n"
+          "TTCN_Logger::log_event_str(\"Function %s returned %s : \");\n"
+          "ret_val.log();\n"
+          "Text_Buf text_buf;\n"
+          "TTCN_Runtime::prepare_function_finished(\"%s\", text_buf);\n"
+          "ret_val.encode_text(text_buf);\n"
+          "TTCN_Runtime::send_function_finished(text_buf);\n",
+          return_type_str, genname_str, actual_par_list, dispname_str,
+          return_type_dispname_str, return_type_dispname_str);
       } else {
-       body = mputprintf(body, "%s(%s);\n"
-         "TTCN_Runtime::function_finished(\"%s\");\n",
-         genname_str, actual_par_list, dispname_str);
+        body = mputprintf(body, "%s(%s);\n"
+          "TTCN_Runtime::function_finished(\"%s\");\n",
+          genname_str, actual_par_list, dispname_str);
       }
       Free(actual_par_list);
       body = mputstr(body, "return TRUE;\n"
-       "} else ");
+        "} else ");
       target->functions.start = mputstr(target->functions.start, body);
       Free(body);
     }
@@ -6225,20 +6215,20 @@ namespace Ttcn {
     switch (function_type) {
     case EXTFUNC_MANUAL:
       if (eb_list) {
-       eb_list->error("Attribute `errorbehavior' can only be used together "
-         "with `encode' or `decode'");
-       eb_list->chk();
+        eb_list->error("Attribute `errorbehavior' can only be used together "
+          "with `encode' or `decode'");
+        eb_list->chk();
       }
       break;
     case EXTFUNC_ENCODE:
       switch (prototype) {
       case PROTOTYPE_NONE:
-       error("Attribute `encode' cannot be used without `prototype'");
-       break;
+        error("Attribute `encode' cannot be used without `prototype'");
+        break;
       case PROTOTYPE_BACKTRACK:
       case PROTOTYPE_SLIDING:
-       error("Attribute `encode' cannot be used with `prototype(%s)'",
-         get_prototype_name());
+        error("Attribute `encode' cannot be used with `prototype(%s)'",
+          get_prototype_name());
       default: /* CONVERT and FAST allowed */
         break;
       }
@@ -6256,34 +6246,59 @@ namespace Ttcn {
         }
       }
       if (output_type) {
-       Type *stream_type = Type::get_stream_type(encoding_type);
-       if (!stream_type->is_identical(output_type)) {
-         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(),
-           output_type->get_typename().c_str());
-       }
+        if(encoding_type == Common::Type::CT_TEXT){  // the TEXT encoding support both octetstring ans charstring stream type
+          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' "
+              "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());
+          }
+        } 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' "
+              "instead of `%s'", Type::get_encoding_name(encoding_type),
+              stream_type->get_typename().c_str(),
+              input_type->get_typename().c_str());
+          }
+        }
       }
       if (eb_list) eb_list->chk();
       chk_allowed_encode();
       break;
     case EXTFUNC_DECODE:
       if (prototype == PROTOTYPE_NONE) {
-       error("Attribute `decode' cannot be used without `prototype'");
+        error("Attribute `decode' cannot be used without `prototype'");
       }
       if (input_type) {
-       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' "
-           "instead of `%s'", Type::get_encoding_name(encoding_type),
-           stream_type->get_typename().c_str(),
-           input_type->get_typename().c_str());
-       }
+        if(encoding_type == Common::Type::CT_TEXT){  // the TEXT encoding support both octetstring ans charstring stream type
+          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' "
+              "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());
+          }
+        } 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' "
+              "instead of `%s'", Type::get_encoding_name(encoding_type),
+              stream_type->get_typename().c_str(),
+              input_type->get_typename().c_str());
+          }
+        }
+        
       }
       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));
+        output_type->error("Output type `%s' does not support %s encoding",
+          output_type->get_typename().c_str(),
+          Type::get_encoding_name(encoding_type));
       }
       if (eb_list) eb_list->chk();
       chk_allowed_encode();
@@ -6334,7 +6349,7 @@ namespace Ttcn {
       Error_Context cntxt2(return_type, "In return type");
       return_type->chk();
       return_type->chk_as_return_type(asstype == A_EXT_FUNCTION_RVAL,
-       "external function");
+        "external function");
     }
     if (!semantic_check_only) fp_list->set_genname(get_genname());
     if (w_attrib_path) {
@@ -6477,7 +6492,7 @@ namespace Ttcn {
       result_name = "ret_val";
       // creating a local variable for the result stream
       str = mputprintf(str, "%s ret_val;\n",
-       output_type->get_genname_value(my_scope).c_str());
+        output_type->get_genname_value(my_scope).c_str());
       break;
     case PROTOTYPE_FAST:
       result_name = fp_list->get_fp_byIndex(1)->get_id().get_name().c_str();
@@ -6522,7 +6537,7 @@ namespace Ttcn {
     // setting error behavior
     if (eb_list) str = eb_list->generate_code(str);
     else if (prototype == PROTOTYPE_BACKTRACK || prototype == PROTOTYPE_SLIDING) {
-       str = mputstr(str, "TTCN_EncDec::set_error_behavior("
+            str = mputstr(str, "TTCN_EncDec::set_error_behavior("
       "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);\n");
     } else str = mputstr(str, "TTCN_EncDec::set_error_behavior("
       "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
@@ -6533,7 +6548,7 @@ namespace Ttcn {
     if (prototype == PROTOTYPE_CONVERT) {
       // creating a local variable for the result
       str = mputprintf(str, "%s ret_val;\n",
-       output_type->get_genname_value(my_scope).c_str());
+        output_type->get_genname_value(my_scope).c_str());
       result_name = "ret_val";
     } else {
       result_name = fp_list->get_fp_byIndex(1)->get_id().get_name().c_str();
@@ -6562,47 +6577,47 @@ namespace Ttcn {
     if (prototype != PROTOTYPE_SLIDING) {
       // checking for remaining data in the buffer if decoding was successful
       str = mputprintf(str, "if (TTCN_EncDec::get_last_error_type() == "
-         "TTCN_EncDec::ET_NONE) {\n"
-       "if (ttcn_buffer.get_pos() < ttcn_buffer.get_len()-1 && "
-         "TTCN_Logger::log_this_event(TTCN_WARNING)) {\n"
-       "ttcn_buffer.cut();\n"
-       "%s remaining_stream;\n"
-       "ttcn_buffer.get_string(remaining_stream);\n"
-       "TTCN_Logger::begin_event(TTCN_WARNING);\n"
-       "TTCN_Logger::log_event_str(\"%s(): Warning: Data remained at the end "
-         "of the stream after successful decoding: \");\n"
-       "remaining_stream.log();\n"
-       "TTCN_Logger::end_event();\n"
-       "}\n", input_type->get_genname_value(my_scope).c_str(), function_name);
+          "TTCN_EncDec::ET_NONE) {\n"
+        "if (ttcn_buffer.get_pos() < ttcn_buffer.get_len()-1 && "
+          "TTCN_Logger::log_this_event(TTCN_WARNING)) {\n"
+        "ttcn_buffer.cut();\n"
+        "%s remaining_stream;\n"
+        "ttcn_buffer.get_string(remaining_stream);\n"
+        "TTCN_Logger::begin_event(TTCN_WARNING);\n"
+        "TTCN_Logger::log_event_str(\"%s(): Warning: Data remained at the end "
+          "of the stream after successful decoding: \");\n"
+        "remaining_stream.log();\n"
+        "TTCN_Logger::end_event();\n"
+        "}\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");
+        str = mputstr(str, "return 0;\n"
+          "} else return 1;\n");
       } else {
-       str = mputstr(str, "}\n");
-       if (prototype == PROTOTYPE_CONVERT)
+        str = mputstr(str, "}\n");
+        if (prototype == PROTOTYPE_CONVERT)
           str = mputstr(str, "return ret_val;\n");
       }
     } else {
       // result handling and debug printout for sliding decoders
       str = mputprintf(str, "switch (TTCN_EncDec::get_last_error_type()) {\n"
-       "case TTCN_EncDec::ET_NONE:\n"
-       // TTCN_Buffer::get_string will call OCTETSTRING::clean_up()
-       "ttcn_buffer.cut();\n"
-       "ttcn_buffer.get_string(%s);\n"
-       "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
-       "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
-       "TTCN_Logger::log_event_str(\"%s(): Stream after decoding: \");\n"
-       "%s.log();\n"
-       "TTCN_Logger::end_event();\n"
-       "}\n"
-       "return 0;\n"
+        "case TTCN_EncDec::ET_NONE:\n"
+        // TTCN_Buffer::get_string will call OCTETSTRING::clean_up()
+        "ttcn_buffer.cut();\n"
+        "ttcn_buffer.get_string(%s);\n"
+        "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
+        "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
+        "TTCN_Logger::log_event_str(\"%s(): Stream after decoding: \");\n"
+        "%s.log();\n"
+        "TTCN_Logger::end_event();\n"
+        "}\n"
+        "return 0;\n"
         "case TTCN_EncDec::ET_INCOMPL_MSG:\n"
-       "case TTCN_EncDec::ET_LEN_ERR:\n"
-       "return 2;\n"
-       "default:\n"
-       "return 1;\n"
-       "}\n", first_par_name, function_name, first_par_name);
+        "case TTCN_EncDec::ET_LEN_ERR:\n"
+        "return 2;\n"
+        "default:\n"
+        "return 1;\n"
+        "}\n", first_par_name, function_name, first_par_name);
     }
     return str;
   }
@@ -6631,7 +6646,7 @@ namespace Ttcn {
     // function prototype
     target->header.function_prototypes =
       mputprintf(target->header.function_prototypes, "extern %s %s(%s);\n",
-       return_type_str, genname_str, formal_par_list);
+        return_type_str, genname_str, formal_par_list);
 
     if (function_type != EXTFUNC_MANUAL) {
       // function body written by the compiler
@@ -6641,22 +6656,22 @@ namespace Ttcn {
         , __FUNCTION__, __LINE__);
 #endif
       body = mputprintf(body,
-       "%s %s(%s)\n"
-       "{\n"
-       , return_type_str, genname_str, formal_par_list);
+        "%s %s(%s)\n"
+        "{\n"
+        , return_type_str, genname_str, formal_par_list);
       switch (function_type) {
       case EXTFUNC_ENCODE:
         body = generate_code_encode(body);
-       break;
+        break;
       case EXTFUNC_DECODE:
         body = generate_code_decode(body);
-       break;
+        break;
       default:
         FATAL_ERROR("Def_ExtFunction::generate_code()");
       }
       body = mputstr(body, "}\n\n");
       target->source.function_bodies = mputstr(target->source.function_bodies,
-       body);
+        body);
       Free(body);
     }
 
@@ -6685,11 +6700,11 @@ namespace Ttcn {
       DEBUG(level + 1, "Prototype: %s", get_prototype_name());
     if (function_type != EXTFUNC_MANUAL) {
       DEBUG(level + 1, "Automatically generated: %s",
-       function_type == EXTFUNC_ENCODE ? "encoder" : "decoder");
+        function_type == EXTFUNC_ENCODE ? "encoder" : "decoder");
       DEBUG(level + 2, "Encoding type: %s",
-       Type::get_encoding_name(encoding_type));
+        Type::get_encoding_name(encoding_type));
       if (encoding_options)
-       DEBUG(level + 2, "Encoding options: %s", encoding_options->c_str());
+        DEBUG(level + 2, "Encoding options: %s", encoding_options->c_str());
     }
     if (eb_list) eb_list->dump(level + 1);
   }
@@ -6925,7 +6940,7 @@ namespace Ttcn {
     // function for altstep instance: prototype
     target->header.function_prototypes =
       mputprintf(target->header.function_prototypes,
-       "extern alt_status %s_instance(%s);\n", genname_str, formal_par_list);
+        "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"
@@ -6945,34 +6960,34 @@ namespace Ttcn {
     // 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, formal_par_list);
 
     // wrapper function for stand-alone instantiation: body
     target->source.function_bodies =
       mputprintf(target->source.function_bodies, "void %s(%s)\n"
-       "{\n"
-       "altstep_begin:\n"
-       "boolean block_flag = FALSE;\n"
-       "alt_status altstep_flag = ALT_UNCHECKED, "
-       "default_flag = ALT_UNCHECKED;\n"
-       "for ( ; ; ) {\n"
-       "TTCN_Snapshot::take_new(block_flag);\n"
-       "if (altstep_flag != ALT_NO) {\n"
-       "altstep_flag = %s_instance(%s);\n"
-       "if (altstep_flag == ALT_YES || altstep_flag == ALT_BREAK) return;\n"
-       "else if (altstep_flag == ALT_REPEAT) goto altstep_begin;\n"
-       "}\n"
-       "if (default_flag != ALT_NO) {\n"
-       "default_flag = TTCN_Default::try_altsteps();\n"
-       "if (default_flag == ALT_YES || default_flag == ALT_BREAK) return;\n"
-       "else if (default_flag == ALT_REPEAT) goto altstep_begin;\n"
-       "}\n"
-       "if (altstep_flag == ALT_NO && default_flag == ALT_NO) "
-       "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,
-       dispname_str);
+        "{\n"
+        "altstep_begin:\n"
+        "boolean block_flag = FALSE;\n"
+        "alt_status altstep_flag = ALT_UNCHECKED, "
+        "default_flag = ALT_UNCHECKED;\n"
+        "for ( ; ; ) {\n"
+        "TTCN_Snapshot::take_new(block_flag);\n"
+        "if (altstep_flag != ALT_NO) {\n"
+        "altstep_flag = %s_instance(%s);\n"
+        "if (altstep_flag == ALT_YES || altstep_flag == ALT_BREAK) return;\n"
+        "else if (altstep_flag == ALT_REPEAT) goto altstep_begin;\n"
+        "}\n"
+        "if (default_flag != ALT_NO) {\n"
+        "default_flag = TTCN_Default::try_altsteps();\n"
+        "if (default_flag == ALT_YES || default_flag == ALT_BREAK) return;\n"
+        "else if (default_flag == ALT_REPEAT) goto altstep_begin;\n"
+        "}\n"
+        "if (altstep_flag == ALT_NO && default_flag == ALT_NO) "
+        "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,
+        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
@@ -6987,11 +7002,11 @@ namespace Ttcn {
     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,
-       dispname_str);
+        " : Default_Base(\"%s\")", genname_str, genname_str, formal_par_list,
+        dispname_str);
     for (size_t i = 0; i < fp_list->get_nof_fps(); i++) {
       const char *fp_name_str =
-       fp_list->get_fp_byIndex(i)->get_id().get_name().c_str();
+        fp_list->get_fp_byIndex(i)->get_id().get_name().c_str();
       str = mputprintf(str, ", par_%s(%s)", fp_name_str, fp_name_str);
     }
     str = mputstr(str, "\n{\n}\n\n");
@@ -7008,8 +7023,8 @@ namespace Ttcn {
     // function for default activation: prototype
     target->header.function_prototypes =
       mputprintf(target->header.function_prototypes,
-       "extern Default_Base *activate_%s(%s);\n", genname_str,
-       formal_par_list);
+        "extern Default_Base *activate_%s(%s);\n", genname_str,
+        formal_par_list);
 
     // function for default activation: body
     str = mprintf("Default_Base *activate_%s(%s)\n"
@@ -7025,7 +7040,7 @@ namespace Ttcn {
 
     target->functions.pre_init = mputprintf(target->functions.pre_init,
       "%s.add_altstep(\"%s\", (genericfunc_t)&%s_instance, (genericfunc_t )&activate_%s, "
-       "(genericfunc_t )&%s);\n", get_module_object_name(), dispname_str, genname_str,
+        "(genericfunc_t )&%s);\n", get_module_object_name(), dispname_str, genname_str,
       genname_str, genname_str);
   }
 
@@ -7179,7 +7194,7 @@ namespace Ttcn {
     // function prototype
     target->header.function_prototypes =
       mputprintf(target->header.function_prototypes,
-       "extern verdicttype testcase_%s(%s);\n", genname_str, formal_par_list);
+        "extern verdicttype testcase_%s(%s);\n", genname_str, formal_par_list);
 
     // function body
     char *body = mprintf("verdicttype testcase_%s(%s)\n"
@@ -7189,7 +7204,7 @@ namespace Ttcn {
     // 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, "
-       "timer_value);\n");
+        "timer_value);\n");
     body = create_location_object(body, "TESTCASE", dispname_str);
     body = fp_list->generate_shadow_objects(body);
     body = mputprintf(body, "try {\n"
@@ -7218,8 +7233,8 @@ namespace Ttcn {
     if (fp_list->get_nof_fps() == 0) {
       // adding to the list of startable testcases
       target->functions.pre_init = mputprintf(target->functions.pre_init,
-       "%s.add_testcase_nonpard(\"%s\", testcase_%s);\n",
-       get_module_object_name(), dispname_str, genname_str);
+        "%s.add_testcase_nonpard(\"%s\", testcase_%s);\n",
+        get_module_object_name(), dispname_str, genname_str);
     } else {
       target->functions.pre_init = mputprintf(target->functions.pre_init,
         "%s.add_testcase_pard(\"%s\", (genericfunc_t)&testcase_%s);\n",
@@ -7441,36 +7456,36 @@ namespace Ttcn {
       switch (t->get_typetype()) {
       case Type::T_PORT:
         switch (asstype) {
-       case A_PAR_VAL:
-       case A_PAR_VAL_INOUT:
-         asstype = A_PAR_PORT;
-         break;
-       default:
-         error("Port type `%s' cannot be used as %s",
-           t->get_fullname().c_str(), get_assname());
-       }
-       break;
+        case A_PAR_VAL:
+        case A_PAR_VAL_INOUT:
+          asstype = A_PAR_PORT;
+          break;
+        default:
+          error("Port type `%s' cannot be used as %s",
+            t->get_fullname().c_str(), get_assname());
+        }
+        break;
       case Type::T_SIGNATURE:
         switch (asstype) {
-       case A_PAR_TEMPL_IN:
-       case A_PAR_TEMPL_OUT:
-       case A_PAR_TEMPL_INOUT:
-         break;
-       default:
-         error("Signature `%s' cannot be used as %s",
-           t->get_fullname().c_str(), get_assname());
-       }
-       break;
+        case A_PAR_TEMPL_IN:
+        case A_PAR_TEMPL_OUT:
+        case A_PAR_TEMPL_INOUT:
+          break;
+        default:
+          error("Signature `%s' cannot be used as %s",
+            t->get_fullname().c_str(), get_assname());
+        }
+        break;
       default:
         switch (asstype) {
-       case A_PAR_PORT:
-       case A_PAR_TIMER:
-         FATAL_ERROR("FormalPar::chk()");
-       case A_PAR_VAL:
-         asstype = A_PAR_VAL_IN;
-       default:
+        case A_PAR_PORT:
+        case A_PAR_TIMER:
+          FATAL_ERROR("FormalPar::chk()");
+        case A_PAR_VAL:
+          asstype = A_PAR_VAL_IN;
+        default:
           break;
-       }
+        }
       }
     } else if (asstype != A_PAR_TIMER) FATAL_ERROR("FormalPar::chk()");
 
@@ -7479,7 +7494,7 @@ namespace Ttcn {
       defval.ap = chk_actual_par(default_value, Type::EXPECTED_STATIC_VALUE);
       delete default_value;
       if (!semantic_check_only)
-       defval.ap->set_code_section(GovernedSimple::CS_POST_INIT);
+        defval.ap->set_code_section(GovernedSimple::CS_POST_INIT);
     }
   }
 
@@ -7583,7 +7598,7 @@ namespace Ttcn {
       return new ActualPar(v);
     } else {
       actual_par->error("A specific value without matching symbols "
-       "was expected for a %s", get_assname());
+        "was expected for a %s", get_assname());
       return new ActualPar();
     }
   }
@@ -7785,13 +7800,13 @@ namespace Ttcn {
     Type *ap_type = actual_par->get_Type();
     if (ap_type) {
       ap_type->warning("Explicit type specification is useless for an %s",
-       get_assname());
+        get_assname());
       actual_par->chk_Type(type);
     }
     Ref_base *derived_ref = actual_par->get_DerivedRef();
     if (derived_ref) {
       derived_ref->error("An in-line modified template cannot be used as %s",
-       get_assname());
+        get_assname());
       actual_par->chk_DerivedRef(type);
     }
     // needed for the error messages
@@ -7803,59 +7818,59 @@ namespace Ttcn {
       Ref_base *ref = ap_template->get_Ref();
       Common::Assignment *ass = ref->get_refd_assignment();
       if (!ass) {
-       delete ref;
-       return new ActualPar();
+        delete ref;
+        return new ActualPar();
       }
       bool asstype_correct = false;
       switch (ass->get_asstype()) {
       case A_PAR_VAL_IN:
-       ass->use_as_lvalue(*ref);
-       if (get_asstype() == A_PAR_VAL_OUT || get_asstype() == A_PAR_TEMPL_OUT) {
-         ass->warning("Passing an `in' parameter as another function's `out' parameter");
-       }
-       // no break
+        ass->use_as_lvalue(*ref);
+        if (get_asstype() == A_PAR_VAL_OUT || get_asstype() == A_PAR_TEMPL_OUT) {
+          ass->warning("Passing an `in' parameter as another function's `out' parameter");
+        }
+        // no break
       case A_VAR:
       case A_PAR_VAL_OUT:
       case A_PAR_VAL_INOUT:
         if (!is_template) asstype_correct = true;
-       break;
+        break;
       case A_PAR_TEMPL_IN:
-       ass->use_as_lvalue(*ref);
-       if (get_asstype() == A_PAR_VAL_OUT || get_asstype() == A_PAR_TEMPL_OUT) {
-         ass->warning("Passing an `in' parameter as another function's `out' parameter");
-       }
-       // no break
+        ass->use_as_lvalue(*ref);
+        if (get_asstype() == A_PAR_VAL_OUT || get_asstype() == A_PAR_TEMPL_OUT) {
+          ass->warning("Passing an `in' parameter as another function's `out' parameter");
+        }
+        // no break
       case A_VAR_TEMPLATE:
       case A_PAR_TEMPL_OUT:
       case A_PAR_TEMPL_INOUT:
         if (is_template) asstype_correct = true;
-       break;
+        break;
       default:
-       break;
+        break;
       }
       if (asstype_correct) {
-       FieldOrArrayRefs *t_subrefs = ref->get_subrefs();
-       Type *ref_type = ass->get_Type()->get_field_type(t_subrefs, exp_val);
-       if (ref_type) {
-         if (!type->is_identical(ref_type)) {
-           ref->error("Type mismatch: Reference to a %s of type "
-             "`%s' was expected instead of `%s'", expected_string,
-             type->get_typename().c_str(), ref_type->get_typename().c_str());
-         } else if (type->get_sub_type() && ref_type->get_sub_type() &&
+        FieldOrArrayRefs *t_subrefs = ref->get_subrefs();
+        Type *ref_type = ass->get_Type()->get_field_type(t_subrefs, exp_val);
+        if (ref_type) {
+          if (!type->is_identical(ref_type)) {
+            ref->error("Type mismatch: Reference to a %s of type "
+              "`%s' was expected instead of `%s'", expected_string,
+              type->get_typename().c_str(), ref_type->get_typename().c_str());
+          } else if (type->get_sub_type() && ref_type->get_sub_type() &&
       (type->get_sub_type()->get_subtypetype()==ref_type->get_sub_type()->get_subtypetype()) &&
       (!type->get_sub_type()->is_compatible(ref_type->get_sub_type()))) {
         ref->error("Subtype mismatch: subtype %s has no common value with subtype %s",
                    type->get_sub_type()->to_string().c_str(),
                    ref_type->get_sub_type()->to_string().c_str());
     }
-         if (t_subrefs && t_subrefs->refers_to_string_element()) {
-           ref->error("Reference to a string element of type `%s' cannot be "
-             "used in this context", ref_type->get_typename().c_str());
-         }
-       }
+          if (t_subrefs && t_subrefs->refers_to_string_element()) {
+            ref->error("Reference to a string element of type `%s' cannot be "
+              "used in this context", ref_type->get_typename().c_str());
+          }
+        }
       } else {
         ref->error("Reference to a %s was expected for an %s instead of %s",
-         expected_string, get_assname(), ass->get_description().c_str());
+          expected_string, get_assname(), ass->get_description().c_str());
       }
       ActualPar* ret_val_ap = new ActualPar(ref);
       // restriction checking if this is a reference to a template variable
@@ -7938,24 +7953,24 @@ namespace Ttcn {
       Ref_base *ref = ap_template->get_Ref();
       Common::Assignment *ass = ref->get_refd_assignment();
       if (!ass) {
-       delete ref;
-       return new ActualPar();
+        delete ref;
+        return new ActualPar();
       }
       switch (ass->get_asstype()) {
       case A_TIMER: {
         ArrayDimensions *dims = ass->get_Dimensions();
-       if (dims) dims->chk_indices(ref, "timer", false, exp_val);
-       else if (ref->get_subrefs()) ref->error("Reference to single %s "
-         "cannot have field or array sub-references",
-         ass->get_description().c_str());
-       break; }
+        if (dims) dims->chk_indices(ref, "timer", false, exp_val);
+        else if (ref->get_subrefs()) ref->error("Reference to single %s "
+          "cannot have field or array sub-references",
+          ass->get_description().c_str());
+        break; }
       case A_PAR_TIMER:
         if (ref->get_subrefs()) ref->error("Reference to %s cannot have "
-         "field or array sub-references", ass->get_description().c_str());
-       break;
+          "field or array sub-references", ass->get_description().c_str());
+        break;
       default:
         ref->error("Reference to a timer or timer parameter was expected for "
-         "a timer parameter instead of %s", ass->get_description().c_str());
+          "a timer parameter instead of %s", ass->get_description().c_str());
       }
       return new ActualPar(ref);
     } else {
@@ -7985,34 +8000,34 @@ namespace Ttcn {
       Ref_base *ref = ap_template->get_Ref();
       Common::Assignment *ass = ref->get_refd_assignment();
       if (!ass) {
-       delete ref;
-       return new ActualPar();
+        delete ref;
+        return new ActualPar();
       }
       bool asstype_correct = false;
       switch (ass->get_asstype()) {
       case A_PORT: {
         ArrayDimensions *dims = ass->get_Dimensions();
-       if (dims) dims->chk_indices(ref, "port", false, exp_val);
-       else if (ref->get_subrefs()) ref->error("Reference to single %s "
-         "cannot have field or array sub-references",
-         ass->get_description().c_str());
+        if (dims) dims->chk_indices(ref, "port", false, exp_val);
+        else if (ref->get_subrefs()) ref->error("Reference to single %s "
+          "cannot have field or array sub-references",
+          ass->get_description().c_str());
         asstype_correct = true;
-       break; }
+        break; }
       case A_PAR_PORT:
         if (ref->get_subrefs()) ref->error("Reference to %s cannot have "
-         "field or array sub-references", ass->get_description().c_str());
+          "field or array sub-references", ass->get_description().c_str());
         asstype_correct = true;
-       break;
+        break;
       default:
         ref->error("Reference to a port or port parameter was expected for a "
-         "port parameter instead of %s", ass->get_description().c_str());
+          "port parameter instead of %s", ass->get_description().c_str());
       }
       if (asstype_correct) {
-       Type *ref_type = ass->get_Type();
-       if (ref_type && !type->is_identical(ref_type))
-         ref->error("Type mismatch: Reference to a port or port parameter "
-           "of type `%s' was expected instead of `%s'",
-           type->get_typename().c_str(), ref_type->get_typename().c_str());
+        Type *ref_type = ass->get_Type();
+        if (ref_type && !type->is_identical(ref_type))
+          ref->error("Type mismatch: Reference to a port or port parameter "
+            "of type `%s' was expected instead of `%s'",
+            type->get_typename().c_str(), ref_type->get_typename().c_str());
       }
       return new ActualPar(ref);
     } else {
@@ -8035,15 +8050,15 @@ namespace Ttcn {
       Definition *my_def = my_parlist->get_my_def();
       if (!my_def) FATAL_ERROR("FormalPar::use_as_lvalue()");
       if (my_def->get_asstype() == A_TEMPLATE)
-       p_loc.error("Parameter `%s' of the template cannot be passed further "
-         "as `out' or `inout' parameter", id->get_dispname().c_str());
+        p_loc.error("Parameter `%s' of the template cannot be passed further "
+          "as `out' or `inout' parameter", id->get_dispname().c_str());
       else {
-       // update the genname so that all references in the generated code
-       // will point to the shadow object
+        // update the genname so that all references in the generated code
+        // will point to the shadow object
   if (!lazy_eval) {
-         set_genname(id->get_name() + "_shadow");
+          set_genname(id->get_name() + "_shadow");
   }
-       used_as_lvalue = true;
+        used_as_lvalue = true;
       }
     }
   }
@@ -8122,7 +8137,7 @@ namespace Ttcn {
     case A_PAR_VAL_INOUT:
     case A_PAR_PORT:
       str = mputprintf(str, "%s& %s", type->get_genname_value(my_scope).c_str(),
-       name_str);
+        name_str);
       break;
     case A_PAR_TEMPL_IN:
       if (lazy_eval) {
@@ -8134,7 +8149,7 @@ namespace Ttcn {
     case A_PAR_TEMPL_OUT:
     case A_PAR_TEMPL_INOUT:
       str = mputprintf(str, "%s& %s",
-       type->get_genname_template(my_scope).c_str(), name_str);
+        type->get_genname_template(my_scope).c_str(), name_str);
       break;
     case A_PAR_TIMER:
       str = mputprintf(str, "TIMER& %s", name_str);
@@ -8182,7 +8197,7 @@ namespace Ttcn {
     case A_PAR_VAL_INOUT:
     case A_PAR_PORT:
       str = mputprintf(str, "%s%c %s%s;\n",
-       type->get_genname_value(my_scope).c_str(), refch, p_prefix, name_str);
+        type->get_genname_value(my_scope).c_str(), refch, p_prefix, name_str);
       break;
     case A_PAR_TEMPL_IN:
       if (lazy_eval) {
@@ -8194,7 +8209,7 @@ namespace Ttcn {
     case A_PAR_TEMPL_OUT:
     case A_PAR_TEMPL_INOUT:
       str = mputprintf(str, "%s%c %s%s;\n",
-       type->get_genname_template(my_scope).c_str(), refch, p_prefix, name_str);
+        type->get_genname_template(my_scope).c_str(), refch, p_prefix, name_str);
       break;
     case A_PAR_TIMER:
       str = mputprintf(str, "TIMER& %s%s;\n", p_prefix, name_str);
@@ -8213,15 +8228,15 @@ namespace Ttcn {
       const char *name_str = id->get_name().c_str();
       switch (asstype) {
       case A_PAR_VAL_IN:
-       str = mputprintf(str, "%s %s(%s);\n",
-         type->get_genname_value(my_scope).c_str(), genname_str, name_str);
-       break;
+        str = mputprintf(str, "%s %s(%s);\n",
+          type->get_genname_value(my_scope).c_str(), genname_str, name_str);
+        break;
       case A_PAR_TEMPL_IN:
-       str = mputprintf(str, "%s %s(%s);\n",
-         type->get_genname_template(my_scope).c_str(), genname_str, name_str);
-       break;
+        str = mputprintf(str, "%s %s(%s);\n",
+          type->get_genname_template(my_scope).c_str(), genname_str, name_str);
+        break;
       default:
-       FATAL_ERROR("FormalPar::generate_shadow_object()");
+        FATAL_ERROR("FormalPar::generate_shadow_object()");
       }
     }
     return str;
@@ -8362,27 +8377,27 @@ namespace Ttcn {
       FormalPar *par = pars_v[i];
       const string& par_name = par->get_id().get_name();
       if (par->get_asstype() != Definition::A_PAR_TIMER)
-       par->get_Type()->set_genname(p_prefix, par_name);
+        par->get_Type()->set_genname(p_prefix, par_name);
       if (par->has_defval()) {
-       string embedded_genname(p_prefix);
-       embedded_genname += '_';
-       embedded_genname += par_name;
-       embedded_genname += "_defval";
+        string embedded_genname(p_prefix);
+        embedded_genname += '_';
+        embedded_genname += par_name;
+        embedded_genname += "_defval";
         ActualPar *defval = par->get_defval();
         switch (defval->get_selection()) {
         case ActualPar::AP_ERROR:
         case ActualPar::AP_REF:
           break;
         case ActualPar::AP_VALUE: {
-         Value *v = defval->get_Value();
+          Value *v = defval->get_Value();
           v->set_genname_prefix("const_");
-         v->set_genname_recursive(embedded_genname);
+          v->set_genname_recursive(embedded_genname);
           break; }
         case ActualPar::AP_TEMPLATE: {
-         Template *t = defval->get_TemplateInstance()->get_Template();
-         t->set_genname_prefix("template_");
-         t->set_genname_recursive(embedded_genname);
-         break; }
+          Template *t = defval->get_TemplateInstance()->get_Template();
+          t->set_genname_prefix("template_");
+          t->set_genname_recursive(embedded_genname);
+          break; }
         default:
           FATAL_ERROR("FormalParList::set_genname()");
         }
@@ -8403,19 +8418,19 @@ namespace Ttcn {
       const string& name = id.get_name();
       const char *dispname = id.get_dispname().c_str();
       if (pars_m.has_key(name)) {
-       par->error("Duplicate parameter with name `%s'", dispname);
-       pars_m[name]->note("Previous definition of `%s' is here", dispname);
+        par->error("Duplicate parameter with name `%s'", dispname);
+        pars_m[name]->note("Previous definition of `%s' is here", dispname);
       } else {
-       pars_m.add(name, par);
-       if (parent_scope && parent_scope->has_ass_withId(id)) {
-         par->error("Parameter name `%s' is not unique in the scope "
-           "hierarchy", dispname);
-         Reference ref(0, id.clone());
-         Common::Assignment *ass = parent_scope->get_ass_bySRef(&ref);
-         if (!ass) FATAL_ERROR("FormalParList::chk()");
-         ass->note("Symbol `%s' is already defined here in a higher scope "
-           "unit", dispname);
-       }
+        pars_m.add(name, par);
+        if (parent_scope && parent_scope->has_ass_withId(id)) {
+          par->error("Parameter name `%s' is not unique in the scope "
+            "hierarchy", dispname);
+          Reference ref(0, id.clone());
+          Common::Assignment *ass = parent_scope->get_ass_bySRef(&ref);
+          if (!ass) FATAL_ERROR("FormalParList::chk()");
+          ass->note("Symbol `%s' is already defined here in a higher scope "
+            "unit", dispname);
+        }
       }
       Error_Context cntxt2(par, "In parameter `%s'", dispname);
       par->chk();
@@ -8423,23 +8438,23 @@ namespace Ttcn {
       switch (deftype) {
       case Definition::A_TEMPLATE:
         switch (par->get_asstype()) {
-       case Definition::A_PAR_VAL_IN:
-       case Definition::A_PAR_TEMPL_IN:
-         // these are allowed
+        case Definition::A_PAR_VAL_IN:
+        case Definition::A_PAR_TEMPL_IN:
+          // these are allowed
           break;
-       default:
+        default:
           par->error("A template cannot have %s", par->get_assname());
-       }
-       break;
+        }
+        break;
       case Definition::A_TESTCASE:
         switch (par->get_asstype()) {
-       case Definition::A_PAR_TIMER:
-       case Definition::A_PAR_PORT:
-         // these are forbidden
+        case Definition::A_PAR_TIMER:
+        case Definition::A_PAR_PORT:
+          // these are forbidden
           par->error("A testcase cannot have %s", par->get_assname());
-       default:
+        default:
           break;
-       }
+        }
       default:
         // everything is allowed for functions and altsteps
         break;
@@ -8497,7 +8512,7 @@ namespace Ttcn {
         break;
       default:
         par->error("%s `%s' cannot be started on a parallel test component "
-         "because it has %s", p_what, p_name, par->get_description().c_str());
+          "because it has %s", p_what, p_name, par->get_description().c_str());
       }
     }
   }
@@ -8510,8 +8525,8 @@ namespace Ttcn {
     // check for the number of parameters
     if (nof_type_pars != nof_function_pars) {
       p_fp_list->error("Too %s parameters: %lu was expected instead of %lu",
-       nof_type_pars < nof_function_pars ? "many" : "few",
-       (unsigned long) nof_type_pars, (unsigned long) nof_function_pars);
+        nof_type_pars < nof_function_pars ? "many" : "few",
+        (unsigned long) nof_type_pars, (unsigned long) nof_function_pars);
     }
     size_t upper_limit =
       nof_type_pars < nof_function_pars ? nof_type_pars : nof_function_pars;
@@ -8525,21 +8540,21 @@ namespace Ttcn {
       // check for parameter kind equivalence
       // (in, out or inout / value or template)
       if (type_par_asstype != function_par_asstype) {
-       function_par->error("The kind of the parameter is not the same as in "
-         "type `%s': %s was expected instead of %s", where,
-         type_par->get_assname(), function_par->get_assname());
+        function_par->error("The kind of the parameter is not the same as in "
+          "type `%s': %s was expected instead of %s", where,
+          type_par->get_assname(), function_par->get_assname());
       }
       // check for type equivalence
       if (type_par_asstype != FormalPar::A_PAR_TIMER &&
-         function_par_asstype != FormalPar::A_PAR_TIMER) {
-       Type *type_par_type = type_par->get_Type();
-       Type *function_par_type = function_par->get_Type();
-       if (!type_par_type->is_identical(function_par_type)) {
-         function_par_type->error("The type of the parameter is not the same "
-           "as in type `%s': `%s' was expected instead of `%s'", where,
-           type_par_type->get_typename().c_str(),
-           function_par_type->get_typename().c_str());
-       } else if (type_par_type->get_sub_type() && function_par_type->get_sub_type() &&
+          function_par_asstype != FormalPar::A_PAR_TIMER) {
+        Type *type_par_type = type_par->get_Type();
+        Type *function_par_type = function_par->get_Type();
+        if (!type_par_type->is_identical(function_par_type)) {
+          function_par_type->error("The type of the parameter is not the same "
+            "as in type `%s': `%s' was expected instead of `%s'", where,
+            type_par_type->get_typename().c_str(),
+            function_par_type->get_typename().c_str());
+        } else if (type_par_type->get_sub_type() && function_par_type->get_sub_type() &&
         (type_par_type->get_sub_type()->get_subtypetype()==function_par_type->get_sub_type()->get_subtypetype()) &&
         (!type_par_type->get_sub_type()->is_compatible(function_par_type->get_sub_type()))) {
     // TODO: maybe equivalence should be checked, or maybe that is too strict
@@ -8555,7 +8570,7 @@ namespace Ttcn {
         function_par->error("The template restriction of the parameter is "
           "not the same as in type `%s': %s restriction was expected instead "
           "of %s restriction", where,
-         type_par->get_template_restriction()==TR_NONE ? "no" :
+          type_par->get_template_restriction()==TR_NONE ? "no" :
           Template::get_restriction_name(type_par->get_template_restriction()),
           function_par->get_template_restriction()==TR_NONE ? "no" :
           Template::get_restriction_name(function_par->
@@ -8569,10 +8584,10 @@ namespace Ttcn {
       const Identifier& type_par_id = type_par->get_id();
       const Identifier& function_par_id = function_par->get_id();
       if (type_par_id != function_par_id) {
-       function_par->warning("The name of the parameter is not the same "
-         "as in type `%s': `%s' was expected instead of `%s'", where,
-         type_par_id.get_dispname().c_str(),
-         function_par_id.get_dispname().c_str());
+        function_par->warning("The name of the parameter is not the same "
+          "as in type `%s': `%s' was expected instead of `%s'", where,
+          type_par_id.get_dispname().c_str(),
+          function_par_id.get_dispname().c_str());
       }
     }
   }
@@ -8600,82 +8615,82 @@ namespace Ttcn {
       // We are now responsible for np.
 
       if (has_fp_withName(*np->get_name())) {
-       // there is a formal parameter with that name
-       FormalPar *fp = get_fp_byName(*np->get_name());
-       const size_t is_at = *formalpar_map[fp]; // the index of the formal par
-       if (is_at >= num_actual) {
-         // There is no actual par in the unnamed part.
-         // Create one from the named param.
-
-         // First, pad the gap with '-'
-         for (; num_actual < is_at; ++num_actual) {
-           Template *not_used;
-           if (pars_v[num_actual]->has_defval()) {
-             not_used = new Template(Template::TEMPLATE_NOTUSED);
-           }
-           else { // cannot use '-' if no default value
-             not_used = new Template(Template::TEMPLATE_ERROR);
-           }
-           TemplateInstance *new_ti = new TemplateInstance(0, 0, not_used);
-           // Conjure a location info at the beginning of the unnamed part
-           // (that is, the beginning of the actual parameter list)
-           new_ti->set_location(p_paps->get_tis()->get_filename(),
-             p_paps->get_tis()->get_first_line(),
-             p_paps->get_tis()->get_first_column(), 0, 0);
-           p_paps->get_tis()->add_ti(new_ti);
-         }
-         TemplateInstance * namedti = np->extract_ti();
-         p_paps->get_tis()->add_ti(namedti);
-         ++num_actual;
-       } else {
-         // There is already an actual par at that position, fetch it
-         TemplateInstance * ti = p_paps->get_tis()->get_ti_byIndex(is_at);
-         Template::templatetype_t tt = ti->get_Template()->get_templatetype();
-
-         if (is_at >= num_unnamed && !ti->get_Type() && !ti->get_DerivedRef()
-           && (tt == Template::TEMPLATE_NOTUSED || tt == Template::TEMPLATE_ERROR)) {
-           // NotUsed in the named part => padding
-           np->error("Named parameter `%s' out of order",
-             np->get_name()->get_dispname().c_str());
-         } else {
-           // attempt to override an original unnamed param with a named one
-           np->error("Formal parameter `%s' assigned more than once",
-             np->get_name()->get_dispname().c_str());
-         }
-       }
+              // there is a formal parameter with that name
+        FormalPar *fp = get_fp_byName(*np->get_name());
+        const size_t is_at = *formalpar_map[fp]; // the index of the formal par
+        if (is_at >= num_actual) {
+          // There is no actual par in the unnamed part.
+          // Create one from the named param.
+
+          // First, pad the gap with '-'
+          for (; num_actual < is_at; ++num_actual) {
+            Template *not_used;
+            if (pars_v[num_actual]->has_defval()) {
+              not_used = new Template(Template::TEMPLATE_NOTUSED);
+            }
+            else { // cannot use '-' if no default value
+              not_used = new Template(Template::TEMPLATE_ERROR);
+            }
+            TemplateInstance *new_ti = new TemplateInstance(0, 0, not_used);
+            // Conjure a location info at the beginning of the unnamed part
+            // (that is, the beginning of the actual parameter list)
+            new_ti->set_location(p_paps->get_tis()->get_filename(),
+              p_paps->get_tis()->get_first_line(),
+              p_paps->get_tis()->get_first_column(), 0, 0);
+            p_paps->get_tis()->add_ti(new_ti);
+          }
+          TemplateInstance * namedti = np->extract_ti();
+          p_paps->get_tis()->add_ti(namedti);
+          ++num_actual;
+        } else {
+          // There is already an actual par at that position, fetch it
+          TemplateInstance * ti = p_paps->get_tis()->get_ti_byIndex(is_at);
+          Template::templatetype_t tt = ti->get_Template()->get_templatetype();
+
+          if (is_at >= num_unnamed && !ti->get_Type() && !ti->get_DerivedRef()
+            && (tt == Template::TEMPLATE_NOTUSED || tt == Template::TEMPLATE_ERROR)) {
+            // NotUsed in the named part => padding
+            np->error("Named parameter `%s' out of order",
+              np->get_name()->get_dispname().c_str());
+          } else {
+            // attempt to override an original unnamed param with a named one
+            np->error("Formal parameter `%s' assigned more than once",
+              np->get_name()->get_dispname().c_str());
+          }
+        }
       }
       else { // no formal parameter with that name
-       char * nam = 0;
-       switch (my_def->get_asstype()) {
-       case Common::Assignment::A_TYPE: {
-         Type *t = my_def->get_Type();
-
-         switch (t ? t->get_typetype() : 0) {
-         case Type::T_FUNCTION:
-           nam = mcopystr("Function reference");
-           break;
-         case Type::T_ALTSTEP:
-           nam = mcopystr("Altstep reference");
-           break;
-         case Type::T_TESTCASE:
-           nam = mcopystr("Testcase reference");
-           break;
-         default:
-           FATAL_ERROR("FormalParList::chk_actual_parlist() "
-                       "Unexpected type %s", t->get_typename().c_str());
-         } // switch(typetype)
-         break; }
-       default:
-         nam = mcopystr(my_def->get_assname());
-         break;
-       } // switch(asstype)
-
-       *nam &= ~('a'-'A'); // Make the first letter uppercase
-       p_paps->get_tis()->error("%s `%s' has no formal parameter `%s'",
-         nam,
-         my_def->get_fullname().c_str(),
-         np->get_name()->get_dispname().c_str());
-       Free(nam);
+        char * nam = 0;
+        switch (my_def->get_asstype()) {
+        case Common::Assignment::A_TYPE: {
+          Type *t = my_def->get_Type();
+
+          switch (t ? t->get_typetype() : 0) {
+          case Type::T_FUNCTION:
+            nam = mcopystr("Function reference");
+            break;
+          case Type::T_ALTSTEP:
+            nam = mcopystr("Altstep reference");
+            break;
+          case Type::T_TESTCASE:
+            nam = mcopystr("Testcase reference");
+            break;
+          default:
+            FATAL_ERROR("FormalParList::chk_actual_parlist() "
+                        "Unexpected type %s", t->get_typename().c_str());
+          } // switch(typetype)
+          break; }
+        default:
+          nam = mcopystr(my_def->get_assname());
+          break;
+        } // switch(asstype)
+
+        *nam &= ~('a'-'A'); // Make the first letter uppercase
+        p_paps->get_tis()->error("%s `%s' has no formal parameter `%s'",
+          nam,
+          my_def->get_fullname().c_str(),
+          np->get_name()->get_dispname().c_str());
+        Free(nam);
       }
       delete np;
     }
@@ -8728,22 +8743,22 @@ namespace Ttcn {
       // the formal parameter for the current actual parameter
       FormalPar *fp = pars_v[i];
       Error_Context cntxt(ti, "In parameter #%lu for `%s'",
-       (unsigned long) (i + 1), fp->get_id().get_dispname().c_str());
+        (unsigned long) (i + 1), fp->get_id().get_dispname().c_str());
       if (!ti->get_Type() && !ti->get_DerivedRef() && ti->get_Template()
-         ->get_templatetype() == Template::TEMPLATE_NOTUSED) {
-       if (fp->has_defval()) {
-         ActualPar *defval = fp->get_defval();
-         p_aplist->add(new ActualPar(defval));
-         if (defval->is_erroneous()) error_flag = true;
-       } else {
-         ti->error("Not used symbol (`-') cannot be used for parameter "
-           "that does not have default value");
-         p_aplist->add(new ActualPar());
-         error_flag = true;
-       }
+          ->get_templatetype() == Template::TEMPLATE_NOTUSED) {
+        if (fp->has_defval()) {
+          ActualPar *defval = fp->get_defval();
+          p_aplist->add(new ActualPar(defval));
+          if (defval->is_erroneous()) error_flag = true;
+        } else {
+          ti->error("Not used symbol (`-') cannot be used for parameter "
+            "that does not have default value");
+          p_aplist->add(new ActualPar());
+          error_flag = true;
+        }
       } else if (!ti->get_Type() && !ti->get_DerivedRef() && ti->get_Template()
-         ->get_templatetype() == Template::TEMPLATE_ERROR) {
-       ti->error("Parameter not specified");
+          ->get_templatetype() == Template::TEMPLATE_ERROR) {
+        ti->error("Parameter not specified");
       } else {
         ActualPar *ap = fp->chk_actual_par(ti, Type::EXPECTED_DYNAMIC_VALUE);
         p_aplist->add(ap);
@@ -8757,7 +8772,7 @@ namespace Ttcn {
     for (size_t i = upper_limit; i < formal_pars; i++) {
       FormalPar *fp = pars_v[i];
       if (fp->has_defval()) {
-       ActualPar *defval = fp->get_defval();
+        ActualPar *defval = fp->get_defval();
         p_aplist->add(new ActualPar(defval));
         if (defval->is_erroneous()) error_flag = true;
       } else {
@@ -8798,17 +8813,17 @@ namespace Ttcn {
       case Common::Assignment::A_VAR:
       case Common::Assignment::A_VAR_TEMPLATE:
       case Common::Assignment::A_TIMER:
-       // it is not allowed to pass references of local variables or timers
-       if (t_par_ass->is_local()) {
-         t_ref->error("Parameter #%lu of %s refers to %s, which is a local "
-           "definition within a statement block and may have shorter "
-           "lifespan than the activated default. Only references to "
-           "variables and timers defined in the component type can be passed "
-           "to activated defaults", (unsigned long) (i + 1), p_description,
-           t_par_ass->get_description().c_str());
-         ret_val = false;
-       }
-       break;
+        // it is not allowed to pass references of local variables or timers
+        if (t_par_ass->is_local()) {
+          t_ref->error("Parameter #%lu of %s refers to %s, which is a local "
+            "definition within a statement block and may have shorter "
+            "lifespan than the activated default. Only references to "
+            "variables and timers defined in the component type can be passed "
+            "to activated defaults", (unsigned long) (i + 1), p_description,
+            t_par_ass->get_description().c_str());
+          ret_val = false;
+        }
+        break;
       case Common::Assignment::A_PAR_VAL_IN:
       case Common::Assignment::A_PAR_VAL_OUT:
       case Common::Assignment::A_PAR_VAL_INOUT:
@@ -8816,24 +8831,24 @@ namespace Ttcn {
       case Common::Assignment::A_PAR_TEMPL_OUT:
       case Common::Assignment::A_PAR_TEMPL_INOUT:
       case Common::Assignment::A_PAR_TIMER: {
-       // it is not allowed to pass references pointing to formal parameters
-       // except for activate() statements within testcases
-       // note: all defaults are deactivated at the end of the testcase
-       FormalPar *t_refd_fp = dynamic_cast<FormalPar*>(t_par_ass);
-       if (!t_refd_fp) FATAL_ERROR("FormalParList::chk_activate_argument()");
-       FormalParList *t_fpl = t_refd_fp->get_my_parlist();
-       if (!t_fpl || !t_fpl->my_def)
-         FATAL_ERROR("FormalParList::chk_activate_argument()");
-       if (t_fpl->my_def->get_asstype() != Common::Assignment::A_TESTCASE) {
+        // it is not allowed to pass references pointing to formal parameters
+        // except for activate() statements within testcases
+        // note: all defaults are deactivated at the end of the testcase
+        FormalPar *t_refd_fp = dynamic_cast<FormalPar*>(t_par_ass);
+        if (!t_refd_fp) FATAL_ERROR("FormalParList::chk_activate_argument()");
+        FormalParList *t_fpl = t_refd_fp->get_my_parlist();
+        if (!t_fpl || !t_fpl->my_def)
+          FATAL_ERROR("FormalParList::chk_activate_argument()");
+        if (t_fpl->my_def->get_asstype() != Common::Assignment::A_TESTCASE) {
           t_ref->error("Parameter #%lu of %s refers to %s, which may have "
-           "shorter lifespan than the activated default. Only references to "
-           "variables and timers defined in the component type can be passed "
-           "to activated defaults", (unsigned long) (i + 1), p_description,
-           t_par_ass->get_description().c_str());
+            "shorter lifespan than the activated default. Only references to "
+            "variables and timers defined in the component type can be passed "
+            "to activated defaults", (unsigned long) (i + 1), p_description,
+            t_par_ass->get_description().c_str());
           ret_val = false;
-       } }
+        } }
       default:
-       break;
+        break;
       }
     }
     return ret_val;
@@ -9351,7 +9366,7 @@ namespace Ttcn {
     size_t nof_pars = params.size();
     for(size_t i = 0; i < nof_pars; i++)
       params[i]->set_fullname(p_fullname +
-       ".<parameter" + Int2string(i + 1) + ">");
+        ".<parameter" + Int2string(i + 1) + ">");
   }
 
   void ActualParList::set_my_scope(Scope *p_scope)
@@ -9385,24 +9400,24 @@ namespace Ttcn {
     for (size_t i = 0; i < nof_pars; i++) {
       ActualPar *par = params[i];
       if (par->get_selection() == ActualPar::AP_DEFAULT)
-       par = par->get_ActualPar();
+        par = par->get_ActualPar();
       if (par->get_selection() == ActualPar::AP_REF) {
-       Common::Assignment *ass = par->get_Ref()->get_refd_assignment();
-       switch (ass->get_asstype()) {
-       case Common::Assignment::A_VAR:
-       case Common::Assignment::A_PAR_VAL_IN:
-       case Common::Assignment::A_PAR_VAL_OUT:
-       case Common::Assignment::A_PAR_VAL_INOUT:
-         if (!value_refs.has_key(ass)) value_refs.add(ass, 0);
-         break;
-       case Common::Assignment::A_VAR_TEMPLATE:
-       case Common::Assignment::A_PAR_TEMPL_IN:
-       case Common::Assignment::A_PAR_TEMPL_OUT:
-       case Common::Assignment::A_PAR_TEMPL_INOUT:
-         if (!template_refs.has_key(ass)) template_refs.add(ass, 0);
-       default:
-         break;
-       }
+        Common::Assignment *ass = par->get_Ref()->get_refd_assignment();
+        switch (ass->get_asstype()) {
+        case Common::Assignment::A_VAR:
+        case Common::Assignment::A_PAR_VAL_IN:
+        case Common::Assignment::A_PAR_VAL_OUT:
+        case Common::Assignment::A_PAR_VAL_INOUT:
+          if (!value_refs.has_key(ass)) value_refs.add(ass, 0);
+          break;
+        case Common::Assignment::A_VAR_TEMPLATE:
+        case Common::Assignment::A_PAR_TEMPL_IN:
+        case Common::Assignment::A_PAR_TEMPL_OUT:
+        case Common::Assignment::A_PAR_TEMPL_INOUT:
+          if (!template_refs.has_key(ass)) template_refs.add(ass, 0);
+        default:
+          break;
+        }
       }
     }
     // walk through the parameter list and generate the code
@@ -9416,72 +9431,72 @@ namespace Ttcn {
       // the copy constructor call is not needed if the parameter is copied
       // into a shadow object in the body of the called function
       if (!p_fpl || !p_fpl->get_fp_byIndex(i)->get_used_as_lvalue()) {
-       switch (par->get_selection()) {
-       case ActualPar::AP_VALUE: {
-         Value *v = par->get_Value();
-         if (v->get_valuetype() == Value::V_REFD) {
-           Common::Assignment *t_ass =
-             v->get_reference()->get_refd_assignment();
-           if (value_refs.has_key(t_ass)) {
-             // a reference to the same variable is also passed to the called
-             // definition
-             copy_needed = true;
-           } else if (p_comptype || p_compself) {
-             // the called definition has a 'runs on' clause so it can access
-             // component variables
-             switch (t_ass->get_asstype()) {
-             case Common::Assignment::A_PAR_VAL_OUT:
-             case Common::Assignment::A_PAR_VAL_INOUT:
-               // the parameter may be an alias of a component variable
-               copy_needed = true;
-               break;
-             case Common::Assignment::A_VAR:
-               // copy is needed if t_ass is a component variable that is
-               // visible by the called definition
-               if (!t_ass->is_local()) copy_needed = true;
-               /** \todo component type compatibility: check whether t_ass is
-                * visible from p_comptype (otherwise copy is not needed) */
-             default:
-               break;
-             }
-           }
-         }
-         break; }
-       case ActualPar::AP_TEMPLATE: {
-         TemplateInstance *ti = par->get_TemplateInstance();
-         if (!ti->get_DerivedRef()) {
-           Template *t = ti->get_Template();
-           if (t->get_templatetype() == Template::TEMPLATE_REFD) {
-             Common::Assignment *t_ass =
-               t->get_reference()->get_refd_assignment();
-             if (template_refs.has_key(t_ass)) {
-               // a reference to the same variable is also passed to the called
-               // definition
-               copy_needed = true;
-             } else if (p_comptype || p_compself) {
-               // the called definition has a 'runs on' clause so it can access
-               // component variables
-               switch (t_ass->get_asstype()) {
-               case Common::Assignment::A_PAR_TEMPL_OUT:
-               case Common::Assignment::A_PAR_TEMPL_INOUT:
-                 // the parameter may be an alias of a component variable
-                 copy_needed = true;
-                 break;
-               case Common::Assignment::A_VAR_TEMPLATE:
-                 // copy is needed if t_ass is a component variable that is
-                 // visible by the called definition
-                 if (!t_ass->is_local()) copy_needed = true;
-                 /** \todo component type compatibility: check whether t_ass is
-                  * visible from p_comptype (otherwise copy is not needed) */
-               default:
-                 break;
-               }
-             }
-           }
-         } }
-       default:
-         break;
-       }
+        switch (par->get_selection()) {
+        case ActualPar::AP_VALUE: {
+          Value *v = par->get_Value();
+          if (v->get_valuetype() == Value::V_REFD) {
+            Common::Assignment *t_ass =
+              v->get_reference()->get_refd_assignment();
+            if (value_refs.has_key(t_ass)) {
+              // a reference to the same variable is also passed to the called
+              // definition
+              copy_needed = true;
+            } else if (p_comptype || p_compself) {
+              // the called definition has a 'runs on' clause so it can access
+              // component variables
+              switch (t_ass->get_asstype()) {
+              case Common::Assignment::A_PAR_VAL_OUT:
+              case Common::Assignment::A_PAR_VAL_INOUT:
+                // the parameter may be an alias of a component variable
+                copy_needed = true;
+                break;
+              case Common::Assignment::A_VAR:
+                // copy is needed if t_ass is a component variable that is
+                // visible by the called definition
+                if (!t_ass->is_local()) copy_needed = true;
+                /** \todo component type compatibility: check whether t_ass is
+                 * visible from p_comptype (otherwise copy is not needed) */
+              default:
+                break;
+              }
+            }
+          }
+          break; }
+        case ActualPar::AP_TEMPLATE: {
+          TemplateInstance *ti = par->get_TemplateInstance();
+          if (!ti->get_DerivedRef()) {
+            Template *t = ti->get_Template();
+            if (t->get_templatetype() == Template::TEMPLATE_REFD) {
+              Common::Assignment *t_ass =
+                t->get_reference()->get_refd_assignment();
+              if (template_refs.has_key(t_ass)) {
+                // a reference to the same variable is also passed to the called
+                // definition
+                copy_needed = true;
+              } else if (p_comptype || p_compself) {
+                // the called definition has a 'runs on' clause so it can access
+                // component variables
+                switch (t_ass->get_asstype()) {
+                case Common::Assignment::A_PAR_TEMPL_OUT:
+                case Common::Assignment::A_PAR_TEMPL_INOUT:
+                  // the parameter may be an alias of a component variable
+                  copy_needed = true;
+                  break;
+                case Common::Assignment::A_VAR_TEMPLATE:
+                  // copy is needed if t_ass is a component variable that is
+                  // visible by the called definition
+                  if (!t_ass->is_local()) copy_needed = true;
+                  /** \todo component type compatibility: check whether t_ass is
+                   * visible from p_comptype (otherwise copy is not needed) */
+                default:
+                  break;
+                }
+              }
+            }
+          } }
+        default:
+          break;
+        }
       }
       
       if (use_runtime_2 && ActualPar::AP_REF == par->get_selection()) {
@@ -9521,13 +9536,12 @@ namespace Ttcn {
               }
               // let the array object know that the index is referenced before
               // calling the function, and let it know that it's now longer
-              // referenced after the function call
+              // referenced after the function call (this is done with the help
+              // of the RefdIndexHandler's constructor and destructor)
+              string tmp_id = ref->get_my_scope()->get_scope_mod_gen()->get_temporary_id();
               expr->preamble = mputprintf(expr->preamble,
-                "%s.add_refd_index(%s);\n",
-                array_expr.expr, index_expr.expr);
-              expr->postamble = mputprintf(expr->postamble, 
-                "%s.remove_refd_index(%s);\n",
-                array_expr.expr, index_expr.expr);
+                "RefdIndexHandler %s(&%s, %s);\n",
+                tmp_id.c_str(), array_expr.expr, index_expr.expr);
               // insert any postambles the array object or the index might have
               if (array_expr.postamble != NULL) {
                 expr->preamble = mputstr(expr->preamble, array_expr.postamble);
index fecfc9d1057cb5694893ebcda448749225b85422..cdac82771ac28568fe6844ec8566418669875262 100644 (file)
@@ -38,7 +38,7 @@ GENERATED_OTHERS := compiler.output rawAST.output coding_attrib_p.output lex.bac
 
 STATIC_SOURCES := ArrayDimensions.cc AST_ttcn3.cc Attributes.cc ILT.cc PatternString.cc \
 RawAST.cc Statement.cc TtcnTemplate.cc Templatestuff.cc TextAST.cc Ttcnstuff.cc \
-compiler.c port.c signature.c BerAST.cc JsonAST.cc Ttcn2Json.cc
+compiler.c port.c signature.c BerAST.cc JsonAST.cc Ttcn2Json.cc profiler.c
 
 SOURCES := $(STATIC_SOURCES) $(GENERATED_SOURCES)
        
index 2a452a902f4492154e8725b2a74443e9df7f48da..02d28a6697c744f736de2612b719920f06a22cbe 100644 (file)
@@ -468,6 +468,8 @@ namespace Ttcn {
     case S_CONTINUE:
     case S_STOP_EXEC:
     case S_REPEAT:
+    case S_START_PROFILER:
+    case S_STOP_PROFILER:
       break;
     case S_START_UNDEF:
     case S_STOP_UNDEF:
@@ -689,6 +691,8 @@ namespace Ttcn {
       ags=0;
     case S_ERROR:
     case S_STOP_EXEC:
+    case S_START_PROFILER:
+    case S_STOP_PROFILER:
       break;
     case S_BREAK:
     case S_CONTINUE:
@@ -1451,6 +1455,8 @@ namespace Ttcn {
     case S_TESTCASE_INSTANCE_REFD:
       return "execute";
     case S_STRING2TTCN: return "string2ttcn";
+    case S_START_PROFILER: return "@profiler.start";
+    case S_STOP_PROFILER: return "@profiler.stop";
     default:
       FATAL_ERROR("Statement::get_stmt_name()");
       return "";
@@ -1529,6 +1535,8 @@ namespace Ttcn {
     case S_CONTINUE:
     case S_STOP_EXEC:
     case S_REPEAT:
+    case S_START_PROFILER:
+    case S_STOP_PROFILER:
       break;
     case S_START_UNDEF:
     case S_STOP_UNDEF:
@@ -1756,6 +1764,8 @@ namespace Ttcn {
     case S_CONTINUE:
     case S_STOP_EXEC:
     case S_REPEAT:
+    case S_START_PROFILER:
+    case S_STOP_PROFILER:
       break;
     case S_START_UNDEF:
     case S_STOP_UNDEF:
@@ -2256,6 +2266,8 @@ namespace Ttcn {
     case S_SETVERDICT:
     case S_TESTCASE_INSTANCE:
     case S_TESTCASE_INSTANCE_REFD:
+    case S_START_PROFILER:
+    case S_STOP_PROFILER:
       return false;
     case S_ALT:
     case S_INTERLEAVE:
@@ -2496,6 +2508,10 @@ namespace Ttcn {
     case S_STRING2TTCN:
       chk_string2ttcn();
       break;
+    case S_START_PROFILER:
+    case S_STOP_PROFILER:
+      // do nothing
+      break;
     default:
       FATAL_ERROR("Statement::chk()");
     } // switch statementtype
@@ -5079,6 +5095,8 @@ error:
     case S_CONTINUE:
     case S_STOP_EXEC:
     case S_REPEAT:
+    case S_START_PROFILER:
+    case S_STOP_PROFILER:
       break;
     case S_ASSIGNMENT:
       ass->set_code_section(p_code_section);
@@ -5467,6 +5485,12 @@ error:
     case S_STRING2TTCN:
       str=generate_code_string2ttcn(str);
       break;
+    case S_START_PROFILER:
+      str = mputstr(str, "ttcn3_prof.start();\n");
+      break;
+    case S_STOP_PROFILER:
+      str = mputstr(str, "ttcn3_prof.stop();\n");
+      break;
     default:
       FATAL_ERROR("Statement::generate_code()");
     } // switch
@@ -7124,6 +7148,8 @@ error:
         case S_FUNCTION_INVOKED:
         case S_ALTSTEP_INVOKED:
         case S_STRING2TTCN:
+        case S_START_PROFILER:
+        case S_STOP_PROFILER:
           break;
         default:
           FATAL_ERROR("Statement::set_parent_path()");
@@ -9086,22 +9112,32 @@ error:
       for(size_t i=0; i<tis->get_nof_tis(); i++) {
         TemplateInstance *ti=tis->get_ti_byIndex(i);
         Template *tb=ti->get_Template();
-        bool specval = tb->is_Value();
+        bool is_value = NULL == ti->get_DerivedRef() && tb->is_Value();
         expression_struct exprs;
         Code::init_expr(&exprs);
-        if (!specval) ti->generate_code(&exprs);
-        else if (tb->get_templatetype() == Template::SPECIFIC_VALUE) {
-          tb->get_specific_value()->generate_code_expr_mandatory(&exprs);
+        if (is_value) {
+          if (tb->get_templatetype() == Template::SPECIFIC_VALUE) {
+            tb->get_specific_value()->generate_code_expr_mandatory(&exprs);
+          }
+          else {
+            Value* val = tb->get_Value();
+            if (NULL == val->get_my_governor()) {
+              // the value's governor could not be determined, treat it as a non-value template
+              is_value = false;
+            }
+            else {
+              val->generate_code_expr_mandatory(&exprs);
+            }
+            delete val;
+          }
         }
-        else {
-          Value* val = tb->get_Value();
-          val->generate_code_expr_mandatory(&exprs);
-          delete val;
+        if (!is_value) {
+          ti->generate_code(&exprs);
         }
         str=tb->update_location_object(str);
         if(!exprs.preamble && !exprs.postamble) {
           str=mputstr(str, "if(");
-          if(!specval)
+          if(!is_value)
             str=mputprintf(str, "%s.match(%s)", exprs.expr, expr_name);
           else str=mputprintf(str, "%s == %s", expr_name, exprs.expr);
           str=mputprintf(str, ") goto %s_%lu;\n", tmp_prefix,
@@ -9113,7 +9149,7 @@ error:
             (unsigned long) idx);
           char *s=exprs.expr;
           exprs.expr=mprintf("%s_%lub = ", tmp_prefix, (unsigned long) idx);
-          if(!specval)
+          if(!is_value)
             exprs.expr=mputprintf(exprs.expr, "%s.match(%s)", s, expr_name);
           else exprs.expr=mputprintf(exprs.expr, "(%s == %s)", expr_name, s);
           Free(s);
index 1c1aa6c17015472d912a14eab451ef64e7e42a49..7abce565f7ba2be923bfa18e07a1e31cd7c75cfc 100644 (file)
@@ -235,7 +235,10 @@ namespace Ttcn {
       /* control statement */
       S_TESTCASE_INSTANCE, // testcase_inst
       S_TESTCASE_INSTANCE_REFD, //execute_refd
-      S_STRING2TTCN // str2ttcn
+      S_STRING2TTCN, // str2ttcn
+      /* TTCN-3 Profiler statements */
+      S_START_PROFILER,
+      S_STOP_PROFILER
     };
 
     enum component_t {
@@ -437,8 +440,8 @@ namespace Ttcn {
     Statement& operator=(const Statement& p); ///< assignment disabled
     void clean_up();
   public:
-    /** Constructor used by S_ERROR, S_STOP_EXEC and S_REPEAT, S_BREAK and
-     *  S_CONTINUE */
+    /** Constructor used by S_ERROR, S_STOP_EXEC and S_REPEAT, S_BREAK,
+     *  S_CONTINUE, S_START_PROFILER and S_STOP_PROFILER */
     Statement(statementtype_t p_st);
     /** Constructor used by S_START_UNDEF and S_STOP_UNDEF */
     Statement(statementtype_t p_st, Ref_base *p_ref, Value *p_val);
index bf646c6aca538013d956dbcc7a19d537a5f639c1..03f6d5ee0fa2962cea552ccc5e472b4a50ad3202 100644 (file)
@@ -1964,6 +1964,21 @@ end:
         // Cannot flatten at compile time if the template has parameters.
         can_flatten = false;
       }
+
+      // check for subreferences in the 'all from' target
+      FieldOrArrayRefs* subrefs = ref->get_subrefs();
+      if (NULL != subrefs) {
+        // flattening values/templates with subreferences is not implemented yet
+        can_flatten = false;
+        for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) {
+          FieldOrArrayRef* subref = subrefs->get_ref(i);
+          if (FieldOrArrayRef::ARRAY_REF == subref->get_type()) {
+            // set any array indexes from undefined lowerID to reference
+            subref->get_val()->set_lowerid_to_ref();
+          }
+        }
+      }
+
       Common::Assignment *ass = ref->get_refd_assignment();
       if (ass == NULL) { // perhaps erroneous
         break;
@@ -2073,11 +2088,18 @@ end:
         switch (val->get_valuetype()) {
         case Common::Value::V_SEQOF: case Common::Value::V_SETOF:
         case Common::Value::V_ARRAY: {
-          const size_t ncomp = val->get_nof_comps();
-          for (size_t i = 0; i < ncomp; ++i) {
-            Value *v = val->get_comp_byIndex(i);
-            Template *newt = new Template(v->clone());
-            new_templates->add_t(newt);
+          if (can_flatten) {
+            const size_t ncomp = val->get_nof_comps();
+            for (size_t i = 0; i < ncomp; ++i) {
+              Value *v = val->get_comp_byIndex(i);
+              Template *newt = new Template(v->clone());
+              new_templates->add_t(newt);
+            }
+          }
+          else {
+            delete new_templates;
+            new_templates = 0;
+            killer = false;
           }
           break; }
 
@@ -2095,7 +2117,9 @@ end:
       case Common::Assignment::A_MODULEPAR: // all from a module parameter
       case Common::Assignment::A_VAR: // all from a variable
       case Common::Assignment::A_PAR_VAL_IN:
-      case Common::Assignment::A_PAR_VAL_INOUT: {
+      case Common::Assignment::A_PAR_VAL_INOUT: 
+      case Common::Assignment::A_FUNCTION_RVAL:
+      case Common::Assignment::A_EXT_FUNCTION_RVAL: {
         delete new_templates; // cannot flatten at compile time
         new_templates = 0;
         break; }
@@ -3232,7 +3256,6 @@ end:
          // variable part
         for (size_t i = 0; i < nof_ts; i++) {
           Template *t = u.templates->get_t_byIndex(i);
-          printf("generate_code_init_seof ALL_FROM: temptype %u\n", t->templatetype);
           for (size_t k = 0, v = variables.size(); k < v; ++k) {
             if (t->templatetype == ALL_FROM) {
               Value *refv = t->u.all_from->u.specific_value;
index ce428baaa8ddc657992c0bee38d3f71a230926fb..b9cb1af8a4c416abeacf54a23fce8ab146014cf4 100644 (file)
@@ -21,6 +21,7 @@
 #include "compiler.h"
 #include "../main.hh"
 #include "../error.h"
+#include "profiler.h"
 
 #ifdef LICENSE
 #include "../../common/license.h"
@@ -310,10 +311,6 @@ void write_output(output_struct *output, const char *module_name,
        COPYRIGHT_STRING "\n\n"
        "// Do not edit this file unless you know what you are doing.\n",
        is_ttcn ? "TTCN-3" : "ASN.1", user_info);
-    
-    if (profiler_enabled) {
-      output->source.includes = mputstr(output->source.includes, "#include \"Profiler.hh\"\n");
-    }
 
     if (output->source.includes != NULL) {
        fputs("\n/* Including header files */\n\n", fp);
index 3746fb3700bd34739d3414fe63d91a082d672e4b..4497b6ca79a5d4132311a5fafbfdf961a6625a9e 100644 (file)
@@ -504,6 +504,7 @@ xor4b               RETURN(Xor4bKeyword);
 "@try"    RETURN(TitanSpecificTryKeyword);
 "@catch"  RETURN(TitanSpecificCatchKeyword);
 "@lazy"   RETURN(TitanSpecificLazyKeyword);
+"@profiler" RETURN(TitanSpecificProfilerKeyword);
 
        /* Predefined function identifiers */
 
index dc5a760fe53582bfe36a2d3a218fff087317f60f..5f07d028593a13016839d9423825b1de8968746e 100644 (file)
@@ -706,6 +706,7 @@ static const string anyname("anytype");
 %token TitanSpecificTryKeyword
 %token TitanSpecificCatchKeyword
 %token TitanSpecificLazyKeyword
+%token TitanSpecificProfilerKeyword
 
 /* Keywords combined with a leading dot */
 
@@ -900,7 +901,7 @@ static const string anyname("anytype");
   StartTimerStatement StopExecutionStatement StopStatement StopTCStatement
   StopTimerStatement TimeoutStatement TimerStatements TriggerStatement
   UnmapStatement VerdictStatements WhileStatement SelectCaseConstruct
-  StopTestcaseStatement String2TtcnStatement
+  StopTestcaseStatement String2TtcnStatement ProfilerStatement
 %type <statementblock> StatementBlock optElseClause FunctionStatementOrDefList
   ControlStatementOrDefList ModuleControlBody
 %type <subtypeparse> ValueOrRange
@@ -940,7 +941,7 @@ static const string anyname("anytype");
   PredefinedValue ReadTimerOp ReferOp ReferencedValue RunningOp RunningTimerOp
   SelfOp SingleExpression SingleLowerBound SystemOp TemplateOps TimerOps
   TimerValue UpperBound Value ValueofOp VerdictOps VerdictValue optReplyValue
-  optTestcaseTimerValue optToClause
+  optTestcaseTimerValue optToClause ProfilerRunningOp
 %type <values> ArrayElementExpressionList seqArrayExpressionSpec
 %type <variableentries> VariableList
 %type <variableentry> VariableEntry
@@ -1204,6 +1205,8 @@ PortType
 PredefOrIdentifier
 PredefinedOps
 PredefinedValue
+ProfilerRunningOp
+ProfilerStatement
 RaiseStatement
 Range
 ReadTimerOp
@@ -1711,12 +1714,12 @@ optRunsOnComprefOrSelf
 %left '*' '/' ModKeyword RemKeyword
 %left UnarySign
 
-%expect 24
+%expect 25
 
 %start GrammarRoot
 
 /*
-XXX Source of conflicts (24 S/R):
+XXX Source of conflicts (25 S/R):
 
 1.) 8 conflicts in one state
 The Expression after 'return' keyword is optional in ReturnStatement.
@@ -1754,9 +1757,14 @@ non-standard language extension.
 
 6.) 1 Conflict due to pattern concatenation
 
+7.) 1 conflict
+The TitanSpecificProfilerKeyword following the ReturnKeyword in a ReturnStatement
+can either be the returned boolean value if followed by the DotRunningKeyword (shift)
+or the next statement if followed by the DotStartKeyword or the DotStopKeyword (reduce).
+
 Note that the parser implemented by bison always chooses to shift instead of
 reduce in case of conflicts. This is the desired behaviour in situations 1.),
-2.) and 4.) since the opposite alternative can be forced by the correct usage
+2.), 4.) and 7.) since the opposite alternative can be forced by the correct usage
 of semi-colons. Situation 3.) does not cause any problems as anytype is not
 supported at the moment.
 */
@@ -3910,6 +3918,7 @@ FunctionStatement: // 180
 | SUTStatements {$$=$1;}
 | StopExecutionStatement { $$ = $1; }
 | StopTestcaseStatement { $$ = $1; }
+| ProfilerStatement { $$ = $1; }
 ;
 
 FunctionInstance: /* refpard */ // 181
@@ -5078,6 +5087,7 @@ ControlStatement: /* Statement *stmt */ // 295
 | BehaviourStatements { $$ = $1; }
 | SUTStatements { $$ = $1; }
 | StopExecutionStatement { $$ = $1; }
+| ProfilerStatement { $$ = $1; }
 ;
 
 /* A.1.6.2.1 Variable instantiation */
@@ -7538,6 +7548,26 @@ StopTestcaseStatement:
   }
 ;
 
+  /* these deliberately don't have their locations set */
+ProfilerStatement:
+  TitanSpecificProfilerKeyword DotStartKeyword
+  {
+    $$ = new Statement(Statement::S_START_PROFILER);
+  }
+| TitanSpecificProfilerKeyword DotStopKeyword
+  {
+    $$ = new Statement(Statement::S_STOP_PROFILER);
+  }
+;
+
+ProfilerRunningOp:
+  TitanSpecificProfilerKeyword DotRunningKeyword
+  {
+    $$ = new Value(Value::OPTYPE_PROF_RUNNING);
+    $$->set_location(infile, @$);
+  }
+;
+
 ReturnStatement: // 552
   ReturnKeyword
   {
@@ -8336,6 +8366,7 @@ OpCall: // 611
     else $$ = new Value(Value::V_ERROR);
     $$->set_location(infile, @$);
   }
+| ProfilerRunningOp { $$ = $1; }
 ;
 
 PredefinedOps:
diff --git a/compiler2/ttcn3/profiler.c b/compiler2/ttcn3/profiler.c
new file mode 100644 (file)
index 0000000..4c09a3e
--- /dev/null
@@ -0,0 +1,126 @@
+/******************************************************************************
+ * Copyright (c) 2000-2015 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
+ ******************************************************************************/
+
+#include "profiler.h"
+#include "../../common/memory.h"
+#include <string.h>
+#include <stdio.h>
+
+/** The file list */
+static tcov_file_list *the_files = 0;
+
+/** The database */
+static profiler_data_t *the_data = 0;
+
+/** The current database index for the next get_profiler_code_line() call */
+static int current_index = 0;
+
+/** The file parameter for the last get_profiler_code_line() call */
+static char* last_file_name = 0;
+
+void init_profiler_data(tcov_file_list* p_file_list)
+{
+  the_files = p_file_list;
+  the_data = (profiler_data_t*)Malloc(sizeof(profiler_data_t));
+  the_data->nof_lines = 0;
+  the_data->size = 4;
+  the_data->lines = (profiler_code_line_t*)Malloc(
+    the_data->size * sizeof(profiler_code_line_t));
+}
+
+boolean is_file_profiled(const char* p_file_name)
+{
+  tcov_file_list* file_walker = the_files;
+  while (0 != file_walker) {
+    if (0 == strcmp(p_file_name, file_walker->file_name)) {
+      return TRUE;
+    }
+    /* check for .ttcnpp instead of .ttcn */
+    size_t file_name_len = strlen(file_walker->file_name);
+    if ('p' == file_walker->file_name[file_name_len - 1] &&
+        'p' == file_walker->file_name[file_name_len - 2] &&
+        0 == strncmp(p_file_name, file_walker->file_name, file_name_len - 2)) {
+      return TRUE;
+    }
+    file_walker = file_walker->next;
+  }
+  return FALSE;
+}
+
+void insert_profiler_code_line(const char* p_file_name,
+  const char* p_function_name, int p_line_no)
+{
+  /* check if the entry already exists */
+  int i;
+  for (i = 0; i < the_data->nof_lines; ++i) {
+    if (0 == strcmp(p_file_name,the_data->lines[i].file_name) &&
+        p_line_no == the_data->lines[i].line_no) {
+      if (0 == the_data->lines[i].function_name && 0 != p_function_name) {
+        the_data->lines[i].function_name = mcopystr(p_function_name);
+      }
+      return;
+    }
+  }
+  if (the_data->nof_lines == the_data->size) {
+    /* database size reached, increase the buffer size (exponentially) */
+    the_data->size *= 2;
+    the_data->lines = (profiler_code_line_t*)Realloc(the_data->lines,
+      the_data->size * sizeof(profiler_code_line_t));
+  }
+  the_data->lines[the_data->nof_lines].file_name = mcopystr(p_file_name);
+  if (0 != p_function_name) {
+    the_data->lines[the_data->nof_lines].function_name = mcopystr(p_function_name);
+  }
+  else {
+    the_data->lines[the_data->nof_lines].function_name = 0;
+  }
+  the_data->lines[the_data->nof_lines].line_no = p_line_no;
+  ++the_data->nof_lines;
+}
+
+boolean get_profiler_code_line(const char *p_file_name,
+  char **p_function_name, int *p_line_no)
+{
+  if (0 == last_file_name || 0 != strcmp(last_file_name, p_file_name)) {
+    /* file parameter changed, reset the current index and store the new file name */
+    current_index = 0;
+    Free(last_file_name);
+    last_file_name = mcopystr(p_file_name);
+  }
+  while (current_index < the_data->nof_lines) {
+    /* find the first entry in the specified file and return it */
+    if (0 == strcmp(p_file_name, the_data->lines[current_index].file_name)) {
+      *p_function_name = the_data->lines[current_index].function_name;
+      *p_line_no = the_data->lines[current_index].line_no;
+      ++current_index;
+      return TRUE;
+    }
+    ++current_index;
+  }
+  /* no entry found with the specified file name */
+  return FALSE;
+}
+
+void free_profiler_data()
+{
+  int i;
+  for (i = 0; i < the_data->nof_lines; ++i) {
+    Free(the_data->lines[i].file_name);
+    Free(the_data->lines[i].function_name);
+  }
+  Free(the_data->lines);
+  Free(the_data);
+  Free(last_file_name);
+  
+  while (0 != the_files) {
+         tcov_file_list *next_file = the_files->next;
+         Free(the_files->file_name);
+         Free(the_files);
+         the_files = next_file;
+       }
+}
diff --git a/compiler2/ttcn3/profiler.h b/compiler2/ttcn3/profiler.h
new file mode 100644 (file)
index 0000000..ab00ccc
--- /dev/null
@@ -0,0 +1,74 @@
+/******************************************************************************
+ * Copyright (c) 2000-2015 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
+ ******************************************************************************/
+
+#ifndef PROFILER_H
+#define        PROFILER_H
+
+#include "../main.hh"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Structure containing one code line or function for the profiler */
+typedef struct profiler_code_line_t {
+  /** Name of the file containing this line */
+  char* file_name;
+  /** Name of the function that starts at this line (or null if no function starts here) */
+  char* function_name;
+  /** Code line number */
+  int line_no;
+} profiler_code_line_t;
+
+/** Profiler database
+  *
+  * Contains entries for the code lines in the processed TTCN-3 files.
+  * Used for initializing the TTCN3_Profiler (in runtime) with all the code 
+  * lines and functions in the processed files, so it can determine which the
+  * unused lines and functions. */
+typedef struct profiler_data_t {
+  profiler_code_line_t *lines;
+  int nof_lines;
+  int size;
+} profiler_data_t;
+
+/** Initializes the database (must be called once, at the start of compilation) */
+void init_profiler_data(tcov_file_list* p_file_list);
+
+/** Returns 1 if the specified file is in the profiler's file list,
+  * otherwise returns 0.*/
+boolean is_file_profiled(const char* p_file_name);
+
+/** Inserts one code line or function to the database 
+  * @param p_file_name [in] name of the file containing the line/function
+  * @param p_function_name [in] name of the function (for functions) or null (for lines)
+  * @param p_line_no [in] line number (for lines) or the function's starting line 
+  * (for functions) */
+void insert_profiler_code_line(const char* p_file_name,
+  const char* p_function_name, int p_line_no);
+
+/** Retrieves the next code line or function from the specified file. Calling this
+  * function with the same file parameter will keep returning the next code line
+  * or function until the end of the database is reached. If the file parameter is
+  * changed, the function will start again from the beginning of the database.
+  * @param p_file_name [in] name of the file to search for
+  * @param p_function_name [out] contains the function name if a function was found
+  * @param p_line_no [out] contains the line number of function start line
+  * @return 1 if a line or function was found, otherwise 0 */
+boolean get_profiler_code_line(const char *p_file_name,
+  char **p_function_name, int *p_line_no);
+
+/** Frees the database (must be called once, at the end of compilation) */
+void free_profiler_data();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PROFILER_H */
+
index f4ae4a5d7b8c5919beb54b2f0a594be8e20e97a9..edbd97a36498611f5c57729846f597695fd02ebf 100644 (file)
@@ -37,55 +37,55 @@ make the type descriptors of embedded types static
 
 static const ASN_Tag_t CHARACTER_STRING_identification_tag_[] = { { ASN_TAG_CONT, 0u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_identification_ber_ = { 1u, CHARACTER_STRING_identification_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_descr_ = { "CHARACTER STRING.identification", &CHARACTER_STRING_identification_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_descr_ = { "CHARACTER STRING.identification", &CHARACTER_STRING_identification_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t CHARACTER_STRING_identification_syntaxes_abstract_tag_[] = { { ASN_TAG_CONT, 0u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_identification_syntaxes_abstract_ber_ = { 1u, CHARACTER_STRING_identification_syntaxes_abstract_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_syntaxes_abstract_descr_ = { "CHARACTER STRING.identification.syntaxes.abstract", &CHARACTER_STRING_identification_syntaxes_abstract_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_syntaxes_abstract_descr_ = { "CHARACTER STRING.identification.syntaxes.abstract", &CHARACTER_STRING_identification_syntaxes_abstract_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
 
 static const ASN_Tag_t CHARACTER_STRING_identification_syntaxes_transfer_tag_[] = { { ASN_TAG_CONT, 1u }};
 const ASN_BERdescriptor_t CHARACTER_STRING_identification_syntaxes_transfer_ber_ = { 1u, CHARACTER_STRING_identification_syntaxes_transfer_tag_ };
-const TTCN_Typedescriptor_t CHARACTER_STRING_identification_syntaxes_transfer_descr_ = { "CHARACTER STRING.identification.syntaxes.transfer", &CHARACTER_STRING_identification_syntaxes_transfer_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
+const TTCN_Typedescriptor_t CHARACTER_STRING_identification_syntaxes_transfer_descr_ = { "CHARACTER STRING.identification.syntaxes.transfer", &CHARACTER_STRING_identification_syntaxes_transfer_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
 
 static const ASN_Tag_t CHARACTER_STRING_identification_syntaxes_tag_[] = { { ASN_TAG_CONT, 0u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_identification_syntaxes_ber_ = { 1u, CHARACTER_STRING_identification_syntaxes_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_syntaxes_descr_ = { "CHARACTER STRING.identification.syntaxes", &CHARACTER_STRING_identification_syntaxes_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_syntaxes_descr_ = { "CHARACTER STRING.identification.syntaxes", &CHARACTER_STRING_identification_syntaxes_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t CHARACTER_STRING_identification_syntax_tag_[] = { { ASN_TAG_CONT, 1u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_identification_syntax_ber_ = { 1u, CHARACTER_STRING_identification_syntax_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_syntax_descr_ = { "CHARACTER STRING.identification.syntax", &CHARACTER_STRING_identification_syntax_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_syntax_descr_ = { "CHARACTER STRING.identification.syntax", &CHARACTER_STRING_identification_syntax_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
 
 static const ASN_Tag_t CHARACTER_STRING_identification_presentation__context__id_tag_[] = { { ASN_TAG_CONT, 2u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_identification_presentation__context__id_ber_ = { 1u, CHARACTER_STRING_identification_presentation__context__id_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_presentation__context__id_descr_ = { "CHARACTER STRING.identification.presentation-context-id", &CHARACTER_STRING_identification_presentation__context__id_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_presentation__context__id_descr_ = { "CHARACTER STRING.identification.presentation-context-id", &CHARACTER_STRING_identification_presentation__context__id_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t CHARACTER_STRING_identification_context__negotiation_presentation__context__id_tag_[] = { { ASN_TAG_CONT, 0u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_identification_context__negotiation_presentation__context__id_ber_ = { 1u, CHARACTER_STRING_identification_context__negotiation_presentation__context__id_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_context__negotiation_presentation__context__id_descr_ = { "CHARACTER STRING.identification.context-negotiation.presentation-context-id", &CHARACTER_STRING_identification_context__negotiation_presentation__context__id_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_context__negotiation_presentation__context__id_descr_ = { "CHARACTER STRING.identification.context-negotiation.presentation-context-id", &CHARACTER_STRING_identification_context__negotiation_presentation__context__id_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t CHARACTER_STRING_identification_context__negotiation_transfer__syntax_tag_[] = { { ASN_TAG_CONT, 1u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_identification_context__negotiation_transfer__syntax_ber_ = { 1u, CHARACTER_STRING_identification_context__negotiation_transfer__syntax_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_context__negotiation_transfer__syntax_descr_ = { "CHARACTER STRING.identification.context-negotiation.transfer-syntax", &CHARACTER_STRING_identification_context__negotiation_transfer__syntax_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_context__negotiation_transfer__syntax_descr_ = { "CHARACTER STRING.identification.context-negotiation.transfer-syntax", &CHARACTER_STRING_identification_context__negotiation_transfer__syntax_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
 
 static const ASN_Tag_t CHARACTER_STRING_identification_context__negotiation_tag_[] = { { ASN_TAG_CONT, 3u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_identification_context__negotiation_ber_ = { 1u, CHARACTER_STRING_identification_context__negotiation_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_context__negotiation_descr_ = { "CHARACTER STRING.identification.context-negotiation", &CHARACTER_STRING_identification_context__negotiation_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_context__negotiation_descr_ = { "CHARACTER STRING.identification.context-negotiation", &CHARACTER_STRING_identification_context__negotiation_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t CHARACTER_STRING_identification_transfer__syntax_tag_[] = { { ASN_TAG_CONT, 4u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_identification_transfer__syntax_ber_ = { 1u, CHARACTER_STRING_identification_transfer__syntax_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_transfer__syntax_descr_ = { "CHARACTER STRING.identification.transfer-syntax", &CHARACTER_STRING_identification_transfer__syntax_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_transfer__syntax_descr_ = { "CHARACTER STRING.identification.transfer-syntax", &CHARACTER_STRING_identification_transfer__syntax_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
 
 static const ASN_Tag_t CHARACTER_STRING_identification_fixed_tag_[] = { { ASN_TAG_CONT, 5u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_identification_fixed_ber_ = { 1u, CHARACTER_STRING_identification_fixed_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_fixed_descr_ = { "CHARACTER STRING.identification.fixed", &CHARACTER_STRING_identification_fixed_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_identification_fixed_descr_ = { "CHARACTER STRING.identification.fixed", &CHARACTER_STRING_identification_fixed_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t CHARACTER_STRING_string__value_tag_[] = { { ASN_TAG_CONT, 2u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_string__value_ber_ = { 1u, CHARACTER_STRING_string__value_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_string__value_descr_ = { "CHARACTER STRING.string-value", &CHARACTER_STRING_string__value_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_string__value_descr_ = { "CHARACTER STRING.string-value", &CHARACTER_STRING_string__value_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t CHARACTER_STRING_data__value__descriptor_tag_[] = { { ASN_TAG_CONT, 1u }};
 static const ASN_BERdescriptor_t CHARACTER_STRING_data__value__descriptor_ber_ = { 1u, CHARACTER_STRING_data__value__descriptor_tag_ };
-static const TTCN_Typedescriptor_t CHARACTER_STRING_data__value__descriptor_descr_ = { "CHARACTER STRING.data-value-descriptor", &CHARACTER_STRING_data__value__descriptor_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING };
+static const TTCN_Typedescriptor_t CHARACTER_STRING_data__value__descriptor_descr_ = { "CHARACTER STRING.data-value-descriptor", &CHARACTER_STRING_data__value__descriptor_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING };
 
 void CHARACTER_STRING_identification::clean_up()
 {
index 7a05319d6256b070e6852ce3273baf584545eb4c..11cfeed960cff696544851b0868e3626aefc6e55 100644 (file)
@@ -37,55 +37,55 @@ make the type descriptors of embedded types static
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_tag_[] = { { ASN_TAG_CONT, 0u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_ber_ = { 1u, EMBEDDED_PDV_identification_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_descr_ = { "EMBEDDED PDV.identification", &EMBEDDED_PDV_identification_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_descr_ = { "EMBEDDED PDV.identification", &EMBEDDED_PDV_identification_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_syntaxes_abstract_tag_[] = { { ASN_TAG_CONT, 0u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_syntaxes_abstract_ber_ = { 1u, EMBEDDED_PDV_identification_syntaxes_abstract_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_syntaxes_abstract_descr_ = { "EMBEDDED PDV.identification.syntaxes.abstract", &EMBEDDED_PDV_identification_syntaxes_abstract_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_syntaxes_abstract_descr_ = { "EMBEDDED PDV.identification.syntaxes.abstract", &EMBEDDED_PDV_identification_syntaxes_abstract_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_syntaxes_transfer_tag_[] = { { ASN_TAG_CONT, 1u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_syntaxes_transfer_ber_ = { 1u, EMBEDDED_PDV_identification_syntaxes_transfer_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_syntaxes_transfer_descr_ = { "EMBEDDED PDV.identification.syntaxes.transfer", &EMBEDDED_PDV_identification_syntaxes_transfer_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_syntaxes_transfer_descr_ = { "EMBEDDED PDV.identification.syntaxes.transfer", &EMBEDDED_PDV_identification_syntaxes_transfer_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_syntaxes_tag_[] = { { ASN_TAG_CONT, 0u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_syntaxes_ber_ = { 1u, EMBEDDED_PDV_identification_syntaxes_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_syntaxes_descr_ = { "EMBEDDED PDV.identification.syntaxes", &EMBEDDED_PDV_identification_syntaxes_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_syntaxes_descr_ = { "EMBEDDED PDV.identification.syntaxes", &EMBEDDED_PDV_identification_syntaxes_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_syntax_tag_[] = { { ASN_TAG_CONT, 1u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_syntax_ber_ = { 1u, EMBEDDED_PDV_identification_syntax_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_syntax_descr_ = { "EMBEDDED PDV.identification.syntax", &EMBEDDED_PDV_identification_syntax_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_syntax_descr_ = { "EMBEDDED PDV.identification.syntax", &EMBEDDED_PDV_identification_syntax_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_presentation__context__id_tag_[] = { { ASN_TAG_CONT, 2u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_presentation__context__id_ber_ = { 1u, EMBEDDED_PDV_identification_presentation__context__id_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_presentation__context__id_descr_ = { "EMBEDDED PDV.identification.presentation-context-id", &EMBEDDED_PDV_identification_presentation__context__id_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_presentation__context__id_descr_ = { "EMBEDDED PDV.identification.presentation-context-id", &EMBEDDED_PDV_identification_presentation__context__id_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_context__negotiation_presentation__context__id_tag_[] = { { ASN_TAG_CONT, 0u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_context__negotiation_presentation__context__id_ber_ = { 1u, EMBEDDED_PDV_identification_context__negotiation_presentation__context__id_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_context__negotiation_presentation__context__id_descr_ = { "EMBEDDED PDV.identification.context-negotiation.presentation-context-id", &EMBEDDED_PDV_identification_context__negotiation_presentation__context__id_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_context__negotiation_presentation__context__id_descr_ = { "EMBEDDED PDV.identification.context-negotiation.presentation-context-id", &EMBEDDED_PDV_identification_context__negotiation_presentation__context__id_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_context__negotiation_transfer__syntax_tag_[] = { { ASN_TAG_CONT, 1u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_context__negotiation_transfer__syntax_ber_ = { 1u, EMBEDDED_PDV_identification_context__negotiation_transfer__syntax_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_context__negotiation_transfer__syntax_descr_ = { "EMBEDDED PDV.identification.context-negotiation.transfer-syntax", &EMBEDDED_PDV_identification_context__negotiation_transfer__syntax_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_context__negotiation_transfer__syntax_descr_ = { "EMBEDDED PDV.identification.context-negotiation.transfer-syntax", &EMBEDDED_PDV_identification_context__negotiation_transfer__syntax_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_context__negotiation_tag_[] = { { ASN_TAG_CONT, 3u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_context__negotiation_ber_ = { 1u, EMBEDDED_PDV_identification_context__negotiation_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_context__negotiation_descr_ = { "EMBEDDED PDV.identification.context-negotiation", &EMBEDDED_PDV_identification_context__negotiation_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_context__negotiation_descr_ = { "EMBEDDED PDV.identification.context-negotiation", &EMBEDDED_PDV_identification_context__negotiation_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_transfer__syntax_tag_[] = { { ASN_TAG_CONT, 4u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_transfer__syntax_ber_ = { 1u, EMBEDDED_PDV_identification_transfer__syntax_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_transfer__syntax_descr_ = { "EMBEDDED PDV.identification.transfer-syntax", &EMBEDDED_PDV_identification_transfer__syntax_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_transfer__syntax_descr_ = { "EMBEDDED PDV.identification.transfer-syntax", &EMBEDDED_PDV_identification_transfer__syntax_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::OBJID };
 
 static const ASN_Tag_t EMBEDDED_PDV_identification_fixed_tag_[] = { { ASN_TAG_CONT, 5u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_identification_fixed_ber_ = { 1u, EMBEDDED_PDV_identification_fixed_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_fixed_descr_ = { "EMBEDDED PDV.identification.fixed", &EMBEDDED_PDV_identification_fixed_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_identification_fixed_descr_ = { "EMBEDDED PDV.identification.fixed", &EMBEDDED_PDV_identification_fixed_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t EMBEDDED_PDV_data__value_tag_[] = { { ASN_TAG_CONT, 2u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_data__value_ber_ = { 1u, EMBEDDED_PDV_data__value_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_data__value_descr_ = { "EMBEDDED PDV.data-value", &EMBEDDED_PDV_data__value_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_data__value_descr_ = { "EMBEDDED PDV.data-value", &EMBEDDED_PDV_data__value_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
 static const ASN_Tag_t EMBEDDED_PDV_data__value__descriptor_tag_[] = { { ASN_TAG_CONT, 1u }};
 static const ASN_BERdescriptor_t EMBEDDED_PDV_data__value__descriptor_ber_ = { 1u, EMBEDDED_PDV_data__value__descriptor_tag_ };
-static const TTCN_Typedescriptor_t EMBEDDED_PDV_data__value__descriptor_descr_ = { "EMBEDDED PDV.data-value-descriptor", &EMBEDDED_PDV_data__value__descriptor_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING };
+static const TTCN_Typedescriptor_t EMBEDDED_PDV_data__value__descriptor_descr_ = { "EMBEDDED PDV.data-value-descriptor", &EMBEDDED_PDV_data__value__descriptor_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING };
 
 /******************** EMBEDDED_PDV_identification ********************/
 
index 65e7e3dd031367555f19db8d251a2b4c5affdec7..4cc701ff01a85fe19107215bc0a5f1c12af84d2f 100644 (file)
@@ -197,19 +197,19 @@ namespace { /* anonymous namespace */
     field_encoding.octet__aligned()=ex.data__value();
   }
 
-  static const TTCN_Typedescriptor_t EXTERNALtransfer_encoding_descr_ = { "EXTERNALtransfer.encoding", &CHOICE_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+  static const TTCN_Typedescriptor_t EXTERNALtransfer_encoding_descr_ = { "EXTERNALtransfer.encoding", &CHOICE_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
   static const ASN_Tag_t EXTERNALtransfer_encoding_single__ASN1__type_tag_[] = { { ASN_TAG_CONT, 0u } };
   static const ASN_BERdescriptor_t EXTERNALtransfer_encoding_single__ASN1__type_ber_ = { 1u, EXTERNALtransfer_encoding_single__ASN1__type_tag_ };
-  static const TTCN_Typedescriptor_t EXTERNALtransfer_encoding_single__ASN1__type_descr_ = { "EXTERNALtransfer.encoding.single-ASN1-type", &EXTERNALtransfer_encoding_single__ASN1__type_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+  static const TTCN_Typedescriptor_t EXTERNALtransfer_encoding_single__ASN1__type_descr_ = { "EXTERNALtransfer.encoding.single-ASN1-type", &EXTERNALtransfer_encoding_single__ASN1__type_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
   static const ASN_Tag_t EXTERNALtransfer_encoding_octet__aligned_tag_[] = { { ASN_TAG_CONT, 1u } };
   static const ASN_BERdescriptor_t EXTERNALtransfer_encoding_octet__aligned_ber_ = { 1u, EXTERNALtransfer_encoding_octet__aligned_tag_ };
-  static const TTCN_Typedescriptor_t EXTERNALtransfer_encoding_octet__aligned_descr_ = { "EXTERNALtransfer.encoding.octet-aligned", &EXTERNALtransfer_encoding_octet__aligned_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+  static const TTCN_Typedescriptor_t EXTERNALtransfer_encoding_octet__aligned_descr_ = { "EXTERNALtransfer.encoding.octet-aligned", &EXTERNALtransfer_encoding_octet__aligned_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
   static const ASN_Tag_t EXTERNALtransfer_encoding_arbitrary_tag_[] = { { ASN_TAG_CONT, 2u } };
   static const ASN_BERdescriptor_t EXTERNALtransfer_encoding_arbitrary_ber_ = { 1u, EXTERNALtransfer_encoding_arbitrary_tag_ };
-  static const TTCN_Typedescriptor_t EXTERNALtransfer_encoding_arbitrary_descr_ = { "EXTERNALtransfer.encoding.arbitrary", &EXTERNALtransfer_encoding_arbitrary_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
+  static const TTCN_Typedescriptor_t EXTERNALtransfer_encoding_arbitrary_descr_ = { "EXTERNALtransfer.encoding.arbitrary", &EXTERNALtransfer_encoding_arbitrary_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE };
 
   /* Member functions of C++ classes */
 
index bfbfde7ead30ae240e0763ac08febdb36af47b93..bb34bb2a392ea9a2f4955c6acd37478f1044fe6e 100644 (file)
@@ -36,7 +36,11 @@ extern unsigned int get_timer_array_index(const INTEGER& index_value,
  *
  * */
 template <typename T_type, unsigned int array_size, int index_offset>
-class TIMER_ARRAY {
+class TIMER_ARRAY 
+#ifdef TITAN_RUNTIME_2
+  : public RefdIndexInterface
+#endif
+{
   T_type array_elements[array_size];
   char * names[array_size];
 
@@ -85,13 +89,6 @@ public:
     }
     TTCN_Logger::log_event_str(" }");
   }
-  
-#ifdef TITAN_RUNTIME_2
-  // Dummy functions, only used in record of/set of in RT2 (the referenced indices
-  // cannot be deleted, since arrays have a fixed size)
-  void add_refd_index(int) {}
-  void remove_refd_index(int) {}
-#endif
 };
 
 extern unsigned int get_port_array_index(int index_value,
@@ -100,7 +97,11 @@ extern unsigned int get_port_array_index(const INTEGER& index_value,
   unsigned int array_size, int index_offset);
 
 template <typename T_type, unsigned int array_size, int index_offset>
-class PORT_ARRAY {
+class PORT_ARRAY
+#ifdef TITAN_RUNTIME_2
+  : public RefdIndexInterface
+#endif
+{
   T_type array_elements[array_size];
   char * names[array_size];
 
@@ -152,13 +153,6 @@ public:
     }
     TTCN_Logger::log_event_str(" }");
   }
-  
-#ifdef TITAN_RUNTIME_2
-  // Dummy functions, only used in record of/set of in RT2 (the referenced indices
-  // cannot be deleted, since arrays have a fixed size)
-  void add_refd_index(int) {}
-  void remove_refd_index(int) {}
-#endif
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -170,6 +164,9 @@ extern unsigned int get_array_index(const INTEGER& index_value,
 
 template <typename T_type, unsigned int array_size, int index_offset>
 class VALUE_ARRAY : public Base_Type
+#ifdef TITAN_RUNTIME_2
+  , public RefdIndexInterface
+#endif
 {
   T_type array_elements[array_size];
 public:
@@ -240,13 +237,6 @@ public:
   /** Decodes accordingly to the JSON encoding rules.
     * Returns the length of the decoded data. */
   int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);
-  
-#ifdef TITAN_RUNTIME_2
-  // Dummy functions, only used in record of/set of in RT2 (the referenced indices
-  // cannot be deleted, since arrays have a fixed size)
-  void add_refd_index(int) {}
-  void remove_refd_index(int) {}
-#endif
 };
 
 template <typename T_type, unsigned int array_size, int index_offset>
index 104e6b0f94e0408119a16137600614a7f18d3169..c64c2f767c2f865a966750bd6ded59fa052ec230 100644 (file)
@@ -1086,101 +1086,101 @@ const Base_Type* TTCN_Type_list::get_nth(size_t pos) const
 }
 
 const TTCN_Typedescriptor_t BOOLEAN_descr_={"BOOLEAN", &BOOLEAN_ber_,
-  &BOOLEAN_raw_, &BOOLEAN_text_, &BOOLEAN_xer_, &BOOLEAN_json_, TTCN_Typedescriptor_t::DONTCARE};
+  &BOOLEAN_raw_, &BOOLEAN_text_, &BOOLEAN_xer_, &BOOLEAN_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t INTEGER_descr_={"INTEGER", &INTEGER_ber_,
-  &INTEGER_raw_, &INTEGER_text_, &INTEGER_xer_, &INTEGER_json_, TTCN_Typedescriptor_t::DONTCARE};
+  &INTEGER_raw_, &INTEGER_text_, &INTEGER_xer_, &INTEGER_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t FLOAT_descr_={"REAL", &FLOAT_ber_, &FLOAT_raw_,
-  NULL, &FLOAT_xer_, &FLOAT_json_, TTCN_Typedescriptor_t::DONTCARE};
+  NULL, &FLOAT_xer_, &FLOAT_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t VERDICTTYPE_descr_={"verdicttype", NULL, NULL,
-  NULL, &VERDICTTYPE_xer_, &VERDICTTYPE_json_, TTCN_Typedescriptor_t::DONTCARE};
+  NULL, &VERDICTTYPE_xer_, &VERDICTTYPE_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t OBJID_descr_={"OBJECT IDENTIFIER", &OBJID_ber_,
-  NULL, NULL, &OBJID_xer_, &OBJID_json_, TTCN_Typedescriptor_t::OBJID};
+  NULL, NULL, &OBJID_xer_, &OBJID_json_, NULL, TTCN_Typedescriptor_t::OBJID};
 
 const TTCN_Typedescriptor_t BITSTRING_descr_={"BIT STRING", &BITSTRING_ber_,
-  &BITSTRING_raw_, NULL, &BITSTRING_xer_, &BITSTRING_json_, TTCN_Typedescriptor_t::DONTCARE};
+  &BITSTRING_raw_, NULL, &BITSTRING_xer_, &BITSTRING_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t HEXSTRING_descr_={"hexstring", NULL,
-  &HEXSTRING_raw_, NULL, &HEXSTRING_xer_, &HEXSTRING_json_, TTCN_Typedescriptor_t::DONTCARE};
+  &HEXSTRING_raw_, NULL, &HEXSTRING_xer_, &HEXSTRING_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t OCTETSTRING_descr_={"OCTET STRING",
-  &OCTETSTRING_ber_, &OCTETSTRING_raw_, &OCTETSTRING_text_, &OCTETSTRING_xer_, &OCTETSTRING_json_, TTCN_Typedescriptor_t::DONTCARE};
+  &OCTETSTRING_ber_, &OCTETSTRING_raw_, &OCTETSTRING_text_, &OCTETSTRING_xer_, &OCTETSTRING_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t CHARSTRING_descr_={"charstring", NULL,
-  &CHARSTRING_raw_, &CHARSTRING_text_, &CHARSTRING_xer_, &CHARSTRING_json_, TTCN_Typedescriptor_t::DONTCARE};
+  &CHARSTRING_raw_, &CHARSTRING_text_, &CHARSTRING_xer_, &CHARSTRING_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t UNIVERSAL_CHARSTRING_descr_={"universal charstring",
-  NULL, NULL, NULL, &UNIVERSAL_CHARSTRING_xer_, &UNIVERSAL_CHARSTRING_json_, TTCN_Typedescriptor_t::DONTCARE};
+  NULL, NULL, &UNIVERSAL_CHARSTRING_text_, &UNIVERSAL_CHARSTRING_xer_, &UNIVERSAL_CHARSTRING_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t COMPONENT_descr_={"component", NULL, NULL, NULL,
-  NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t DEFAULT_descr_={"default", NULL, NULL, NULL,
-  NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t ASN_NULL_descr_={"NULL", &ASN_NULL_ber_, NULL,
-  NULL, &ASN_NULL_xer_, &ASN_NULL_json_, TTCN_Typedescriptor_t::DONTCARE};
+  NULL, &ASN_NULL_xer_, &ASN_NULL_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t ASN_ANY_descr_={"ANY", &ASN_ANY_ber_, NULL,
-  NULL, NULL, &ASN_ANY_json_, TTCN_Typedescriptor_t::DONTCARE};
+  NULL, NULL, &ASN_ANY_json_, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t EXTERNAL_descr_={"EXTERNAL", &EXTERNAL_ber_, NULL,
-  NULL, &EXTERNAL_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  NULL, &EXTERNAL_xer_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t EMBEDDED_PDV_descr_={"EMBEDDED PDV",
-  &EMBEDDED_PDV_ber_, NULL, NULL, &EMBEDDED_PDV_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  &EMBEDDED_PDV_ber_, NULL, NULL, &EMBEDDED_PDV_xer_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t CHARACTER_STRING_descr_={"CHARACTER STRING",
-  &CHARACTER_STRING_ber_, NULL, NULL, &CHARACTER_STRING_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  &CHARACTER_STRING_ber_, NULL, NULL, &CHARACTER_STRING_xer_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t ObjectDescriptor_descr_={"ObjectDescriptor",
-  &ObjectDescriptor_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING};
+  &ObjectDescriptor_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING};
 
 const TTCN_Typedescriptor_t UTF8String_descr_={"UTF8String", &UTF8String_ber_,
-  NULL, NULL, &UTF8String_xer_, NULL, TTCN_Typedescriptor_t::UTF8STRING};
+  NULL, NULL, &UTF8String_xer_, NULL, NULL, TTCN_Typedescriptor_t::UTF8STRING};
 
 const TTCN_Typedescriptor_t ASN_ROID_descr_={"RELATIVE-OID", &ASN_ROID_ber_,
-  NULL, NULL, &ASN_ROID_xer_, &ASN_ROID_json_, TTCN_Typedescriptor_t::ROID};
+  NULL, NULL, &ASN_ROID_xer_, &ASN_ROID_json_, NULL, TTCN_Typedescriptor_t::ROID};
 
 const TTCN_Typedescriptor_t NumericString_descr_={"NumericString",
-  &NumericString_ber_, NULL, NULL, &NumericString_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  &NumericString_ber_, NULL, NULL, &NumericString_xer_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t PrintableString_descr_={"PrintableString",
-  &PrintableString_ber_, NULL, NULL, &PrintableString_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  &PrintableString_ber_, NULL, NULL, &PrintableString_xer_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t TeletexString_descr_={"TeletexString",
-  &TeletexString_ber_, NULL, NULL, &TeletexString_xer_, NULL, TTCN_Typedescriptor_t::TELETEXSTRING};
+  &TeletexString_ber_, NULL, NULL, &TeletexString_xer_, NULL, NULL, TTCN_Typedescriptor_t::TELETEXSTRING};
 const TTCN_Typedescriptor_t& T61String_descr_=TeletexString_descr_;
 
 const TTCN_Typedescriptor_t VideotexString_descr_={"VideotexString",
-  &VideotexString_ber_, NULL, NULL, &VideotexString_xer_, NULL, TTCN_Typedescriptor_t::VIDEOTEXSTRING};
+  &VideotexString_ber_, NULL, NULL, &VideotexString_xer_, NULL, NULL, TTCN_Typedescriptor_t::VIDEOTEXSTRING};
 
 const TTCN_Typedescriptor_t IA5String_descr_={"IA5String", &IA5String_ber_,
-  NULL, NULL, &IA5String_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  NULL, NULL, &IA5String_xer_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t ASN_GeneralizedTime_descr_={"GeneralizedTime",
-  &ASN_GeneralizedTime_ber_, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  &ASN_GeneralizedTime_ber_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t ASN_UTCTime_descr_={"UTCTime", &ASN_UTCTime_ber_,
-  NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 
 const TTCN_Typedescriptor_t GraphicString_descr_={"GraphicString",
-  &GraphicString_ber_, NULL, NULL, &GraphicString_xer_, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING};
+  &GraphicString_ber_, NULL, NULL, &GraphicString_xer_, NULL, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING};
 
 const TTCN_Typedescriptor_t VisibleString_descr_={"VisibleString",
-  &VisibleString_ber_, NULL, NULL, &VisibleString_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE};
+  &VisibleString_ber_, NULL, NULL, &VisibleString_xer_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE};
 const TTCN_Typedescriptor_t& ISO646String_descr_=VisibleString_descr_;
 
 const TTCN_Typedescriptor_t GeneralString_descr_={"GeneralString",
-  &GeneralString_ber_, NULL, NULL, &GeneralString_xer_, NULL, TTCN_Typedescriptor_t::GENERALSTRING};
+  &GeneralString_ber_, NULL, NULL, &GeneralString_xer_, NULL, NULL, TTCN_Typedescriptor_t::GENERALSTRING};
 
 const TTCN_Typedescriptor_t UniversalString_descr_={"UniversalString",
-  &UniversalString_ber_, NULL, NULL, &UniversalString_xer_, NULL, TTCN_Typedescriptor_t::UNIVERSALSTRING};
+  &UniversalString_ber_, NULL, NULL, &UniversalString_xer_, NULL, NULL, TTCN_Typedescriptor_t::UNIVERSALSTRING};
 
 const TTCN_Typedescriptor_t BMPString_descr_={"BMPString", &BMPString_ber_,
-  NULL, NULL, &BMPString_xer_, NULL, TTCN_Typedescriptor_t::BMPSTRING};
+  NULL, NULL, &BMPString_xer_, NULL, NULL, TTCN_Typedescriptor_t::BMPSTRING};
 
 
index 2e49375559337c42d6d56820b847f483917280ab..76323a4e0821fd3f0030686e94ad9d184c7ed04b 100644 (file)
 #include "Encdec.hh"
 #include "RInt.hh"
 #include "JSON_Tokenizer.hh"
-#include "Vector.hh"
 #ifdef TITAN_RUNTIME_2
 #include "Struct_of.hh"
 #include "XER.hh"
+#include "Vector.hh"
+#include "RefdIndex.hh"
 #endif
 
 struct ASN_BERdescriptor_t;
@@ -43,6 +44,7 @@ struct TTCN_Typedescriptor_t {
   const TTCN_TEXTdescriptor_t * const text; /**< Information for TEXT coding */
   const XERdescriptor_t * const xer; /**< Information for XER */
   const TTCN_JSONdescriptor_t * const json; /**< Information for JSON coding */
+  const TTCN_Typedescriptor_t * const oftype_descr; /**< Record-of element's type descriptor */
   /** ASN subtype
    *
    *  Used by classes implementing more than one ASN.1 type
@@ -642,7 +644,7 @@ class INTEGER;
  *
  */
 // Record_Of_Template can be found in Template.hh
-class Record_Of_Type : public Base_Type
+class Record_Of_Type : public Base_Type, public RefdIndexInterface
 {
   friend class Set_Of_Template;
   friend class Record_Of_Template;
@@ -776,7 +778,7 @@ public:
   virtual int XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
     const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned flavor, int indent, embed_values_enc_struct_t*) const;
   /// Helper for XER_encode_negtest
-  int encode_element(int i, const Erroneous_values_t* err_vals,
+  int encode_element(int i, const XERdescriptor_t& p_td, const Erroneous_values_t* err_vals,
     const Erroneous_descriptor_t* emb_descr,
     TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t* emb_val) const;
   virtual int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int, embed_values_dec_struct_t*);
@@ -794,8 +796,6 @@ public:
   /** @returns \c true  if this is a set-of type,
    *           \c false if this is a record-of type */
   virtual boolean is_set() const = 0;
-  /** return the type descriptor of the element */
-  virtual const TTCN_Typedescriptor_t* get_elem_descr() const = 0;
   /** creates an instance of the record's element class, using the default constructor */
   virtual Base_Type* create_elem() const = 0;
 
@@ -812,12 +812,12 @@ public:
   /** Indicates that the element at the given index is referenced by an 'out' or
     * 'inout' parameter and must not be deleted.
     * Used just before the actual function call that references the element. */
-  void add_refd_index(int index);
+  virtual void add_refd_index(int index);
   
   /** Indicates that the element at the given index is no longer referenced by
     * an 'out' or 'inout' parameter.
     * Used immediately after the actual function call that referenced the element. */
-  void remove_refd_index(int index);
+  virtual void remove_refd_index(int index);
 };
 
 extern boolean operator==(null_type null_value,
index 7d57b546e7824288811c01b7bb4c7023b504d141..66f3604ed4c9252252be0d4e3612f27884efa363 100644 (file)
@@ -124,21 +124,31 @@ void COMPONENT::kill() const
 
 void COMPONENT::set_param(Module_Param& param) {
   param.basic_check(Module_Param::BC_VALUE, "component reference (integer or null) value");
-  switch (param.get_type()) {
-  case Module_Param::MP_Integer:
-    component_value = (component)param.get_integer()->get_val();
-    break;
-  case Module_Param::MP_Ttcn_Null:
+  if (Ttcn_String_Parsing::happening()) {
+    // accept all component values in case it's a string2ttcn operation
+    switch (param.get_type()) {
+    case Module_Param::MP_Integer:
+      component_value = (component)param.get_integer()->get_val();
+      break;
+    case Module_Param::MP_Ttcn_Null:
+      component_value = NULL_COMPREF;
+      break;
+    case Module_Param::MP_Ttcn_mtc:
+      component_value = MTC_COMPREF;
+      break;
+    case Module_Param::MP_Ttcn_system:
+      component_value = SYSTEM_COMPREF;
+      break;
+    default:
+      param.type_error("component reference (integer or null) value");
+    }
+  }
+  else {
+    // only accept the null value if it's a module parameter
+    if (Module_Param::MP_Ttcn_Null != param.get_type()) {
+      param.error("Only the 'null' value is allowed for module parameters of type 'component'.");
+    }
     component_value = NULL_COMPREF;
-    break;
-  case Module_Param::MP_Ttcn_mtc:
-    component_value = MTC_COMPREF;
-    break;
-  case Module_Param::MP_Ttcn_system:
-    component_value = SYSTEM_COMPREF;
-    break;
-  default:
-    param.type_error("component reference (integer or null) value");
   }
 }
 
index 50c1c919e231a08cc56545ebd49e09e2e2139252..59d6a43cf586096d963dde9ed0e628e6df375ec9 100644 (file)
@@ -793,9 +793,66 @@ int FLOAT::XER_encode(const XERdescriptor_t& p_td,
   return (int)p_buf.get_len() - encoded_length;
 }
 
+boolean FLOAT::is_float(const char* p_str)
+{
+  bool first_digit = false; // first digit reached
+  bool decimal_point = false; // decimal point (.) reached
+  bool exponent_mark = false; // exponential mark (e or E) reached
+  bool exponent_sign = false; // sign of the exponential (- or +) reached
+  
+  if ('-' == *p_str || '+' == *p_str) {
+    ++p_str;
+  }
+  
+  while (0 != *p_str) {
+    switch(*p_str) {
+    case '.':
+      if (decimal_point || exponent_mark || !first_digit) {
+        return false;
+      }
+      decimal_point = true;
+      first_digit = false;
+      break;
+    case 'e':
+    case 'E':
+      if (exponent_mark || !first_digit) {
+        return false;
+      }
+      exponent_mark = true;
+      first_digit = false;
+      break;
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      first_digit = true;
+      break;
+    case '-':
+    case '+':
+      if (exponent_sign || !exponent_mark || first_digit) {
+        return false;
+      }
+      exponent_sign = true;
+      break;
+    default:
+      return false;
+    }
+    
+    ++p_str; 
+  }
+  return first_digit;
+}
+
 int FLOAT::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
   unsigned int flavor, embed_values_dec_struct_t*)
 {
+  bound_flag = false;
   int exer  = is_exer(flavor);
   int success = reader.Ok(), depth = -1;
   if (success <= 0) return 0;
@@ -807,8 +864,10 @@ int FLOAT::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
 tagless:
     const char * value = (const char *)reader.Value();
 
-    if (value && sscanf(value, "%lf", &float_value))
+    if (value && is_float(value)) {
       bound_flag = true;
+      sscanf(value, "%lf", &float_value);
+    }
 
     // Let the caller do reader.AdvanceAttribute();
   }
@@ -828,8 +887,10 @@ tagless:
       }
       else if (XML_READER_TYPE_TEXT == type && depth != -1) {
         const char * value = (const char*)reader.Value();
-        if (value && sscanf(value, "%lf", &float_value) == 1)
+        if (value && is_float(value)) {
           bound_flag = true;
+          sscanf(value, "%lf", &float_value);
+        }
       }
       else if (XML_READER_TYPE_END_ELEMENT == type) {
         verify_end(reader, p_td, depth, exer);
index 013d39de728a33e56fd9ec38289b00c3478645bf..18e6faa35d842c40c9726a51aed65b77cec5590b 100644 (file)
@@ -41,6 +41,10 @@ class FLOAT : public Base_Type {
 
   boolean bound_flag;
   ttcn3float float_value;
+  
+  /** Returns true if the string parameter contains the string representation 
+    * of a real number, otherwise returns false. */
+  boolean is_float(const char* p_str);
 
 public:
 
index ff35320ae46f8d33a6447c846b212bf3cb604c8f..ce0f040b69150c38348aeb9ee231e255a0a2d136 100644 (file)
@@ -12,9 +12,13 @@ include $(TOP)/Makefile.cfg
 SCHEMAS := TitanLoggerApi.xsd
 # Generated from `TitanLoggerApi.xsd'.
 GENERATED_MODULES := TitanLoggerApi.ttcn
+       
+PREGENERATOR_MODULES := PreGenRecordOf.ttcn
 
 GENERATED_LOGGERAPI_SOURCES := $(GENERATED_MODULES:.ttcn=.cc)
 GENERATED_LOGGERCONTROL_SOURCES := TitanLoggerControl.cc
+       
+PREGENERATED_SOURCES := $(PREGENERATOR_MODULES:.ttcn=.cc)
 
 ORIGINATORS := TitanLoggerApi.xsd TitanLoggerApi.ttcn TitanLoggerControl.ttcn gccversion.c \
 config_process.l config_process.y
@@ -33,12 +37,14 @@ endif
 # These directories (RT1/RT2) are replicated inside $(INCDIR)
 GENERATED_LOGGERAPI_SOURCES     := $(addprefix $(APIDIR)/,$(GENERATED_LOGGERAPI_SOURCES))
 GENERATED_LOGGERCONTROL_SOURCES := $(addprefix $(APIDIR)/,$(GENERATED_LOGGERCONTROL_SOURCES))
+PREGENERATED_SOURCES           := $(addprefix $(APIDIR)/,$(PREGENERATED_SOURCES))
 
 GENERATED_SOURCES := $(GENERATED_LOGGERAPI_SOURCES)          $(GENERATED_LOGGERCONTROL_SOURCES)         config_process.lex.cc config_process.tab.cc
+GENERATED_SOURCES += $(PREGENERATED_SOURCES)
 GENERATED_HEADERS := $(GENERATED_LOGGERAPI_SOURCES:.cc=.hh)  $(GENERATED_LOGGERCONTROL_SOURCES:.cc=.hh) config_process.tab.hh config_process.lex.hh
-GENERATED_HEADERS += $(GENERATED_LOGGERAPI_SOURCES:.cc=Simple.hh)
+GENERATED_HEADERS += $(GENERATED_LOGGERAPI_SOURCES:.cc=Simple.hh) $(PREGENERATED_SOURCES:.cc=.hh)
 GENERATED_OTHERS  := $(GENERATED_LOGGERAPI_SOURCES).compiled $(GENERATED_LOGGERCONTROL_SOURCES).compiled
-GENERATED_OTHERS  += config_process.output lex.backup
+GENERATED_OTHERS  += $(PREGENERATED_SOURCES).compiled config_process.output lex.backup
 
 TTCN_COMPILER_FLAGS :=
 ifeq ($(FUNCTION_TEST_RUNTIME), yes)
@@ -157,7 +163,7 @@ Port.hh Event_Handler.hh Struct_of.hh Array.hh Optional.hh Textbuf.hh Encdec.hh
 Module_list.hh Parameters.h Addfunc.hh RAW.hh BER.hh TEXT.hh ASN_Null.hh \
 ASN_Any.hh ASN_External.hh ASN_EmbeddedPDV.hh ASN_CharacterString.hh XER.hh \
 XmlReader.hh cversion.h TitanLoggerControl.ttcn TitanLoggerApi.xsd Vector.hh \
-JSON.hh Profiler.hh
+JSON.hh Profiler.hh RefdIndex.hh
 # Copied during "make install"
 
 ifdef REGEX_DIR
@@ -257,6 +263,7 @@ endif
 endif
        mkdir -p $(INCDIR)/$(APIDIR)
        cp $(APIDIR)/TitanLoggerApi*.hh $(INCDIR)/$(APIDIR)
+       cp $(APIDIR)/PreGenRecordOf.hh $(INCDIR)/$(APIDIR)
 
 # # # # executables
 single$(RT2_SUFFIX)$(EXESUFFIX): $(LIBRARY)
@@ -350,6 +357,17 @@ $(GENERATED_LOGGERCONTROL_SOURCES).compiled:: TitanLoggerControl.ttcn
        mkdir -p $(APIDIR)
        ../compiler2/compiler$(EXESUFFIX) $(TTCN_COMPILER_FLAGS) $^ - $?
        touch $@
+       
+$(PREGENERATED_SOURCES): $(PREGENERATED_SOURCES).compiled
+       @if [ ! -f $@ ]; then $(RM) $<; $(MAKE) $<; fi
+
+$(PREGENERATED_SOURCES).compiled:: ../compiler2/compiler$(EXESUFFIX)
+       @if [ -f $@ ]; then $(RM) $@; $(MAKE) $@; fi
+
+$(PREGENERATED_SOURCES).compiled:: $(PREGENERATOR_MODULES)
+       mkdir -p $(APIDIR)
+       ../compiler2/compiler$(EXESUFFIX) -F $(TTCN_COMPILER_FLAGS) $^ - $?
+       touch $@
 
 include ../Makefile.genrules
 
index a382c4d700bd3c054de534c1c68864f44ef16221..e6f19ba6ca21dce68fe9250c9e86667e68fe8b61 100644 (file)
@@ -95,8 +95,6 @@ void Module_List::pre_init_modules()
 {
   for (TTCN_Module *list_iter = list_head; list_iter != NULL;
     list_iter = list_iter->list_next) list_iter->pre_init_module();
-
-  send_versions();
 }
 
 void Module_List::post_init_modules()
index 85e14757f23dc0710bacbf2bfcc0d525c40cd6b0..3ac4d32faeabde6ec9e2b7b73928a7f35559847f 100644 (file)
 enum optional_sel { OPTIONAL_UNBOUND, OPTIONAL_OMIT, OPTIONAL_PRESENT };
 
 template <typename T_type>
-class OPTIONAL : public Base_Type {
+class OPTIONAL : public Base_Type 
+#ifdef TITAN_RUNTIME_2
+  , public RefdIndexInterface
+#endif
+{
   /** The value, if present (owned by OPTIONAL) 
     * In Runtime2 the pointer is null, when the value is not present.
     * In Runtime1 its presence is indicated by the optional_selection member. */
@@ -319,19 +323,13 @@ public:
     * 'inout' or 'out' parameter to a function (only in Runtime2).
     * Sets the optional value to present (this would be done by the indexing operation
     * anyway) and redirects the call to the optional value. */
-  void add_refd_index(int index);
+  virtual void add_refd_index(int index);
   
   /** Called after an element of an optional record of/set of is passed as an
     * 'inout' or 'out' parameter to a function (only in Runtime2).
     * Redirects the call to the optional value. */
-  void remove_refd_index(int index);
+  virtual void remove_refd_index(int index);
 #endif
-  
-  /** Called before an element of an optional record of/set of is passed as an
-    * 'inout' or 'out' parameter to a function. Returns the size of the record of/
-    * set of.
-    * Redirects the call to the optional value. */
-  int size_of();
 };
 
 #if HAVE_GCC(4,6)
@@ -827,14 +825,20 @@ void OPTIONAL<T_type>::add_refd_index(int index)
 {
   ++param_refs;
   set_to_present();
-  optional_value->add_refd_index(index);
+  RefdIndexInterface* refd_opt_val = dynamic_cast<RefdIndexInterface*>(optional_value);
+  if (0 != refd_opt_val) {
+    refd_opt_val->add_refd_index(index);
+  }
 }
 
 template<typename T_type>
 void OPTIONAL<T_type>::remove_refd_index(int index)
 {
   --param_refs;
-  optional_value->remove_refd_index(index);
+  RefdIndexInterface* refd_opt_val = dynamic_cast<RefdIndexInterface*>(optional_value);
+  if (0 != refd_opt_val) {
+    refd_opt_val->remove_refd_index(index);
+  }
 }
 #endif
 
@@ -1005,6 +1009,12 @@ OPTIONAL<T_type>::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
         // we already checked for exer==1
         if (!check_namespace((const char*)reader.NamespaceUri(), p_td)) break;
 
+        // set to omit if the attribute is empty
+        const char * value = (const char *)reader.Value();
+        if (strlen(value) == 0) {
+          break;
+        }
+        
         set_to_present();
         optional_value->XER_decode(p_td, reader, flavor, emb_val);
         goto finished;
index ddd0242c8c7587d52bc1f7c2d260f677a84071c1..2f6bdd22ead60a26c7b2e9280adec942d6c8e556 100644 (file)
@@ -24,6 +24,9 @@
 #include "Error.hh"
 #include "Encdec.hh"
 #include "TCov.hh"
+#ifdef LINUX
+#include <execinfo.h>
+#endif  
 
 #ifdef LICENSE
 #include "../common/license.h"
@@ -35,7 +38,7 @@ const char * stored_argv = "Unidentified program";
 
 //static const char segfault[] = " : Segmentation fault occurred\n";
 
-void signal_handler(int)
+void signal_handler(int signum)
 {
   int retval;
   time_t now=time(0);
@@ -44,7 +47,7 @@ void signal_handler(int)
   struct tm *tmp;
   tmp=localtime(&now);
   if(tmp==NULL){
-    fprintf(stderr,"<Unknown> %s: Segmentation fault occurred\n",stored_argv);
+    fprintf(stderr,"<Unknown> %s: %s\n",stored_argv, signum==SIGABRT?"Abort was called":"Segmentation fault occurred");
   } else {
 /*  retval = write(STDERR_FILENO, stored_argv, strlen(stored_argv));
   retval = write(STDERR_FILENO, segfault , sizeof(segfault)-1); // sizeof includes \0
@@ -52,10 +55,18 @@ void signal_handler(int)
   (void)retval;
 */
     retval=strftime(ts,60,"%F %T",tmp);
-    fprintf(stderr,"%s %s: Segmentation fault occurred\n",ts,stored_argv);
+    fprintf(stderr,"%s %s: %s\n",ts,stored_argv,signum==SIGABRT?"Abort was called":"Segmentation fault occurred");
   }
   fflush(stderr);
+#ifdef LINUX
+  int nptrs;
+  void *buffer[100];
+  nptrs = backtrace(buffer, 100);
+  backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
   
+  fflush(stderr);
+#endif  
+  signal(SIGABRT, SIG_DFL);
   abort();
 }
 
@@ -185,6 +196,7 @@ int main(int argc, char *argv[])
   sigemptyset(&act.sa_mask);
   act.sa_flags = 0;
   sigaction(SIGSEGV, &act, 0);
+  sigaction(SIGABRT, &act, 0);
 
 #ifdef MEMORY_DEBUG
   debug_new_counter.set_program_name(argv[0]);
diff --git a/core/PreGenRecordOf.ttcn b/core/PreGenRecordOf.ttcn
new file mode 100644 (file)
index 0000000..da2b0d5
--- /dev/null
@@ -0,0 +1,83 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2000-2015 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
+///////////////////////////////////////////////////////////////////////////////
+
+// This module contains 'record of' and 'set of' type declarations for certain base types.
+// It is used for pre-generating the C++ classes that represent these types,
+// so they are not re-generated every time they are declared in TTCN-3 or ASN.1
+// modules.
+module PreGenRecordOf {
+
+// 'record of' declarations (regular):
+type record of boolean PREGEN_RECORD_OF_BOOLEAN;
+
+type record of integer PREGEN_RECORD_OF_INTEGER;
+
+type record of float PREGEN_RECORD_OF_FLOAT;
+
+type record of bitstring PREGEN_RECORD_OF_BITSTRING;
+
+type record of hexstring PREGEN_RECORD_OF_HEXSTRING;
+
+type record of octetstring PREGEN_RECORD_OF_OCTETSTRING;
+
+type record of charstring PREGEN_RECORD_OF_CHARSTRING;
+
+type record of universal charstring PREGEN_RECORD_OF_UNIVERSAL_CHARSTRING;
+
+// 'record of' declarations (with optimized memory allocation):
+type record of boolean PREGEN_RECORD_OF_BOOLEAN_OPTIMIZED with { extension "optimize:memalloc" };
+
+type record of integer PREGEN_RECORD_OF_INTEGER_OPTIMIZED with { extension "optimize:memalloc" };
+
+type record of float PREGEN_RECORD_OF_FLOAT_OPTIMIZED with { extension "optimize:memalloc" };
+
+type record of bitstring PREGEN_RECORD_OF_BITSTRING_OPTIMIZED with { extension "optimize:memalloc" };
+
+type record of hexstring PREGEN_RECORD_OF_HEXSTRING_OPTIMIZED with { extension "optimize:memalloc" };
+
+type record of octetstring PREGEN_RECORD_OF_OCTETSTRING_OPTIMIZED with { extension "optimize:memalloc" };
+
+type record of charstring PREGEN_RECORD_OF_CHARSTRING_OPTIMIZED with { extension "optimize:memalloc" };
+
+type record of universal charstring PREGEN_RECORD_OF_UNIVERSAL_CHARSTRING_OPTIMIZED with { extension "optimize:memalloc" };
+
+// 'set of' declarations (regular):
+type set of boolean PREGEN_SET_OF_BOOLEAN;
+
+type set of integer PREGEN_SET_OF_INTEGER;
+
+type set of float PREGEN_SET_OF_FLOAT;
+
+type set of bitstring PREGEN_SET_OF_BITSTRING;
+
+type set of hexstring PREGEN_SET_OF_HEXSTRING;
+
+type set of octetstring PREGEN_SET_OF_OCTETSTRING;
+
+type set of charstring PREGEN_SET_OF_CHARSTRING;
+
+type set of universal charstring PREGEN_SET_OF_UNIVERSAL_CHARSTRING;
+
+// 'set of' declarations (with optimized memory allocation):
+type set of boolean PREGEN_SET_OF_BOOLEAN_OPTIMIZED with { extension "optimize:memalloc" };
+
+type set of integer PREGEN_SET_OF_INTEGER_OPTIMIZED with { extension "optimize:memalloc" };
+
+type set of float PREGEN_SET_OF_FLOAT_OPTIMIZED with { extension "optimize:memalloc" };
+
+type set of bitstring PREGEN_SET_OF_BITSTRING_OPTIMIZED with { extension "optimize:memalloc" };
+
+type set of hexstring PREGEN_SET_OF_HEXSTRING_OPTIMIZED with { extension "optimize:memalloc" };
+
+type set of octetstring PREGEN_SET_OF_OCTETSTRING_OPTIMIZED with { extension "optimize:memalloc" };
+
+type set of charstring PREGEN_SET_OF_CHARSTRING_OPTIMIZED with { extension "optimize:memalloc" };
+
+type set of universal charstring PREGEN_SET_OF_UNIVERSAL_CHARSTRING_OPTIMIZED with { extension "optimize:memalloc" };
+
+}
index 860e5c8a08b1afbb42861aace8094cfdbd8e70e0..e9d3b9f8d57140ddf04906ba1867a9720e5af385 100644 (file)
@@ -7,13 +7,83 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "Profiler.hh"
-#include <sys/time.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "JSON_Tokenizer.hh"
 #include "memory.h"
 #include "Runtime.hh"
+#include <unistd.h>
+#include "Component.hh"
+
+////////////////////////////////////
+//////// timeval operations ////////
+////////////////////////////////////
+
+/** Reads a timeval value from the given string. The parameter must contain the
+  * string representation of a real number with 6 digits after the decimal dot. */
+static timeval string2timeval(const char* str)
+{
+  // read and store the first part (atoi will read until the decimal dot)
+  long int sec = atoi(str);
+  timeval tv;
+  tv.tv_sec = sec;
+
+  do {
+    // step over each digit
+    sec /= 10;
+    ++str;
+  }
+  while (sec > 9);
+
+  // step over the decimal dot and read the second part of the number
+  tv.tv_usec = atoi(str + 1);
+  return tv;
+}
+
+/** Returns the string representation of a real number (with 6 digits after the
+  * decimal dot) equivalent to the timeval parameter. 
+  * The returned character pointer needs to be freed. */
+static char* timeval2string(timeval tv)
+{
+  // convert the first part and set the second part to all zeros
+  char* str = mprintf("%ld.000000", tv.tv_sec);
+  
+  // go through each digit of the second part and add them to the zeros in the string
+  size_t pos = mstrlen(str) - 1;
+  while (tv.tv_usec > 0) {
+    str[pos] += tv.tv_usec % 10;
+    tv.tv_usec /= 10;
+    --pos;
+  }
+  return str;
+}
+
+/** Adds the two timeval parameters together and returns the result. */
+static timeval add_timeval(const timeval operand1, const timeval operand2)
+{
+  timeval tv;
+  tv.tv_usec = operand1.tv_usec + operand2.tv_usec;
+  tv.tv_sec = operand1.tv_sec + operand2.tv_sec;
+  if (tv.tv_usec >= 1000000) {
+    ++tv.tv_sec;
+    tv.tv_usec -= 1000000;
+  }
+  return tv;
+}
+
+/** Subtracts the second timeval parameter from the first one and returns the result. */
+static timeval subtract_timeval(const timeval operand1, const timeval operand2)
+{
+  timeval tv;
+  tv.tv_usec = operand1.tv_usec - operand2.tv_usec;
+  tv.tv_sec = operand1.tv_sec - operand2.tv_sec;
+  if (tv.tv_usec < 0) {
+    --tv.tv_sec;
+    tv.tv_usec += 1000000;
+  }
+  return tv;
+}
 
 ////////////////////////////////////
 ////////// TTCN3_Profiler //////////
@@ -22,8 +92,8 @@
 TTCN3_Profiler ttcn3_prof;
 
 TTCN3_Profiler::TTCN3_Profiler()
-: disable_profiler(FALSE), disable_coverage(FALSE), aggregate_data(FALSE)
-, disable_stats(FALSE)
+: stopped(FALSE), disable_profiler(FALSE), disable_coverage(FALSE)
+, aggregate_data(FALSE), disable_stats(FALSE), stats_flags(STATS_ALL)
 {
   database_filename = mcopystr("profiler.db");
   stats_filename = mcopystr("profiler.stats");
@@ -32,8 +102,19 @@ TTCN3_Profiler::TTCN3_Profiler()
 
 TTCN3_Profiler::~TTCN3_Profiler()
 {
-  if (!disable_profiler || !disable_coverage) {
-    import_data();
+  if (!profiler_db.empty() && (!disable_profiler || !disable_coverage)) {
+    if (aggregate_data && (TTCN_Runtime::is_single() || TTCN_Runtime::is_hc())) {
+      // import the data from the previous run
+      import_data();
+    }
+    if (TTCN_Runtime::is_hc()) {
+      // import the data gathered by the other processes (the import function
+      // waits for them to finish exporting)
+      import_data(MTC_COMPREF);
+      for (size_t i = 0; i < ptc_list.size(); ++i) {
+        import_data(ptc_list[i]);
+      }
+    }
     export_data();
     if (!disable_stats && (TTCN_Runtime::is_single() || TTCN_Runtime::is_hc())) {
       print_stats();
@@ -49,6 +130,27 @@ TTCN3_Profiler::~TTCN3_Profiler()
   Free(stats_filename);
 }
 
+void TTCN3_Profiler::start()
+{
+  if (stopped) {
+    set_prev(disable_profiler ? -1 : TTCN3_Stack_Depth::depth(), NULL, -1);
+    stopped = FALSE;
+  }
+}
+
+void TTCN3_Profiler::stop()
+{
+  if (!stopped) {
+    if (NULL != prev_file) {
+      // update the previous line's time
+      timeval elapsed = subtract_timeval(get_time(), prev_time);
+      add_line_time(elapsed, get_element(prev_file), prev_line);
+      TTCN3_Stack_Depth::update_stack_elapsed(elapsed);
+    }
+    stopped = TRUE;
+  }
+}
+
 void TTCN3_Profiler::set_disable_profiler(boolean p_disable_profiler)
 {
   disable_profiler = p_disable_profiler;
@@ -81,41 +183,94 @@ void TTCN3_Profiler::set_disable_stats(boolean p_disable_stats)
   disable_stats = p_disable_stats;
 }
 
+void TTCN3_Profiler::reset_stats_flags()
+{
+  stats_flags = 0;
+}
+
+void TTCN3_Profiler::add_stats_flags(unsigned int p_flags)
+{
+  stats_flags |= p_flags;
+}
+
 boolean TTCN3_Profiler::is_profiler_disabled() const
 {
   return disable_profiler;
 }
 
+boolean TTCN3_Profiler::is_running() const
+{
+  return !stopped;
+}
+
+void TTCN3_Profiler::add_ptc(component p_comp_ref)
+{
+  ptc_list.push_back(p_comp_ref);
+}
+
 #define IMPORT_FORMAT_ERROR(cond) \
   if (cond) { \
     TTCN_warning("Database format is invalid. Profiler and/or code coverage data will not be loaded."); \
     return; \
   }
 
-void TTCN3_Profiler::init_data_file()
+void TTCN3_Profiler::import_data(component p_comp_ref /* = NULL_COMPREF */)
 {
-  // delete the database file (from the previous run) if data aggregation is not set
-  if (!aggregate_data && (!disable_profiler || !disable_coverage)) {
-    remove(database_filename);
+  char* file_name = NULL;
+  if (NULL_COMPREF == p_comp_ref) {
+    // this is the main database file (from the previous run), no suffix needed
+    file_name = database_filename;
   }
-}
-
-void TTCN3_Profiler::import_data()
-{
+  else if (MTC_COMPREF == p_comp_ref) {
+    // this is the database for the MTC, suffix the file name with "mtc"
+    file_name = mprintf("%s.mtc", database_filename);
+  }
+  else {
+    // this is the database for one of the PTCs, suffix the file name with the
+    // component reference
+    file_name = mprintf("%s.%d", database_filename, p_comp_ref);
+  }
+  
   // open the file, if it exists
-  FILE* file = fopen(database_filename, "r");
-  if (NULL == file) {
-    return;
+  int file_size = 0;
+  FILE* file = fopen(file_name, "r");
+  if (NULL != file) {
+    // get the file size
+    fseek(file, 0, SEEK_END);
+    file_size = ftell(file);
+  }
+  while (0 == file_size) {
+    if (NULL_COMPREF == p_comp_ref) {
+      // no data from the previous run
+      return;
+    }
+    // as for the process-specific database files: keep reading until it appears
+    if (NULL != file) {
+      fclose(file);
+    }
+    usleep(1000);
+    file = fopen(file_name, "r");
+    if (NULL != file) {
+      // refresh the file size
+      fseek(file, 0, SEEK_END);
+      file_size = ftell(file);
+    }
   }
   
-  // get the file size
-  fseek(file, 0, SEEK_END);
-  int file_size = ftell(file);
+  // rewind the file (the file pointer has been moved to the end of the file to
+  // calculate its size)
   rewind(file);
   
   // read the entire file into a character buffer
   char* buffer = (char*)Malloc(file_size);
   fread(buffer, 1, file_size, file);
+  fclose(file);
+  
+  if (NULL_COMPREF != p_comp_ref) {
+    // the process-specific database file is no longer needed
+    remove(file_name);
+    Free(file_name);
+  }
   
   // initialize a JSON tokenizer with the buffer
   JSON_Tokenizer json(buffer, file_size);
@@ -202,33 +357,32 @@ void TTCN3_Profiler::import_data()
         func_data.name = function_name;
         func_data.lineno = start_line;
         func_data.exec_count = 0;
-        func_data.total_time = 0.0;
+        func_data.total_time.tv_sec = 0;
+        func_data.total_time.tv_usec = 0;
         profiler_db[file_index].functions.push_back(func_data);
       }
       
-      if (!disable_coverage) {
-        // function execution count:
-        json.get_next_token(&token, &value, &value_len);
-        IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 15 ||
-          0 != strncmp(value, "execution count", value_len));
+      // function execution count:
+      json.get_next_token(&token, &value, &value_len);
+      IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 15 ||
+        0 != strncmp(value, "execution count", value_len));
 
-        // read the execution count and add it to the current data
-        json.get_next_token(&token, &value, &value_len);
-        IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token);
-        profiler_db[file_index].functions[function_index].exec_count += atoi(value);
-      }
-      
-      if (!disable_profiler) {
-        // total function execution time:
-        json.get_next_token(&token, &value, &value_len);
-        IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 10 ||
-          0 != strncmp(value, "total time", value_len));
+      // read the execution count and add it to the current data
+      json.get_next_token(&token, &value, &value_len);
+      IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token);
+      profiler_db[file_index].functions[function_index].exec_count += atoi(value);
 
-        // read the total time and add it to the current data
-        json.get_next_token(&token, &value, &value_len);
-        IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token);
-        profiler_db[file_index].functions[function_index].total_time += atof(value);
-      }
+      // total function execution time:
+      json.get_next_token(&token, &value, &value_len);
+      IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 10 ||
+        0 != strncmp(value, "total time", value_len));
+
+      // read the total time and add it to the current data
+      // note: the database contains a real number, this needs to be split into 2 integers
+      json.get_next_token(&token, &value, &value_len);
+      IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token);
+      profiler_db[file_index].functions[function_index].total_time = add_timeval(
+        profiler_db[file_index].functions[function_index].total_time, string2timeval(value));
 
       // end of the function's object
       json.get_next_token(&token, NULL, NULL);
@@ -251,6 +405,7 @@ void TTCN3_Profiler::import_data()
     IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_START != token);
     json.get_next_token(&token, NULL, NULL);
     while (JSON_TOKEN_OBJECT_START == token) {
+      int line_index = 0;
       
       // line number:
       json.get_next_token(&token, &value, &value_len);
@@ -262,39 +417,32 @@ void TTCN3_Profiler::import_data()
       IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token);
       int lineno = atoi(value);
       IMPORT_FORMAT_ERROR(lineno < 0);
-      size_t line_no = lineno;
-      if (line_no >= profiler_db[file_index].lines.size()) {
-        for (size_t i = profiler_db[file_index].lines.size(); i <= line_no; ++i) {
-          profiler_db_item_t::profiler_line_data_t line_data;
-          line_data.total_time = 0.0;
-          line_data.exec_count = 0;
-          profiler_db[file_index].lines.push_back(line_data);
-        }
+      line_index = get_line(file_index, lineno);
+      if (-1 == line_index) {
+        create_line(file_index, lineno);
+        line_index = profiler_db[file_index].lines.size() - 1;
       }
       
-      if (!disable_coverage) {
-        // line execution count:
-        json.get_next_token(&token, &value, &value_len);
-        IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 15 ||
-          0 != strncmp(value, "execution count", value_len));
+      // line execution count:
+      json.get_next_token(&token, &value, &value_len);
+      IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 15 ||
+        0 != strncmp(value, "execution count", value_len));
 
-        // read the execution count and add it to the current data
-        json.get_next_token(&token, &value, &value_len);
-        IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token);
-        profiler_db[file_index].lines[line_no].exec_count += atoi(value);
-      }
+      // read the execution count and add it to the current data
+      json.get_next_token(&token, &value, &value_len);
+      IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token);
+      profiler_db[file_index].lines[line_index].exec_count += atoi(value);
       
-      if (!disable_profiler) {
-        // total line execution time:
-        json.get_next_token(&token, &value, &value_len);
-        IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 10 ||
-          0 != strncmp(value, "total time", value_len));
+      // total line execution time:
+      json.get_next_token(&token, &value, &value_len);
+      IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 10 ||
+        0 != strncmp(value, "total time", value_len));
 
-        // read the total time and add it to the current data
-        json.get_next_token(&token, &value, &value_len);
-        IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token);
-        profiler_db[file_index].lines[line_no].total_time += atof(value);
-      }
+      // read the total time and add it to the current data
+      json.get_next_token(&token, &value, &value_len);
+      IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token);
+      profiler_db[file_index].lines[line_index].total_time = add_timeval(
+        profiler_db[file_index].lines[line_index].total_time, string2timeval(value));
 
       // end of the line's object
       json.get_next_token(&token, NULL, NULL);
@@ -321,19 +469,36 @@ void TTCN3_Profiler::import_data()
 
 void TTCN3_Profiler::export_data()
 {
-  // nothing to export if the database is empty
-  if (profiler_db.empty()) {
-    return;
+  char* file_name = NULL;
+  if (TTCN_Runtime::is_single() || TTCN_Runtime::is_hc()) {
+    // this is the main database file, no suffix needed
+    file_name = database_filename;
+  }
+  else if (TTCN_Runtime::is_mtc()) {
+    // this is the database for the MTC, suffix the file name with "mtc"
+    file_name = mprintf("%s.mtc", database_filename);
+  }
+  else {
+    // this is the database for one of the PTCs, suffix the file name with the
+    // component reference
+    file_name = mprintf("%s.%d", database_filename, (component)self);
   }
   
   // check whether the file can be opened for writing
-  FILE* file = fopen(database_filename, "w");
+  FILE* file = fopen(file_name, "w");
   if (NULL == file) {
     TTCN_warning("Could not open file '%s' for writing. Profiler and/or code coverage "
-      "data will not be saved.", database_filename);
+      "data will not be saved.", file_name);
+    if (file_name != database_filename) {
+      Free(file_name);
+    }
     return;
   }
   
+  if (file_name != database_filename) {
+    Free(file_name);
+  }
+  
   // use the JSON tokenizer to create a JSON document from the database
   JSON_Tokenizer json(true);
   
@@ -354,40 +519,47 @@ void TTCN3_Profiler::export_data()
     json.put_next_token(JSON_TOKEN_NAME, "functions");
     json.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
     for (size_t j = 0; j < profiler_db[i].functions.size(); ++j) {
+      // only store functions with actual data
+      if ((0 != profiler_db[i].functions[j].total_time.tv_sec &&
+           0 != profiler_db[i].functions[j].total_time.tv_usec) ||
+          0 != profiler_db[i].functions[j].exec_count) {
       
-      // the data is stored in an object for each function
-      json.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
-      
-      // store the function name
-      json.put_next_token(JSON_TOKEN_NAME, "name");
-      char* func_name_str = mprintf("\"%s\"", profiler_db[i].functions[j].name);
-      json.put_next_token(JSON_TOKEN_STRING, func_name_str);
-      Free(func_name_str);
-      
-      // store the function start line
-      json.put_next_token(JSON_TOKEN_NAME, "start line");
-      char* start_line_str = mprintf("%d", profiler_db[i].functions[j].lineno);
-      json.put_next_token(JSON_TOKEN_NUMBER, start_line_str);
-      Free(start_line_str);
-      
-      if (!disable_coverage) {
+        // the data is stored in an object for each function
+        json.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+
+        // store the function name
+        json.put_next_token(JSON_TOKEN_NAME, "name");
+        char* func_name_str = mprintf("\"%s\"", profiler_db[i].functions[j].name);
+        json.put_next_token(JSON_TOKEN_STRING, func_name_str);
+        Free(func_name_str);
+
+        // store the function start line
+        json.put_next_token(JSON_TOKEN_NAME, "start line");
+        char* start_line_str = mprintf("%d", profiler_db[i].functions[j].lineno);
+        json.put_next_token(JSON_TOKEN_NUMBER, start_line_str);
+        Free(start_line_str);
+
         // store the function execution count
         json.put_next_token(JSON_TOKEN_NAME, "execution count");
-        char* exec_count_str = mprintf("%d", profiler_db[i].functions[j].exec_count);
+        char* exec_count_str = mprintf("%d", disable_coverage ? 0 :
+          profiler_db[i].functions[j].exec_count);
         json.put_next_token(JSON_TOKEN_NUMBER, exec_count_str);
         Free(exec_count_str);
-      }
-      
-      if (!disable_profiler) {
+
         // store the function's total execution time
         json.put_next_token(JSON_TOKEN_NAME, "total time");
-        char* exec_count_str = mprintf("%.6lf", profiler_db[i].functions[j].total_time);
-        json.put_next_token(JSON_TOKEN_NUMBER, exec_count_str);
-        Free(exec_count_str);
+        if (disable_profiler) {
+          json.put_next_token(JSON_TOKEN_NUMBER, "0.000000");
+        }
+        else {
+          char* total_time_str = timeval2string(profiler_db[i].functions[j].total_time);
+          json.put_next_token(JSON_TOKEN_NUMBER, total_time_str);
+          Free(total_time_str);
+        }
+
+        // end of function object
+        json.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
       }
-      
-      // end of function object
-      json.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
     }
     
     // end of function data array
@@ -397,34 +569,38 @@ void TTCN3_Profiler::export_data()
     json.put_next_token(JSON_TOKEN_NAME, "lines");
     json.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
     for (size_t j = 0; j < profiler_db[i].lines.size(); ++j) {
-      if (0.0 != profiler_db[i].lines[j].total_time ||
+      // only store lines with actual data
+      if ((0 != profiler_db[i].lines[j].total_time.tv_sec &&
+           0 != profiler_db[i].lines[j].total_time.tv_usec) ||
           0 != profiler_db[i].lines[j].exec_count) {
-        
+
         // store line data in an object
         json.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
-        
+
         // store the line number
         json.put_next_token(JSON_TOKEN_NAME, "number");
-        char* line_number_str = mprintf("%lu", j);
+        char* line_number_str = mprintf("%d", profiler_db[i].lines[j].lineno);
         json.put_next_token(JSON_TOKEN_NUMBER, line_number_str);
         Free(line_number_str);
-        
-        if (!disable_coverage) {
-          // store the line execution count
-          json.put_next_token(JSON_TOKEN_NAME, "execution count");
-          char* exec_count_str = mprintf("%d", profiler_db[i].lines[j].exec_count);
-          json.put_next_token(JSON_TOKEN_NUMBER, exec_count_str);
-          Free(exec_count_str);
-        }
 
-        if (!disable_profiler) {
-          // store the line's total execution time
-          json.put_next_token(JSON_TOKEN_NAME, "total time");
-          char* exec_count_str = mprintf("%.6lf", profiler_db[i].lines[j].total_time);
-          json.put_next_token(JSON_TOKEN_NUMBER, exec_count_str);
-          Free(exec_count_str);
+        // store the line execution count
+        json.put_next_token(JSON_TOKEN_NAME, "execution count");
+        char* exec_count_str = mprintf("%d", disable_coverage ? 0 :
+          profiler_db[i].lines[j].exec_count);
+        json.put_next_token(JSON_TOKEN_NUMBER, exec_count_str);
+        Free(exec_count_str);
+
+        // store the line's total execution time
+        json.put_next_token(JSON_TOKEN_NAME, "total time");
+        if (disable_profiler) {
+          json.put_next_token(JSON_TOKEN_NUMBER, "0.000000");
         }
-        
+        else {
+          char* total_time_str = timeval2string(profiler_db[i].lines[j].total_time);
+          json.put_next_token(JSON_TOKEN_NUMBER, total_time_str);
+          Free(total_time_str);
+        }
+
         // end of this line's object
         json.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
       }
@@ -445,6 +621,43 @@ void TTCN3_Profiler::export_data()
   fclose(file);
 }
 
+// Structure for one code line or function, used by print_stats for sorting
+struct stats_data_t {
+  const char* filename; // not owned
+  const char* funcname; // not owned, NULL for code lines that don't start a function
+  int lineno;
+  timeval total_time;
+  int exec_count;
+};
+
+// Compare function for sorting stats data based on total execution time (descending)
+int stats_data_cmp_time(const void* p_left, const void* p_right) {
+  const stats_data_t* p_left_data = (stats_data_t*)p_left;
+  const stats_data_t* p_right_data = (stats_data_t*)p_right;
+  if (p_left_data->total_time.tv_sec > p_right_data->total_time.tv_sec) return -1;
+  if (p_left_data->total_time.tv_sec < p_right_data->total_time.tv_sec) return 1;
+  if (p_left_data->total_time.tv_usec > p_right_data->total_time.tv_usec) return -1;
+  if (p_left_data->total_time.tv_usec < p_right_data->total_time.tv_usec) return 1;
+  return 0;
+}
+
+// Compare function for sorting stats data based on execution count (descending)
+int stats_data_cmp_count(const void* p_left, const void* p_right) {
+  return ((stats_data_t*)p_right)->exec_count - ((stats_data_t*)p_left)->exec_count;
+}
+
+// Compare function for sorting stats data based on total time per execution count (descending)
+int stats_data_cmp_avg(const void* p_left, const void* p_right) {
+  const stats_data_t* p_left_data = (stats_data_t*)p_left;
+  const stats_data_t* p_right_data = (stats_data_t*)p_right;
+  double left_time = p_left_data->total_time.tv_sec + p_left_data->total_time.tv_usec / 1000000.0;
+  double right_time = p_right_data->total_time.tv_sec + p_right_data->total_time.tv_usec / 1000000.0;
+  double diff = (right_time / p_right_data->exec_count) - (left_time / p_left_data->exec_count);
+  if (diff < 0) return -1;
+  if (diff > 0) return 1;
+  return 0;
+}
+
 void TTCN3_Profiler::print_stats() 
 {
   if (profiler_db.empty()) {
@@ -462,122 +675,804 @@ void TTCN3_Profiler::print_stats()
     , disable_coverage ? "" : "code coverage "
     , disable_profiler ? "######" : (disable_coverage ? "#########" : ""));
   
+  char* line_func_count_str = NULL;
+  if (stats_flags & STATS_NUMBER_OF_LINES) {
+    line_func_count_str = mcopystr(
+      "--------------------------------------\n"
+      "- Number of code lines and functions -\n"
+      "--------------------------------------\n");
+  }
+  
   // line data
-  char* line_data_str = mprintf(
-    "-------------------------------------------------\n"
-    "%s- Code line data (%s%s%s) -%s\n"
-    "-------------------------------------------------\n"
-    , disable_profiler ? "-------" : (disable_coverage ? "---------" : "")
-    , disable_profiler ? "" : "total time"
-    , (disable_profiler || disable_coverage) ? "" : " / "
-    , disable_coverage ? "" : "execution count"
-    , disable_profiler ? "------" : (disable_coverage ? "---------" : ""));
+  char* line_data_str = NULL;
+  if (stats_flags & STATS_LINE_DATA_RAW) {
+    line_data_str = mprintf(
+      "-------------------------------------------------\n"
+      "%s- Code line data (%s%s%s) -%s\n"
+      "-------------------------------------------------\n"
+      , disable_profiler ? "-------" : (disable_coverage ? "---------" : "")
+      , disable_profiler ? "" : "total time"
+      , (disable_profiler || disable_coverage) ? "" : " / "
+      , disable_coverage ? "" : "execution count"
+      , disable_profiler ? "------" : (disable_coverage ? "---------" : ""));
+  }
   
   // average time / exec count for lines
   char* line_avg_str = NULL;
-  if (!disable_coverage && !disable_profiler) {
+  if (!disable_coverage && !disable_profiler && (stats_flags & STATS_LINE_AVG_RAW)) {
     line_avg_str = mcopystr(
-      "-------------------------------------------------\n"
-      "- Average time / execution count for code lines -\n"
-      "-------------------------------------------------\n");
+      "-------------------------------------------\n"
+      "- Average time / execution for code lines -\n"
+      "-------------------------------------------\n");
   }
   
   // function data
-  char* func_data_str = mprintf(
-    "------------------------------------------------\n"
-    "%s- Function data (%s%s%s) -%s\n"
-    "------------------------------------------------\n"
-    , disable_profiler ? "-------" : (disable_coverage ? "---------" : "")
-    , disable_profiler ? "" : "total time"
-    , (disable_profiler || disable_coverage) ? "" : " / "
-    , disable_coverage ? "" : "execution count"
-    , disable_profiler ? "------" : (disable_coverage ? "---------" : ""));
+  char* func_data_str = NULL;
+  if (stats_flags & STATS_FUNC_DATA_RAW) {
+    func_data_str = mprintf(
+      "------------------------------------------------\n"
+      "%s- Function data (%s%s%s) -%s\n"
+      "------------------------------------------------\n"
+      , disable_profiler ? "-------" : (disable_coverage ? "---------" : "")
+      , disable_profiler ? "" : "total time"
+      , (disable_profiler || disable_coverage) ? "" : " / "
+      , disable_coverage ? "" : "execution count"
+      , disable_profiler ? "------" : (disable_coverage ? "---------" : ""));
+  }
   
   // average time / exec count for functions
   char* func_avg_str = NULL;
-  if (!disable_coverage && !disable_profiler) {
+  if (!disable_coverage && !disable_profiler && (stats_flags & STATS_FUNC_AVG_RAW)) {
     func_avg_str = mcopystr(
+      "------------------------------------------\n"
+      "- Average time / execution for functions -\n"
+      "------------------------------------------\n");
+  }
+  
+  char* line_time_sorted_mod_str = NULL;
+  if (!disable_profiler && (stats_flags & STATS_LINE_TIMES_SORTED_BY_MOD)) {
+    line_time_sorted_mod_str = mcopystr(
+      "------------------------------------------------\n"
+      "- Total time of code lines, sorted, per module -\n"
+      "------------------------------------------------\n");
+  }
+  
+  char* line_count_sorted_mod_str = NULL;
+  if (!disable_coverage && (stats_flags & STATS_LINE_COUNT_SORTED_BY_MOD)) {
+    line_count_sorted_mod_str = mcopystr(
+      "-----------------------------------------------------\n"
+      "- Execution count of code lines, sorted, per module -\n"
+      "-----------------------------------------------------\n");
+  }
+  
+  char* line_avg_sorted_mod_str = NULL;
+  if (!disable_profiler && !disable_coverage && (stats_flags & STATS_LINE_AVG_SORTED_BY_MOD)) {
+    line_avg_sorted_mod_str = mcopystr(
+      "--------------------------------------------------------------\n"
+      "- Average time / execution of code lines, sorted, per module -\n"
+      "--------------------------------------------------------------\n");
+  }
+  
+  char* line_time_sorted_tot_str = NULL;
+  if (!disable_profiler && (stats_flags & STATS_LINE_TIMES_SORTED_TOTAL)) {
+    line_time_sorted_tot_str = mcopystr(
+      "-------------------------------------------\n"
+      "- Total time of code lines, sorted, total -\n"
+      "-------------------------------------------\n");
+  }
+  
+  char* line_count_sorted_tot_str = NULL;
+  if (!disable_coverage && (stats_flags & STATS_LINE_COUNT_SORTED_TOTAL)) {
+    line_count_sorted_tot_str = mcopystr(
       "------------------------------------------------\n"
-      "- Average time / execution count for functions -\n"
+      "- Execution count of code lines, sorted, total -\n"
       "------------------------------------------------\n");
   }
   
+  char* line_avg_sorted_tot_str = NULL;
+  if (!disable_profiler && !disable_coverage && (stats_flags & STATS_LINE_AVG_SORTED_TOTAL)) {
+    line_avg_sorted_tot_str = mcopystr(
+      "---------------------------------------------------------\n"
+      "- Average time / execution of code lines, sorted, total -\n"
+      "---------------------------------------------------------\n");
+  }
+  
+  char* func_time_sorted_mod_str = NULL;
+  if (!disable_profiler && (stats_flags & STATS_FUNC_TIMES_SORTED_BY_MOD)) {
+    func_time_sorted_mod_str = mcopystr(
+      "-----------------------------------------------\n"
+      "- Total time of functions, sorted, per module -\n"
+      "-----------------------------------------------\n");
+  }
+  
+  char* func_count_sorted_mod_str = NULL;
+  if (!disable_coverage && (stats_flags & STATS_FUNC_COUNT_SORTED_BY_MOD)) {
+    func_count_sorted_mod_str = mcopystr(
+      "----------------------------------------------------\n"
+      "- Execution count of functions, sorted, per module -\n"
+      "----------------------------------------------------\n");
+  }
+  
+  char* func_avg_sorted_mod_str = NULL;
+  if (!disable_profiler && !disable_coverage && (stats_flags & STATS_FUNC_AVG_SORTED_BY_MOD)) {
+    func_avg_sorted_mod_str = mcopystr(
+      "-------------------------------------------------------------\n"
+      "- Average time / execution of functions, sorted, per module -\n"
+      "-------------------------------------------------------------\n");
+  }
+  
+  char* func_time_sorted_tot_str = NULL;
+  if (!disable_profiler && (stats_flags & STATS_FUNC_TIMES_SORTED_TOTAL)) {
+    func_time_sorted_tot_str = mcopystr(
+      "------------------------------------------\n"
+      "- Total time of functions, sorted, total -\n"
+      "------------------------------------------\n");
+  }
+  
+  char* func_count_sorted_tot_str = NULL;
+  if (!disable_coverage && (stats_flags & STATS_FUNC_COUNT_SORTED_TOTAL)) {
+    func_count_sorted_tot_str = mcopystr(
+      "-----------------------------------------------\n"
+      "- Execution count of functions, sorted, total -\n"
+      "-----------------------------------------------\n");
+  }
+  
+  char* func_avg_sorted_tot_str = NULL;
+  if (!disable_profiler && !disable_coverage && (stats_flags & STATS_FUNC_AVG_SORTED_TOTAL)) {
+    func_avg_sorted_tot_str = mcopystr(
+      "--------------------------------------------------------\n"
+      "- Average time / execution of functions, sorted, total -\n"
+      "--------------------------------------------------------\n");
+  }
+  
+  char* line_time_sorted_top10_str = NULL;
+  if (!disable_profiler && (stats_flags & STATS_TOP10_LINE_TIMES)) {
+    line_time_sorted_top10_str = mcopystr(
+      "------------------------------------\n"
+      "- Total time of code lines, top 10 -\n"
+      "------------------------------------\n");
+  }
+  
+  char* line_count_sorted_top10_str = NULL;
+  if (!disable_coverage && (stats_flags & STATS_TOP10_LINE_COUNT)) {
+    line_count_sorted_top10_str = mcopystr(
+      "-----------------------------------------\n"
+      "- Execution count of code lines, top 10 -\n"
+      "-----------------------------------------\n");
+  }
+  
+  char* line_avg_sorted_top10_str = NULL;
+  if (!disable_profiler && !disable_coverage && (stats_flags & STATS_TOP10_LINE_AVG)) {
+    line_avg_sorted_top10_str = mcopystr(
+      "--------------------------------------------------\n"
+      "- Average time / execution of code lines, top 10 -\n"
+      "--------------------------------------------------\n");
+  }
+  
+  char* func_time_sorted_top10_str = NULL;
+  if (!disable_profiler && (stats_flags & STATS_TOP10_FUNC_TIMES)) {
+    func_time_sorted_top10_str = mcopystr(
+      "-----------------------------------\n"
+      "- Total time of functions, top 10 -\n"
+      "-----------------------------------\n");
+  }
+  
+  char* func_count_sorted_top10_str = NULL;
+  if (!disable_coverage && (stats_flags & STATS_TOP10_FUNC_COUNT)) {
+    func_count_sorted_top10_str = mcopystr(
+      "----------------------------------------\n"
+      "- Execution count of functions, top 10 -\n"
+      "----------------------------------------\n");
+  }
+  
+  char* func_avg_sorted_top10_str = NULL;
+  if (!disable_profiler && !disable_coverage && (stats_flags & STATS_TOP10_FUNC_AVG)) {
+    func_avg_sorted_top10_str = mcopystr(
+      "-------------------------------------------------\n"
+      "- Average time / execution of functions, top 10 -\n"
+      "-------------------------------------------------\n");
+  }
+  
+  char* unused_lines_str = NULL;
+  char* unused_func_str = NULL;
+  if (!disable_coverage && (stats_flags & STATS_UNUSED_LINES)) {
+    unused_lines_str = mcopystr(
+      "---------------------\n"
+      "- Unused code lines -\n"
+      "---------------------\n");
+  }
+  if (!disable_coverage && (stats_flags & STATS_UNUSED_FUNC)) {
+    unused_func_str = mcopystr(
+      "--------------------\n"
+      "- Unused functions -\n"
+      "--------------------\n");
+  }
+  
+  // variables for counting totals, and for determining the amount of unused lines/functions
+  size_t total_code_lines = 0;
+  size_t total_functions = 0;
+  size_t used_code_lines = 0;
+  size_t used_functions = 0;
+  
+  // cached sizes of statistics data segments, needed to determine whether a separator
+  // is needed or not
+  size_t line_data_str_len = mstrlen(line_data_str);
+  size_t func_data_str_len = mstrlen(func_data_str);
+  size_t unused_lines_str_len = mstrlen(unused_lines_str);
+  size_t unused_func_str_len = mstrlen(unused_func_str);
+  size_t line_avg_str_len = mstrlen(line_avg_str);
+  size_t func_avg_str_len = mstrlen(func_avg_str);
+  
   // cycle through the database and gather the necessary data
   for (size_t i = 0; i < profiler_db.size(); ++i) {
     if (i > 0) {
-      // add separators between files
-      line_data_str = mputstr(line_data_str, "-------------------------------------------------\n");
-      func_data_str = mputstr(func_data_str, "------------------------------------------------\n");
-      if (!disable_profiler && !disable_coverage) {
-        line_avg_str = mputstr(line_avg_str, "-------------------------------------------------\n");
-        func_avg_str = mputstr(func_avg_str, "------------------------------------------------\n");
+      // add separators between files (only add them if the previous file actually added something)
+      if ((stats_flags & STATS_LINE_DATA_RAW) && line_data_str_len != mstrlen(line_data_str)) {
+        line_data_str = mputstr(line_data_str, "-------------------------------------------------\n");
+        line_data_str_len = mstrlen(line_data_str);
+      }
+      if ((stats_flags & STATS_FUNC_DATA_RAW) && func_data_str_len != mstrlen(func_data_str)) {
+        func_data_str = mputstr(func_data_str, "------------------------------------------------\n");
+        func_data_str_len = mstrlen(func_data_str);
+      }
+      if (!disable_coverage) {
+        if ((stats_flags & STATS_UNUSED_LINES) && unused_lines_str_len != mstrlen(unused_lines_str)) {
+          unused_lines_str = mputstr(unused_lines_str, "---------------------\n");
+          unused_lines_str_len = mstrlen(unused_lines_str);
+        }
+        if ((stats_flags & STATS_UNUSED_FUNC) && unused_func_str_len != mstrlen(unused_func_str)) {
+          unused_func_str = mputstr(unused_func_str, "--------------------\n");
+          unused_func_str_len = mstrlen(unused_func_str);
+        }
+        if (!disable_profiler) {
+          if ((stats_flags & STATS_LINE_AVG_RAW) && line_avg_str_len != mstrlen(line_avg_str)) {
+            line_avg_str = mputstr(line_avg_str, "-------------------------------------------\n");
+            line_avg_str_len = mstrlen(line_avg_str);
+          }
+          if ((stats_flags & STATS_FUNC_AVG_RAW) && func_avg_str_len != mstrlen(func_avg_str)) {
+            func_avg_str = mputstr(func_avg_str, "------------------------------------------\n");
+            func_avg_str_len = mstrlen(func_avg_str);
+          }
+        }
       }
     }
     
     // lines
     for (size_t j = 0; j < profiler_db[i].lines.size(); ++j) {
-      if (0.0 != profiler_db[i].lines[j].total_time ||
-          0 != profiler_db[i].lines[j].exec_count) {
+      // line specification (including function name for the function's start line)
+      char* line_spec_str = mprintf("%s:%d", profiler_db[i].filename,
+        profiler_db[i].lines[j].lineno);
+      int func = get_function(i, profiler_db[i].lines[j].lineno);
+      if (-1 != func) {
+        line_spec_str = mputprintf(line_spec_str, " [%s]", profiler_db[i].functions[func].name);
+      }
+      line_spec_str = mputstrn(line_spec_str, "\n", 1);
+      
+      if (disable_coverage || 0 != profiler_db[i].lines[j].exec_count) {
         if (!disable_profiler) {
-          line_data_str = mputprintf(line_data_str, "%.6lfs", profiler_db[i].lines[j].total_time);
+          if (stats_flags & STATS_LINE_DATA_RAW) {
+            char* total_time_str = timeval2string(profiler_db[i].lines[j].total_time);
+            line_data_str = mputprintf(line_data_str, "%ss", total_time_str);
+            Free(total_time_str);
+          }
           if (!disable_coverage) {
-            line_data_str = mputstrn(line_data_str, "\t/\t", 3);
-            line_avg_str = mputprintf(line_avg_str, "%.6lfs", 
-              profiler_db[i].lines[j].total_time / profiler_db[i].lines[j].exec_count);
+            if (stats_flags & STATS_LINE_DATA_RAW) {
+              line_data_str = mputstrn(line_data_str, "\t/\t", 3);
+            }
+            if (stats_flags & STATS_LINE_AVG_RAW) {
+              double avg = (profiler_db[i].lines[j].total_time.tv_sec +
+                profiler_db[i].lines[j].total_time.tv_usec / 1000000.0) /
+                profiler_db[i].lines[j].exec_count;
+              char* total_time_str = timeval2string(profiler_db[i].lines[j].total_time);
+              line_avg_str = mputprintf(line_avg_str, "%.6lfs\t(%ss / %d)", 
+                avg, total_time_str, profiler_db[i].lines[j].exec_count);
+              Free(total_time_str);
+            }
           }
         }
-        if (!disable_coverage) {
+        if (!disable_coverage && (stats_flags & STATS_LINE_DATA_RAW)) {
           line_data_str = mputprintf(line_data_str, "%d", profiler_db[i].lines[j].exec_count);
         }
-        
-        // line specification (including function name for the function's start line)
-        char* line_spec_str = mprintf("\t%s:%lu", profiler_db[i].filename, j);
-        int func = get_function(i, j);
-        if (-1 != func) {
-          line_spec_str = mputprintf(line_spec_str, " [%s]", profiler_db[i].functions[func].name);
-        }
-        line_spec_str = mputstrn(line_spec_str, "\n", 1);
-        
+
         // add the line spec string to the other strings
-        line_data_str = mputstr(line_data_str, line_spec_str);
-        if (!disable_profiler && !disable_coverage) {
-          line_avg_str = mputstr(line_avg_str, line_spec_str);
+        if (stats_flags & STATS_LINE_DATA_RAW) {
+          line_data_str = mputprintf(line_data_str, "\t%s", line_spec_str);
+        }
+        if (!disable_profiler && !disable_coverage && (stats_flags & STATS_LINE_AVG_RAW)) {
+          line_avg_str = mputprintf(line_avg_str, "\t%s", line_spec_str);
         }
+        ++used_code_lines;
       }
+      else if (stats_flags & STATS_UNUSED_LINES) {
+        // unused line
+        unused_lines_str = mputstr(unused_lines_str, line_spec_str);
+      }
+      Free(line_spec_str);
     }
     
     // functions
     for (size_t j = 0; j < profiler_db[i].functions.size(); ++j) {
-      if (!disable_profiler) {
-        func_data_str = mputprintf(func_data_str, "%.6lfs", profiler_db[i].functions[j].total_time);
-        if (!disable_coverage) {
-          func_data_str = mputstrn(func_data_str, "\t/\t", 3);
-          func_avg_str = mputprintf(func_avg_str, "%.6lfs", 
-            profiler_db[i].functions[j].total_time / profiler_db[i].functions[j].exec_count);
+      // functions specification
+      char* func_spec_str = mprintf("%s:%d [%s]\n", profiler_db[i].filename,
+        profiler_db[i].functions[j].lineno, profiler_db[i].functions[j].name);
+
+      if (disable_coverage || 0 != profiler_db[i].functions[j].exec_count) {
+        if (!disable_profiler) {
+          if (stats_flags & STATS_FUNC_DATA_RAW) {
+            char* total_time_str = timeval2string(profiler_db[i].functions[j].total_time);
+            func_data_str = mputprintf(func_data_str, "%ss", total_time_str);
+            Free(total_time_str);
+          }
+          if (!disable_coverage) {
+            if (stats_flags & STATS_FUNC_DATA_RAW) {
+              func_data_str = mputstrn(func_data_str, "\t/\t", 3);
+            }
+            if (stats_flags & STATS_FUNC_AVG_RAW) {
+              double avg = (profiler_db[i].functions[j].total_time.tv_sec +
+                profiler_db[i].functions[j].total_time.tv_usec / 1000000.0) /
+                profiler_db[i].functions[j].exec_count;
+              char* total_time_str = timeval2string(profiler_db[i].functions[j].total_time);
+              func_avg_str = mputprintf(func_avg_str, "%.6lfs\t(%ss / %d)", 
+                avg, total_time_str, profiler_db[i].functions[j].exec_count);
+              Free(total_time_str);
+            }
+          }
+        }
+        if (!disable_coverage && (stats_flags & STATS_FUNC_DATA_RAW)) {
+          func_data_str = mputprintf(func_data_str, "%d", profiler_db[i].functions[j].exec_count);
+        }
+
+        // add the line spec string to the other strings
+        if (stats_flags & STATS_FUNC_DATA_RAW) {
+          func_data_str = mputprintf(func_data_str, "\t%s", func_spec_str);
         }
+        if (!disable_profiler && !disable_coverage && (stats_flags & STATS_FUNC_AVG_RAW)) {
+          func_avg_str = mputprintf(func_avg_str, "\t%s", func_spec_str);
+        }
+        
+        ++used_functions;
       }
-      if (!disable_coverage) {
-        func_data_str = mputprintf(func_data_str, "%d", profiler_db[i].functions[j].exec_count);
+      else if (stats_flags & STATS_UNUSED_FUNC) {
+        // unused function
+        unused_func_str = mputprintf(unused_func_str, func_spec_str);
+      }
+      Free(func_spec_str);
+    }
+    
+    // number of lines and functions
+    if (stats_flags & STATS_NUMBER_OF_LINES) {
+      line_func_count_str = mputprintf(line_func_count_str, "%s:\t%lu lines,\t%lu functions\n",
+         profiler_db[i].filename, profiler_db[i].lines.size(), profiler_db[i].functions.size());
+    }
+    total_code_lines += profiler_db[i].lines.size();
+    total_functions += profiler_db[i].functions.size();
+  }
+  if (stats_flags & STATS_NUMBER_OF_LINES) {
+    line_func_count_str = mputprintf(line_func_count_str,
+      "--------------------------------------\n"
+      "Total:\t%lu lines,\t%lu functions\n", total_code_lines, total_functions);
+  }
+  
+  if (stats_flags & (STATS_TOP10_ALL_DATA | STATS_ALL_DATA_SORTED)) {
+    // copy code line and function info into stats_data_t containers for sorting
+    stats_data_t* code_line_stats = (stats_data_t*)Malloc(used_code_lines * sizeof(stats_data_t));
+    stats_data_t* function_stats = (stats_data_t*)Malloc(used_functions * sizeof(stats_data_t));
+    int line_index = 0;
+    int func_index = 0;
+
+    for (size_t i = 0; i < profiler_db.size(); ++i) {
+      for (size_t j = 0; j < profiler_db[i].lines.size(); ++j) {
+        if (disable_coverage || 0 != profiler_db[i].lines[j].exec_count) {
+          code_line_stats[line_index].filename = profiler_db[i].filename;
+          code_line_stats[line_index].funcname = NULL;
+          code_line_stats[line_index].lineno = profiler_db[i].lines[j].lineno;
+          code_line_stats[line_index].total_time = profiler_db[i].lines[j].total_time;
+          code_line_stats[line_index].exec_count = profiler_db[i].lines[j].exec_count;
+          int func = get_function(i, profiler_db[i].lines[j].lineno);
+          if (-1 != func) {
+            code_line_stats[line_index].funcname = profiler_db[i].functions[func].name;
+          }
+          ++line_index;
+        }
+      }
+      for (size_t j = 0; j < profiler_db[i].functions.size(); ++j) {
+        if (disable_coverage || 0 != profiler_db[i].functions[j].exec_count) {
+          function_stats[func_index].filename = profiler_db[i].filename;
+          function_stats[func_index].funcname = profiler_db[i].functions[j].name;
+          function_stats[func_index].lineno = profiler_db[i].functions[j].lineno;
+          function_stats[func_index].total_time = profiler_db[i].functions[j].total_time;
+          function_stats[func_index].exec_count = profiler_db[i].functions[j].exec_count;
+          ++func_index;
+        }
       }
+    }
 
-      // functions specification
-      char* func_spec_str = mprintf("\t%s:%d [%s]\n", profiler_db[i].filename,
-        profiler_db[i].functions[j].lineno, profiler_db[i].functions[j].name);
+    if (!disable_profiler) {
+      // sort the code lines and functions by total time
+      qsort(code_line_stats, used_code_lines, sizeof(stats_data_t), &stats_data_cmp_time);
+      qsort(function_stats, used_functions, sizeof(stats_data_t), &stats_data_cmp_time);
+
+      if (stats_flags & (STATS_LINE_TIMES_SORTED_TOTAL | STATS_TOP10_LINE_TIMES)) {
+        // cycle through the sorted code lines and gather the necessary data
+        for (size_t i = 0; i < used_code_lines; ++i) {
+          char* total_time_str = timeval2string(code_line_stats[i].total_time);
+          char* the_data = mprintf("%ss\t%s:%d", total_time_str,
+            code_line_stats[i].filename, code_line_stats[i].lineno);
+          Free(total_time_str);
+          if (NULL != code_line_stats[i].funcname) {
+            the_data = mputprintf(the_data, " [%s]", code_line_stats[i].funcname);
+          }
+          the_data = mputstrn(the_data, "\n", 1);
+          if (stats_flags & STATS_LINE_TIMES_SORTED_TOTAL) {
+            line_time_sorted_tot_str = mputstr(line_time_sorted_tot_str, the_data);
+          }
+          if (i < 10 && (stats_flags & STATS_TOP10_LINE_TIMES)) {
+            line_time_sorted_top10_str = mputprintf(line_time_sorted_top10_str,
+              "%2lu.\t%s", i + 1, the_data);
+          }
+          Free(the_data);
+        }
+      }
+
+      if (stats_flags & (STATS_FUNC_TIMES_SORTED_TOTAL | STATS_TOP10_FUNC_TIMES)) {
+        // cycle through the sorted functions and gather the necessary data
+        for (size_t i = 0; i < used_functions; ++i) {
+          char* total_time_str = timeval2string(function_stats[i].total_time);
+          char* the_data = mprintf("%ss\t%s:%d [%s]\n", total_time_str,
+            function_stats[i].filename, function_stats[i].lineno, function_stats[i].funcname);
+          Free(total_time_str);
+          if (stats_flags & STATS_FUNC_TIMES_SORTED_TOTAL) {
+            func_time_sorted_tot_str = mputstr(func_time_sorted_tot_str, the_data);
+          }
+          if (i < 10 && (stats_flags & STATS_TOP10_FUNC_TIMES)) {
+            func_time_sorted_top10_str = mputprintf(func_time_sorted_top10_str,
+              "%2lu.\t%s", i + 1, the_data);
+          }
+          Free(the_data);
+        }
+      }
+
+      if (stats_flags & (STATS_LINE_TIMES_SORTED_BY_MOD | STATS_FUNC_TIMES_SORTED_BY_MOD)) {
+        // cached string lengths, to avoid multiple separators after each other
+        size_t line_time_sorted_mod_str_len = mstrlen(line_time_sorted_mod_str);
+        size_t func_time_sorted_mod_str_len = mstrlen(func_time_sorted_mod_str);
+
+        // cycle through the sorted statistics and gather the necessary data per module
+        for (size_t i = 0; i < profiler_db.size(); ++i) {
+          if (i > 0) {
+            if ((stats_flags & STATS_LINE_TIMES_SORTED_BY_MOD) &&
+                line_time_sorted_mod_str_len != mstrlen(line_time_sorted_mod_str)) {
+              line_time_sorted_mod_str = mputstr(line_time_sorted_mod_str,
+                "------------------------------------------------\n");
+              line_time_sorted_mod_str_len = mstrlen(line_time_sorted_mod_str);
+            }
+            if ((stats_flags & STATS_FUNC_TIMES_SORTED_BY_MOD) &&
+                func_time_sorted_mod_str_len != mstrlen(func_time_sorted_mod_str)) {
+              func_time_sorted_mod_str = mputstr(func_time_sorted_mod_str,
+                "-----------------------------------------------\n");
+              func_time_sorted_mod_str_len = mstrlen(func_time_sorted_mod_str);
+            }
+          }
+          if (stats_flags & STATS_LINE_TIMES_SORTED_BY_MOD) {
+            for (size_t j = 0; j < used_code_lines; ++j) {
+              if (0 == strcmp(code_line_stats[j].filename, profiler_db[i].filename)) {
+                char* total_time_str = timeval2string(code_line_stats[j].total_time);
+                line_time_sorted_mod_str = mputprintf(line_time_sorted_mod_str,
+                  "%ss\t%s:%d", total_time_str, code_line_stats[j].filename,
+                  code_line_stats[j].lineno);
+                Free(total_time_str);
+                if (NULL != code_line_stats[j].funcname) {
+                  line_time_sorted_mod_str = mputprintf(line_time_sorted_mod_str,
+                    " [%s]", code_line_stats[j].funcname);
+                }
+                line_time_sorted_mod_str = mputstrn(line_time_sorted_mod_str, "\n", 1);
+              }
+            }
+          }
+          if (stats_flags & STATS_FUNC_TIMES_SORTED_BY_MOD) {
+            for (size_t j = 0; j < used_functions; ++j) {
+              if (0 == strcmp(function_stats[j].filename, profiler_db[i].filename)) {
+                char* total_time_str = timeval2string(function_stats[j].total_time);
+                func_time_sorted_mod_str = mputprintf(func_time_sorted_mod_str,
+                  "%ss\t%s:%d [%s]\n", total_time_str, function_stats[j].filename,
+                  function_stats[j].lineno, function_stats[j].funcname);
+                Free(total_time_str);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    if (!disable_coverage) {
+      // sort the code lines and functions by execution count
+      qsort(code_line_stats, used_code_lines, sizeof(stats_data_t), &stats_data_cmp_count);
+      qsort(function_stats, used_functions, sizeof(stats_data_t), &stats_data_cmp_count);
+
+      if (stats_flags & (STATS_LINE_COUNT_SORTED_TOTAL | STATS_TOP10_LINE_COUNT)) {
+        // cycle through the sorted code lines and gather the necessary data
+        for (size_t i = 0; i < used_code_lines; ++i) {
+          char* the_data = mprintf("%d\t%s:%d", code_line_stats[i].exec_count,
+            code_line_stats[i].filename, code_line_stats[i].lineno);
+          if (NULL != code_line_stats[i].funcname) {
+            the_data = mputprintf(the_data, " [%s]", code_line_stats[i].funcname);
+          }
+          the_data = mputstrn(the_data, "\n", 1);
+          if (stats_flags & STATS_LINE_COUNT_SORTED_TOTAL) {
+            line_count_sorted_tot_str = mputstr(line_count_sorted_tot_str, the_data);
+          }
+          if (i < 10 && (stats_flags & STATS_TOP10_LINE_COUNT)) {
+            line_count_sorted_top10_str = mputprintf(line_count_sorted_top10_str,
+              "%2lu.\t%s", i + 1, the_data);
+          }
+          Free(the_data);
+        }
+      }
+
+      if (stats_flags & (STATS_FUNC_COUNT_SORTED_TOTAL | STATS_TOP10_FUNC_COUNT)) {
+        // cycle through the sorted functions and gather the necessary data
+        for (size_t i = 0; i < used_functions; ++i) {
+          char* the_data = mprintf("%d\t%s:%d [%s]\n",
+            function_stats[i].exec_count, function_stats[i].filename,
+            function_stats[i].lineno, function_stats[i].funcname);
+          if (stats_flags & STATS_FUNC_COUNT_SORTED_TOTAL) {
+            func_count_sorted_tot_str = mputstr(func_count_sorted_tot_str, the_data);
+          }
+          if (i < 10 && (stats_flags & STATS_TOP10_FUNC_COUNT)) {
+            func_count_sorted_top10_str = mputprintf(func_count_sorted_top10_str,
+              "%2lu.\t%s", i + 1, the_data);
+          }
+          Free(the_data);
+        }
+      }
+
+      if (stats_flags & (STATS_LINE_COUNT_SORTED_BY_MOD | STATS_FUNC_COUNT_SORTED_BY_MOD)) {
+        // cached string lengths, to avoid multiple separators after each other
+        size_t line_count_sorted_mod_str_len = mstrlen(line_count_sorted_mod_str);
+        size_t func_count_sorted_mod_str_len = mstrlen(func_count_sorted_mod_str);
+
+        // cycle through the sorted statistics and gather the necessary data per module
+        for (size_t i = 0; i < profiler_db.size(); ++i) {
+          if (i > 0) {
+            if ((stats_flags & STATS_LINE_COUNT_SORTED_BY_MOD) &&
+                line_count_sorted_mod_str_len != mstrlen(line_count_sorted_mod_str)) {
+              line_count_sorted_mod_str = mputstr(line_count_sorted_mod_str,
+                "-----------------------------------------------------\n");
+              line_count_sorted_mod_str_len = mstrlen(line_count_sorted_mod_str);
+            }
+            if ((stats_flags & STATS_FUNC_COUNT_SORTED_BY_MOD) &&
+                func_count_sorted_mod_str_len != mstrlen(func_count_sorted_mod_str)) {
+              func_count_sorted_mod_str = mputstr(func_count_sorted_mod_str,
+                "----------------------------------------------------\n");
+              func_count_sorted_mod_str_len = mstrlen(func_count_sorted_mod_str);
+            }
+          }
+          if (stats_flags & STATS_LINE_COUNT_SORTED_BY_MOD) {
+            for (size_t j = 0; j < used_code_lines; ++j) {
+              if (0 == strcmp(code_line_stats[j].filename, profiler_db[i].filename)) {
+                line_count_sorted_mod_str = mputprintf(line_count_sorted_mod_str,
+                  "%d\t%s:%d", code_line_stats[j].exec_count, code_line_stats[j].filename,
+                  code_line_stats[j].lineno);
+                if (NULL != code_line_stats[j].funcname) {
+                  line_count_sorted_mod_str = mputprintf(line_count_sorted_mod_str,
+                    " [%s]", code_line_stats[j].funcname);
+                }
+                line_count_sorted_mod_str = mputstrn(line_count_sorted_mod_str, "\n", 1);
+              }
+            }
+          }
+          if (stats_flags & STATS_FUNC_COUNT_SORTED_BY_MOD) {
+            for (size_t j = 0; j < used_functions; ++j) {
+              if (0 == strcmp(function_stats[j].filename, profiler_db[i].filename)) {
+                func_count_sorted_mod_str = mputprintf(func_count_sorted_mod_str,
+                  "%d\t%s:%d [%s]\n", function_stats[j].exec_count, function_stats[j].filename,
+                  function_stats[j].lineno, function_stats[j].funcname);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    if (!disable_profiler && !disable_coverage) {
+      // sort the code lines and functions by average time / execution
+      qsort(code_line_stats, used_code_lines, sizeof(stats_data_t), &stats_data_cmp_avg);
+      qsort(function_stats, used_functions, sizeof(stats_data_t), &stats_data_cmp_avg);
+
+      if (stats_flags & (STATS_LINE_AVG_SORTED_TOTAL | STATS_TOP10_LINE_AVG)) {
+        // cycle through the sorted code lines and gather the necessary data
+        for (size_t i = 0; i < used_code_lines; ++i) {
+          double avg = (code_line_stats[i].total_time.tv_sec +
+            code_line_stats[i].total_time.tv_usec / 1000000.0) /
+            code_line_stats[i].exec_count;
+          char* total_time_str = timeval2string(code_line_stats[i].total_time);
+          char* the_data = mprintf("%.6lfs\t(%ss / %d)\t%s:%d",
+            avg, total_time_str, code_line_stats[i].exec_count,
+            code_line_stats[i].filename, code_line_stats[i].lineno);
+          Free(total_time_str);
+          if (NULL != code_line_stats[i].funcname) {
+            the_data = mputprintf(the_data, " [%s]", code_line_stats[i].funcname);
+          }
+          the_data = mputstrn(the_data, "\n", 1);
+          if (stats_flags & STATS_LINE_AVG_SORTED_TOTAL) {
+            line_avg_sorted_tot_str = mputstr(line_avg_sorted_tot_str, the_data);
+          }
+          if (i < 10 && (stats_flags & STATS_TOP10_LINE_AVG)) {
+            line_avg_sorted_top10_str = mputprintf(line_avg_sorted_top10_str,
+              "%2lu.\t%s", i + 1, the_data);
+          }
+          Free(the_data);
+        }
+      }
+
+      if (stats_flags & (STATS_FUNC_AVG_SORTED_TOTAL | STATS_TOP10_FUNC_AVG)) {
+        // cycle through the sorted functions and gather the necessary data
+        for (size_t i = 0; i < used_functions; ++i) {
+          double avg = (function_stats[i].total_time.tv_sec +
+            function_stats[i].total_time.tv_usec / 1000000.0) /
+            function_stats[i].exec_count;
+          char* total_time_str = timeval2string(function_stats[i].total_time);
+          char* the_data = mprintf("%.6lfs\t(%ss / %d)\t%s:%d [%s]\n",
+            avg, total_time_str, function_stats[i].exec_count,
+            function_stats[i].filename, function_stats[i].lineno, function_stats[i].funcname);
+          Free(total_time_str);
+          if (stats_flags & STATS_FUNC_AVG_SORTED_TOTAL) {
+            func_avg_sorted_tot_str = mputstr(func_avg_sorted_tot_str, the_data);
+          }
+          if (i < 10 && (stats_flags & STATS_TOP10_FUNC_AVG)) {
+            func_avg_sorted_top10_str = mputprintf(func_avg_sorted_top10_str,
+              "%2lu.\t%s", i + 1, the_data);
+          }
+          Free(the_data);
+        }
+      }
+
+      if (stats_flags & (STATS_LINE_AVG_SORTED_BY_MOD | STATS_FUNC_AVG_SORTED_BY_MOD)) {
+        // cached string lengths, to avoid multiple separators after each other
+        size_t line_avg_sorted_mod_str_len = mstrlen(line_avg_sorted_mod_str);
+        size_t func_avg_sorted_mod_str_len = mstrlen(func_avg_sorted_mod_str);
 
-      // add the line spec string to the other strings
-      func_data_str = mputstr(func_data_str, func_spec_str);
-      if (!disable_profiler && !disable_coverage) {
-        func_avg_str = mputstr(func_avg_str, func_spec_str);
+        // cycle through the sorted statistics and gather the necessary data per module
+        for (size_t i = 0; i < profiler_db.size(); ++i) {
+          if (i > 0) {
+            if ((stats_flags & STATS_LINE_AVG_SORTED_BY_MOD) &&
+                line_avg_sorted_mod_str_len != mstrlen(line_avg_sorted_mod_str)) {
+              line_avg_sorted_mod_str = mputstr(line_avg_sorted_mod_str,
+                "--------------------------------------------------------------\n");
+              line_avg_sorted_mod_str_len = mstrlen(line_avg_sorted_mod_str);
+            }
+            if ((stats_flags & STATS_FUNC_AVG_SORTED_BY_MOD) &&
+                func_avg_sorted_mod_str_len != mstrlen(func_avg_sorted_mod_str)) {
+              func_avg_sorted_mod_str = mputstr(func_avg_sorted_mod_str,
+                "-------------------------------------------------------------\n");
+              func_avg_sorted_mod_str_len = mstrlen(func_avg_sorted_mod_str);
+            }
+          }
+          if (stats_flags & STATS_LINE_AVG_SORTED_BY_MOD) {
+            for (size_t j = 0; j < used_code_lines; ++j) {
+              if (0 == strcmp(code_line_stats[j].filename, profiler_db[i].filename)) {
+                double avg = (code_line_stats[j].total_time.tv_sec +
+                  code_line_stats[j].total_time.tv_usec / 1000000.0) /
+                  code_line_stats[j].exec_count;
+                char* total_time_str = timeval2string(code_line_stats[j].total_time);
+                line_avg_sorted_mod_str = mputprintf(line_avg_sorted_mod_str,
+                  "%.6lfs\t(%ss / %d)\t%s:%d",
+                  avg, total_time_str, code_line_stats[j].exec_count,
+                  code_line_stats[j].filename, code_line_stats[j].lineno);
+                Free(total_time_str);
+                if (NULL != code_line_stats[j].funcname) {
+                  line_avg_sorted_mod_str = mputprintf(line_avg_sorted_mod_str,
+                    " [%s]", code_line_stats[j].funcname);
+                }
+                line_avg_sorted_mod_str = mputstrn(line_avg_sorted_mod_str, "\n", 1);
+              }
+            }
+          }
+          if (stats_flags & STATS_FUNC_AVG_SORTED_BY_MOD) {
+            for (size_t j = 0; j < used_functions; ++j) {
+              if (0 == strcmp(function_stats[j].filename, profiler_db[i].filename)) {
+                double avg = (function_stats[j].total_time.tv_sec +
+                  function_stats[j].total_time.tv_usec / 1000000.0) /
+                  function_stats[j].exec_count;
+                char* total_time_str = timeval2string(function_stats[j].total_time);
+                func_avg_sorted_mod_str = mputprintf(func_avg_sorted_mod_str,
+                  "%.6lfs\t(%ss / %d)\t%s:%d [%s]\n",
+                  avg, total_time_str, function_stats[j].exec_count,
+                  function_stats[j].filename, function_stats[j].lineno, function_stats[j].funcname);
+                Free(total_time_str);
+              }
+            }
+          }
+        }
       }
     }
+
+    // free the stats data
+    Free(code_line_stats);
+    Free(function_stats);
   }
   
   // add new lines at the end of each segment
-  line_data_str = mputstrn(line_data_str, "\n", 1);
-  func_data_str = mputstrn(func_data_str, "\n", 1);
-  if (!disable_profiler && !disable_coverage) {
-    line_avg_str = mputstrn(line_avg_str, "\n", 1);
-    func_avg_str = mputstrn(func_avg_str, "\n", 1);
+  if (stats_flags & STATS_NUMBER_OF_LINES) {
+    line_func_count_str = mputstrn(line_func_count_str, "\n", 1);
+  }
+  if (stats_flags & STATS_LINE_DATA_RAW) {
+    line_data_str = mputstrn(line_data_str, "\n", 1);
+  }
+  if (stats_flags & STATS_FUNC_DATA_RAW) {
+    func_data_str = mputstrn(func_data_str, "\n", 1);
+  }
+  if (!disable_profiler) {
+    if (stats_flags & STATS_LINE_TIMES_SORTED_BY_MOD) {
+      line_time_sorted_mod_str = mputstrn(line_time_sorted_mod_str, "\n", 1);
+    }
+    if (stats_flags & STATS_LINE_TIMES_SORTED_TOTAL) {
+      line_time_sorted_tot_str = mputstrn(line_time_sorted_tot_str, "\n", 1);
+    }
+    if (stats_flags & STATS_FUNC_TIMES_SORTED_BY_MOD) {
+      func_time_sorted_mod_str = mputstrn(func_time_sorted_mod_str, "\n", 1);
+    }
+    if (stats_flags & STATS_FUNC_TIMES_SORTED_TOTAL) {
+      func_time_sorted_tot_str = mputstrn(func_time_sorted_tot_str, "\n", 1);
+    }
+    if (stats_flags & STATS_TOP10_LINE_TIMES) {
+      line_time_sorted_top10_str = mputstrn(line_time_sorted_top10_str, "\n", 1);
+    }
+    if (stats_flags & STATS_TOP10_FUNC_TIMES) {
+      func_time_sorted_top10_str = mputstrn(func_time_sorted_top10_str, "\n", 1);
+    }
+    if (!disable_coverage) {
+      if (stats_flags & STATS_LINE_AVG_RAW) {
+        line_avg_str = mputstrn(line_avg_str, "\n", 1);
+      }
+      if (stats_flags & STATS_LINE_AVG_RAW) {
+        func_avg_str = mputstrn(func_avg_str, "\n", 1);
+      }
+      if (stats_flags & STATS_LINE_AVG_SORTED_BY_MOD) {
+        line_avg_sorted_mod_str = mputstrn(line_avg_sorted_mod_str, "\n", 1);
+      }
+      if (stats_flags & STATS_LINE_AVG_SORTED_TOTAL) {
+        line_avg_sorted_tot_str = mputstrn(line_avg_sorted_tot_str, "\n", 1);
+      }
+      if (stats_flags & STATS_FUNC_AVG_SORTED_BY_MOD) {
+        func_avg_sorted_mod_str = mputstrn(func_avg_sorted_mod_str, "\n", 1);
+      }
+      if (stats_flags & STATS_FUNC_AVG_SORTED_TOTAL) {
+        func_avg_sorted_tot_str = mputstrn(func_avg_sorted_tot_str, "\n", 1);
+      }
+      if (stats_flags & STATS_TOP10_LINE_AVG) {
+        line_avg_sorted_top10_str = mputstrn(line_avg_sorted_top10_str, "\n", 1);
+      }
+      if (stats_flags & STATS_TOP10_FUNC_AVG) {
+        func_avg_sorted_top10_str = mputstrn(func_avg_sorted_top10_str, "\n", 1);
+      }
+    }
+  }
+  if (!disable_coverage) {
+    if (stats_flags & STATS_LINE_COUNT_SORTED_BY_MOD) {
+      line_count_sorted_mod_str = mputstrn(line_count_sorted_mod_str, "\n", 1);
+    }
+    if (stats_flags & STATS_LINE_COUNT_SORTED_TOTAL) {
+      line_count_sorted_tot_str = mputstrn(line_count_sorted_tot_str, "\n", 1);
+    }
+    if (stats_flags & STATS_FUNC_COUNT_SORTED_BY_MOD) {
+      func_count_sorted_mod_str = mputstrn(func_count_sorted_mod_str, "\n", 1);
+    }
+    if (stats_flags & STATS_FUNC_COUNT_SORTED_TOTAL) {
+      func_count_sorted_tot_str = mputstrn(func_count_sorted_tot_str, "\n", 1);
+    }
+    if (stats_flags & STATS_TOP10_LINE_COUNT) {
+      line_count_sorted_top10_str = mputstrn(line_count_sorted_top10_str, "\n", 1);
+    }
+    if (stats_flags & STATS_TOP10_FUNC_COUNT) {
+      func_count_sorted_top10_str = mputstrn(func_count_sorted_top10_str, "\n", 1);
+    }
+    if (stats_flags & STATS_UNUSED_LINES) {
+      unused_lines_str = mputstrn(unused_lines_str, "\n", 1);
+    }
+    if (stats_flags & STATS_UNUSED_FUNC) {
+      unused_func_str = mputstrn(unused_func_str, "\n", 1);
+    }
   }
   
   // write the statistics to the specified file
@@ -587,29 +1482,83 @@ void TTCN3_Profiler::print_stats()
       "statistics will not be saved.", stats_filename);
     return;
   }
-  fprintf(file, "%s%s%s%s%s"
-    , title_str, line_data_str
-    , (disable_profiler || disable_coverage) ? "" : line_avg_str
-    , func_data_str, (disable_profiler || disable_coverage) ? "" : func_avg_str);
+  // by now the strings for all disabled statistics entries should be null
+  fprintf(file, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
+    , title_str
+    , (NULL != line_func_count_str) ? line_func_count_str : ""
+    , (NULL != line_data_str) ? line_data_str : ""
+    , (NULL != line_avg_str) ? line_avg_str : ""
+    , (NULL != func_data_str) ? func_data_str : ""
+    , (NULL != func_avg_str) ? func_avg_str : ""
+    , (NULL != line_time_sorted_mod_str) ? line_time_sorted_mod_str : ""
+    , (NULL != line_time_sorted_tot_str) ? line_time_sorted_tot_str : ""
+    , (NULL != func_time_sorted_mod_str) ? func_time_sorted_mod_str : ""
+    , (NULL != func_time_sorted_tot_str) ? func_time_sorted_tot_str : ""
+    , (NULL != line_count_sorted_mod_str) ? line_count_sorted_mod_str : ""
+    , (NULL != line_count_sorted_tot_str) ? line_count_sorted_tot_str : ""
+    , (NULL != func_count_sorted_mod_str) ? func_count_sorted_mod_str : ""
+    , (NULL != func_count_sorted_tot_str) ? func_count_sorted_tot_str : ""
+    , (NULL != line_avg_sorted_mod_str) ? line_avg_sorted_mod_str : ""
+    , (NULL != line_avg_sorted_tot_str) ? line_avg_sorted_tot_str : ""
+    , (NULL != func_avg_sorted_mod_str) ? func_avg_sorted_mod_str : ""
+    , (NULL != func_avg_sorted_tot_str) ? func_avg_sorted_tot_str : ""
+    , (NULL != line_time_sorted_top10_str) ? line_time_sorted_top10_str : ""
+    , (NULL != func_time_sorted_top10_str) ? func_time_sorted_top10_str : ""
+    , (NULL != line_count_sorted_top10_str) ? line_count_sorted_top10_str : ""
+    , (NULL != func_count_sorted_top10_str) ? func_count_sorted_top10_str : ""
+    , (NULL != line_avg_sorted_top10_str) ? line_avg_sorted_top10_str : ""
+    , (NULL != func_avg_sorted_top10_str) ? func_avg_sorted_top10_str : ""
+    , (NULL != unused_lines_str) ? unused_lines_str : ""
+    , (NULL != unused_func_str) ? unused_func_str : "");
+  
   fclose(file);
+  
+  // free the strings
+  Free(title_str);
+  Free(line_func_count_str);
+  Free(line_data_str);
+  Free(line_avg_str);
+  Free(func_data_str);
+  Free(func_avg_str);
+  Free(line_time_sorted_mod_str);
+  Free(line_time_sorted_tot_str);
+  Free(func_time_sorted_mod_str);
+  Free(func_time_sorted_tot_str);
+  Free(line_count_sorted_mod_str);
+  Free(line_count_sorted_tot_str);
+  Free(func_count_sorted_mod_str);
+  Free(func_count_sorted_tot_str);
+  Free(line_avg_sorted_mod_str);
+  Free(line_avg_sorted_tot_str);
+  Free(func_avg_sorted_mod_str);
+  Free(func_avg_sorted_tot_str);
+  Free(line_time_sorted_top10_str);
+  Free(func_time_sorted_top10_str);
+  Free(line_count_sorted_top10_str);
+  Free(func_count_sorted_top10_str);
+  Free(line_avg_sorted_top10_str);
+  Free(func_avg_sorted_top10_str);
+  Free(unused_lines_str);
+  Free(unused_func_str);
 }
 
 void TTCN3_Profiler::reset()
 {
-  prev_time = 0.0;
+  prev_time.tv_sec = 0;
+  prev_time.tv_usec = 0;
   prev_file = NULL;
   prev_line = -1;
-  prev_stack_len = 0;
+  prev_stack_len = -1;
 }
 
-double TTCN3_Profiler::get_time() 
+timeval TTCN3_Profiler::get_time() 
 {
   timeval tv;
   gettimeofday(&tv, NULL);
-  return tv.tv_sec + tv.tv_usec / 1000000.0;
+  return tv;
 }
 
-void TTCN3_Profiler::enter_function(const char* filename, int lineno, const char* function_name)
+void TTCN3_Profiler::enter_function(const char* filename, int lineno)
 {
   if (disable_profiler && disable_coverage) {
     return;
@@ -619,17 +1568,13 @@ void TTCN3_Profiler::enter_function(const char* filename, int lineno, const char
   // is measured by using the stack depth.
   execute_line(filename, lineno);
   
-  int element = get_element(filename);
-  
-  // store function data
-  int func = get_function(element, lineno);
-  if (-1 == func) {
-    create_function(element, lineno, function_name);
-    func = profiler_db[element].functions.size() - 1;
-  }
-  
-  if (!disable_coverage) {
-    ++profiler_db[element].functions[func].exec_count;
+  if (!stopped) {
+    int element = get_element(filename);
+
+    // store function data
+    if (!disable_coverage) {
+      ++profiler_db[element].functions[get_function(element, lineno)].exec_count;
+    }
   }
 }
 
@@ -639,35 +1584,33 @@ void TTCN3_Profiler::execute_line(const char* filename, int lineno)
     return;
   }
   
-  if (!disable_profiler) {
-    double currentTime = get_time();
-
-    // prev line should not be measured, because it is still running: we are in longer stack level
-    if (0.0 == prev_time || TTCN3_Stack_Depth::depth() > prev_stack_len) {
-      // add prev timer to call stack:
-      TTCN3_Stack_Depth::add_stack(prev_stack_len, prev_file, filename, prev_line, lineno);
-    }
-    else {
-      // if stack level is the same or higher: current line should be measured:
-      double elapsed = currentTime - prev_time;
+  if (!disable_profiler && TTCN3_Stack_Depth::depth() > prev_stack_len) {
+    // this line is in a different function than the last one, don't measure anything
+    TTCN3_Stack_Depth::add_stack(prev_stack_len, prev_file, filename, prev_line, lineno);
+  }
+  
+  if (!stopped) {
+    if (!disable_profiler && NULL != prev_file) {
+      // this line is in the same function as the previous one, measure the time difference
+      timeval elapsed = subtract_timeval(get_time(), prev_time);
 
-      // add the elapsed time to the time of the previous line:
+      // add the elapsed time to the total time of the previous line
       add_line_time(elapsed, get_element(prev_file), prev_line);
 
       TTCN3_Stack_Depth::update_stack_elapsed(elapsed);
     }
-  }
-  
-  // several instructions could be in the same line, only count the line once
-  if (!disable_coverage && (lineno != prev_line || NULL == prev_file || 
-                            0 != strcmp(prev_file, filename))) {
-    int element = get_element(filename);
-    
-    // make sure the line exists in the database
-    create_lines(element, lineno);
-    
-    // increase line execution count
-    ++profiler_db[element].lines[lineno].exec_count;
+
+    // functions starting at line 0 are: pre_init_module and post_init_module,
+    // don't include them in the database (as they don't appear in the TTCN-3 code),
+    // but include any actual code lines they may contain
+    // also, several instructions could be in the same line, only count the line once
+    if (0 != lineno && !disable_coverage && (lineno != prev_line || NULL == prev_file || 
+                                             0 != strcmp(prev_file, filename))) {
+      int element = get_element(filename);
+
+      // increase line execution count
+      ++profiler_db[element].lines[get_line(element, lineno)].exec_count;
+    }
   }
   
   // store the current location as previous for the next call
@@ -702,65 +1645,69 @@ void TTCN3_Profiler::create_function(int element, int lineno, const char* functi
 {
   profiler_db_item_t::profiler_function_data_t func_data;
   func_data.lineno = lineno;
-  func_data.total_time = 0.0;
+  func_data.total_time.tv_sec = 0;
+  func_data.total_time.tv_usec = 0;
   func_data.exec_count = 0;
   func_data.name = mcopystr(function_name);
   profiler_db[element].functions.push_back(func_data);
 }
 
-void TTCN3_Profiler::create_lines(int element, int lineno)
+int TTCN3_Profiler::get_line(int element, int lineno)
 {
-  // set 0 for the unknown lines
-  size_t line_no = lineno;
-  if (profiler_db[element].lines.size() <= line_no) {
-    for (size_t i = profiler_db[element].lines.size(); i <= line_no; ++i) {
-      profiler_db_item_t::profiler_line_data_t line_data;
-      line_data.total_time = 0.0;
-      line_data.exec_count = 0;
-      profiler_db[element].lines.push_back(line_data);
+  for (size_t i = 0; i < profiler_db[element].lines.size(); ++i) {
+    if (profiler_db[element].lines[i].lineno == lineno) {
+      return i;
     }
   }
+  return -1;
+}
+
+void TTCN3_Profiler::create_line(int element, int lineno)
+{
+  profiler_db_item_t::profiler_line_data_t line_data;
+  line_data.lineno = lineno;
+  line_data.total_time.tv_sec = 0;
+  line_data.total_time.tv_usec = 0;
+  line_data.exec_count = 0;
+  profiler_db[element].lines.push_back(line_data);
 }
 
-void TTCN3_Profiler::add_line_time(double elapsed, int element, int lineno) 
+void TTCN3_Profiler::add_line_time(timeval elapsed, int element, int lineno) 
 {
-  if (-1 == lineno) {
+  if (0 == lineno) {
     return;
   }
-
-  // ensure the line data exists
-  create_lines(element, lineno);
-  
-  // increase the time of the line in the current file:
-  profiler_db[element].lines[lineno].total_time += elapsed;
+  profiler_db[element].lines[get_line(element, lineno)].total_time = add_timeval(
+    profiler_db[element].lines[get_line(element, lineno)].total_time, elapsed);
 }
 
-void TTCN3_Profiler::add_function_time(double elapsed, int element, int lineno)
+void TTCN3_Profiler::add_function_time(timeval elapsed, int element, int lineno)
 {
   int func = get_function(element, lineno);
   if (-1 == func) {
     return;
   }
-  profiler_db[element].functions[func].total_time += elapsed;
+  profiler_db[element].functions[func].total_time = add_timeval(
+    profiler_db[element].functions[func].total_time, elapsed);
 }
 
 void TTCN3_Profiler::update_last()
 {
-  if (0.0 == prev_time) {
+  if (stopped || (0 == prev_time.tv_sec && 0 == prev_time.tv_usec) || NULL == prev_file) {
     return;
   }
-  
-  double currentTime = get_time();
-  double elapsed = currentTime - prev_time;
+
+  timeval elapsed = subtract_timeval(get_time(), prev_time);
 
   int element = get_element(prev_file);
   
-  // add the elapsed time to the time of the previous line:
+  // add the elapsed time to the total time of the previous line
   add_line_time(elapsed, element, prev_line);
   TTCN3_Stack_Depth::update_stack_elapsed(elapsed);
 
-  // reset measurement:
-  prev_time = 0.0;
+  // reset measurement
+  prev_time.tv_sec = 0;
+  prev_time.tv_usec = 0;
 }
 
 void TTCN3_Profiler::set_prev(int stack_len, const char* filename, int lineno)
@@ -779,6 +1726,8 @@ void TTCN3_Profiler::set_prev(int stack_len, const char* filename, int lineno)
 
 int TTCN3_Stack_Depth::current_depth = -1;
 Vector<TTCN3_Stack_Depth::call_stack_timer_item_t> TTCN3_Stack_Depth::call_stack_timer_db;
+boolean TTCN3_Stack_Depth::net_line_times = FALSE;
+boolean TTCN3_Stack_Depth::net_func_times = FALSE;
 
 TTCN3_Stack_Depth::TTCN3_Stack_Depth() 
 {
@@ -801,6 +1750,16 @@ TTCN3_Stack_Depth::~TTCN3_Stack_Depth()
   --current_depth;
 }
 
+void TTCN3_Stack_Depth::set_net_line_times(boolean p_net_line_times)
+{
+  net_line_times = p_net_line_times;
+}
+
+void TTCN3_Stack_Depth::set_net_func_times(boolean p_net_func_times)
+{
+  net_func_times = p_net_func_times;
+}
+
 void TTCN3_Stack_Depth::add_stack(int stack_len, const char* caller_file, const char* func_file,
                                   int caller_line, int start_line) 
 {
@@ -810,19 +1769,55 @@ void TTCN3_Stack_Depth::add_stack(int stack_len, const char* caller_file, const
   item.func_file = func_file;
   item.caller_line = caller_line;
   item.start_line = start_line;
-  item.elapsed = 0.0;
+  item.elapsed.tv_sec = 0;
+  item.elapsed.tv_usec = 0;
+  item.first_call = true;
+  item.recursive_call = false;
+
+  if (!net_line_times || !net_func_times) {
+    // check if it's a recursive function
+    for (int i = current_depth - 1; i >= 0 ; --i) {
+      if (call_stack_timer_db[i].start_line == start_line &&
+          0 == strcmp(call_stack_timer_db[i].func_file, func_file)) {
+        item.recursive_call = true;
+
+        // check if the caller is new
+        if (call_stack_timer_db[i].caller_line == caller_line &&
+            ((NULL == call_stack_timer_db[i].caller_file && NULL == caller_file) ||
+             (NULL != call_stack_timer_db[i].caller_file && NULL != caller_file &&
+             0 == strcmp(call_stack_timer_db[i].caller_file, caller_file)))) {
+          item.first_call = false;
+          break;
+        }
+      }
+    }
+  }
+  
   call_stack_timer_db.push_back(item);
 }
 
 void TTCN3_Stack_Depth::remove_stack()
 {
-  // if stack level is the same or higher: measure the time:
-  double elapsed = call_stack_timer_db[current_depth].elapsed;
-
-  int element = ttcn3_prof.get_element(call_stack_timer_db[current_depth].func_file);
-
-  // add elapsed time to the total execution time of the previous line:
-  ttcn3_prof.add_function_time(elapsed, element, call_stack_timer_db[current_depth].start_line);
+  // add the time gathered for this stack level to the appropriate line and function
+  // except for functions starting at line 0 (pre_init_module and post_init_module)
+  if (0 != call_stack_timer_db[current_depth].start_line) {
+    timeval elapsed = call_stack_timer_db[current_depth].elapsed;
+    if (!net_line_times && NULL != call_stack_timer_db[current_depth].caller_file &&
+        call_stack_timer_db[current_depth].first_call) {
+      // add the elapsed time to the caller line, if it exists
+      // (only add it once for recursive functions, at the first call)
+      ttcn3_prof.add_line_time(elapsed,
+        ttcn3_prof.get_element(call_stack_timer_db[current_depth].caller_file),
+        call_stack_timer_db[current_depth].caller_line);
+    }
+    if (!net_func_times && !call_stack_timer_db[current_depth].recursive_call) {
+      // add the elapsed time to the called function, if it's not recursive
+      // (in case of net function times this has already been done in update_stack_elapsed)
+      ttcn3_prof.add_function_time(elapsed,
+        ttcn3_prof.get_element(call_stack_timer_db[current_depth].func_file),
+        call_stack_timer_db[current_depth].start_line);
+    }
+  }
 
   ttcn3_prof.set_prev(call_stack_timer_db[current_depth].stack_len, 
     call_stack_timer_db[current_depth].caller_file,
@@ -831,9 +1826,21 @@ void TTCN3_Stack_Depth::remove_stack()
   call_stack_timer_db.erase_at(current_depth);
 }
 
-void TTCN3_Stack_Depth::update_stack_elapsed(double elapsed) 
+void TTCN3_Stack_Depth::update_stack_elapsed(timeval elapsed) 
 {
-  for(int i = 0; i <= current_depth; i++) {
-    call_stack_timer_db[i].elapsed += elapsed;
+  // if function times are net times, only add the elapsed time to the current function
+  if (net_func_times) {
+    ttcn3_prof.add_function_time(elapsed,
+      ttcn3_prof.get_element(call_stack_timer_db[current_depth].func_file),
+      call_stack_timer_db[current_depth].start_line);
   }
-}
\ No newline at end of file
+  if (!net_line_times || !net_func_times) {
+    // cycle through the stack and add the elapsed time to the entries where 
+    // the function/caller pair appears for the first time (marked by 'first_call')
+    for(int i = 0; i <= current_depth; ++i) {
+      if (call_stack_timer_db[i].first_call) {
+        call_stack_timer_db[i].elapsed = add_timeval(call_stack_timer_db[i].elapsed, elapsed);
+      }
+    }
+  }
+}
index c84bb97a90b66a50aa66839e0278f8654fa25dfe..67b4081a1968031f903001b9fa14d99270462d9e 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "Vector.hh"
 #include "Types.h"
+#include <sys/time.h>
 
 /** This class performs profiling and code coverage on lines and functions in
   * TTCN-3 code (requires the -z compiler option).
@@ -22,8 +23,10 @@ public:
   struct profiler_db_item_t {
     /** Database entry for one line */
     struct profiler_line_data_t {
+      /** Line number */
+      int lineno;
       /** The line's total execution time */
-      double total_time;
+      timeval total_time;
       /** The number of times this line was executed */
       int exec_count;
     };
@@ -34,26 +37,78 @@ public:
       /** Function starting line */
       int lineno;
       /** The function's total execution time */
-      double total_time;
+      timeval total_time;
       /** The number of times this function was executed */
       int exec_count;
     };
     /** TTCN-3 File name (relative path, owned) */
     char* filename;
-    /** Contains database entries for all the lines in this file (its index is
-      * the line number, so there may be empty elements) */
+    /** Contains database entries for all the lines in this file */
     Vector<profiler_line_data_t> lines;
-    /** Contains database entries for all the functions in this file (one entry
-      * for each function) */
+    /** Contains database entries for all the functions in this file */
     Vector<profiler_function_data_t> functions;
   };
   
+  enum profiler_stats_flag_t {
+    // flags for each statistics entry
+    STATS_NUMBER_OF_LINES          = 0x0000001,
+    STATS_LINE_DATA_RAW            = 0x0000002,
+    STATS_FUNC_DATA_RAW            = 0x0000004,
+    STATS_LINE_AVG_RAW             = 0x0000008,
+    STATS_FUNC_AVG_RAW             = 0x0000010,
+    STATS_LINE_TIMES_SORTED_BY_MOD = 0x0000020,
+    STATS_FUNC_TIMES_SORTED_BY_MOD = 0x0000040,
+    STATS_LINE_TIMES_SORTED_TOTAL  = 0x0000080,
+    STATS_FUNC_TIMES_SORTED_TOTAL  = 0x0000100,
+    STATS_LINE_COUNT_SORTED_BY_MOD = 0x0000200,
+    STATS_FUNC_COUNT_SORTED_BY_MOD = 0x0000400,
+    STATS_LINE_COUNT_SORTED_TOTAL  = 0x0000800,
+    STATS_FUNC_COUNT_SORTED_TOTAL  = 0x0001000,
+    STATS_LINE_AVG_SORTED_BY_MOD   = 0x0002000,
+    STATS_FUNC_AVG_SORTED_BY_MOD   = 0x0004000,
+    STATS_LINE_AVG_SORTED_TOTAL    = 0x0008000,
+    STATS_FUNC_AVG_SORTED_TOTAL    = 0x0010000,
+    STATS_TOP10_LINE_TIMES         = 0x0020000,
+    STATS_TOP10_FUNC_TIMES         = 0x0040000,
+    STATS_TOP10_LINE_COUNT         = 0x0080000,
+    STATS_TOP10_FUNC_COUNT         = 0x0100000,
+    STATS_TOP10_LINE_AVG           = 0x0200000,
+    STATS_TOP10_FUNC_AVG           = 0x0400000,
+    STATS_UNUSED_LINES             = 0x0800000,
+    STATS_UNUSED_FUNC              = 0x1000000,
+    // grouped entries
+    STATS_ALL_RAW_DATA             = 0x000001E,
+    STATS_LINE_DATA_SORTED_BY_MOD  = 0x0002220,
+    STATS_FUNC_DATA_SORTED_BY_MOD  = 0x0004440,
+    STATS_LINE_DATA_SORTED_TOTAL   = 0x0008880,
+    STATS_FUNC_DATA_SORTED_TOTAL   = 0x0011100,
+    STATS_LINE_DATA_SORTED         = 0x000AAA0,
+    STATS_FUNC_DATA_SORTED         = 0x0015540,
+    STATS_ALL_DATA_SORTED          = 0x001FFE0,
+    STATS_TOP10_LINE_DATA          = 0x02A0000,
+    STATS_TOP10_FUNC_DATA          = 0x0540000,
+    STATS_TOP10_ALL_DATA           = 0x07E0000,
+    STATS_UNUSED_DATA              = 0x1800000,
+    STATS_ALL                      = 0x1FFFFFF
+  };
+  
   /** Constructor */
   TTCN3_Profiler();
-  /** Destructor - adds all gathered data to the database file and prints
-    * statistics if necessary */
+  /** Destructor 
+    * In single mode and in the Host Controller's process in parallel mode:
+    *  - imports data gathered on the previous run (if data aggregation is set)
+    *  - imports data gathered by all other processes (only in parallel mode)
+    *  - prints statistics (if necessary)
+    * Afterwards, in all cases:
+    *  - exports data gathered in this process (including any imported data)
+    *  - frees allocated memory */
   ~TTCN3_Profiler();
   
+  /** Reactivates the profiler if it was stopped before, data gathering will resume */
+  void start();
+  /** Deactivates the profiler, no more data will be gathered until it is reactivated */
+  void stop();
+  
   /** Enables or disables profiling - called by the config file parser */
   void set_disable_profiler(boolean p_disable_profiler);
   /** Enables or disables code coverage - called by the config file parser */
@@ -66,14 +121,21 @@ public:
   void set_stats_filename(const char* p_stats_filename);
   /** Enables or disables the printing of statistics - called by the config file parser */
   void set_disable_stats(boolean p_disable_stats);
+  /** Disables all statistics entry flags - called by the config file parser */
+  void reset_stats_flags();
+  /** Enables the specified statistics entry flags - called by the config file parser */
+  void add_stats_flags(unsigned int p_flags);
   
   /** Returns true if profiling is disabled */
   boolean is_profiler_disabled() const;
+  /** Returns true if the profiler is currently running (not stopped) */
+  boolean is_running() const;
   
-  /** Deletes the database file if data aggregation is not set */
-  void init_data_file();
+  /** Stores the component reference of a newly created PTC (in parallel mode only) */
+  void add_ptc(component p_comp_ref);
+
   /** Adds the data from the database file to the local database */
-  void import_data();
+  void import_data(component p_comp_ref = NULL_COMPREF);
   /** Writes the local database to the database file (overwrites the file) */
   void export_data();
   
@@ -83,9 +145,9 @@ public:
   /** Resets data related to the previous location and time (the local database is not changed) */
   void reset();
   /** Returns the current time (in seconds) */
-  static double get_time();
+  static timeval get_time();
   /** Called when a TTCN-3 function starts execution - stores data */
-  void enter_function(const char* filename, int lineno, const char* function_name);
+  void enter_function(const char* filename, int lineno);
   /** Called when a TTCN-3 code line starts execution - stores data */
   void execute_line(const char* filename, int lineno);
   /** Returns the index of a TTCN-3 file's entry in the local database */
@@ -99,18 +161,22 @@ public:
     * @param lineno function start line
     * @param function_name name of the function */
   void create_function(int element, int lineno, const char* function_name);
-  /** Creates TTCN-3 code line entries up to the given line number */
-  void create_lines(int element, int lineno);
+  /** Returns the index of a TTCN-3 code line's entry in the database */
+  int get_line(int element, int lineno);
+  /** Creates a new TTCN-3 code line entry and inserts it into the database */
+  void create_line(int element, int lineno);
   /** Adds elapsed time to the specified TTCN-3 code line's total time */
-  void add_line_time(double elapsed, int element, int lineno);
+  void add_line_time(timeval elapsed, int element, int lineno);
   /** Adds elapsed time to the specified TTCN-3 function's total time*/
-  void add_function_time(double elapsed, int element, int lineno);
+  void add_function_time(timeval elapsed, int element, int lineno);
   /** Called when a TTCN-3 function's execution ends - stores data */
   void update_last();
   /** Stores data related to the previous location */
   void set_prev(int stack_len, const char* filename, int lineno);
 
 private:
+  /** If true, the profiler ignores execute_line, enter_function and update_last calls */
+  boolean stopped;
   /** Profiling is disabled if true */
   boolean disable_profiler;
   /** Code coverage is disabled if true */
@@ -124,9 +190,10 @@ private:
   char* stats_filename;
   /** Statistics will not be calculated and printed if true */
   boolean disable_stats;
-  
+  /** Flags that determine which statistics entries are displayed */
+  unsigned int stats_flags;
   /** The time measured at the previous TTCN-3 code line */
-  double prev_time;
+  timeval prev_time;
   /** Name of the TTCN-3 file, where the last executed line is (not owned) */
   const char* prev_file;
   /** The number of the previously executed line */
@@ -135,6 +202,9 @@ private:
   Vector<profiler_db_item_t> profiler_db;
   /** The stack length at the previously executed line */
   int prev_stack_len;
+  /** Contains the component references of all PTCs (only relevant in the Host
+    * Controller's process, in parallel mode) */
+  Vector<component> ptc_list;
 };
 
 /** The global TTCN3_Profiler object
@@ -151,21 +221,27 @@ extern TTCN3_Profiler ttcn3_prof;
   * Its instances depict the current call stack. One instance is created at the start
   * of each TTCN-3 function execution, and it's destroyed at the function's end. */
 class TTCN3_Stack_Depth {
-public:
+public:  
   /** Entry for one function call in the call stack */
   struct call_stack_timer_item_t {
     /** Stack length before the function call */
     int stack_len;
     /** File name, where the calling function is declared (not owned) */
     const char* caller_file;
-    /** File name, where the called function is declared (not owned)*/
+    /** File name, where the called function is declared (not owned) */
     const char* func_file;
     /** Calling function's start line */
     int caller_line;
     /** Called function's start line */
     int start_line;
     /** Time elapsed in this function call */
-    double elapsed;
+    timeval elapsed;
+    /** If true, then this is the first entry of this function and caller pair
+      * (only used in case of gross line times) */
+    boolean first_call;
+    /** If true, then this function has appeared before in the call stack 
+      * (only used in case of gross function times)*/
+    boolean recursive_call;
   };
   
   /** Constructor - increases the stack depth */
@@ -173,6 +249,11 @@ public:
   /** Destructor - decreases the stack depth, updates call times in the profiler */
   ~TTCN3_Stack_Depth();
   
+  /** Sets whether line times should include function call times - called by the config file parser */
+  static void set_net_line_times(boolean p_net_line_times);
+  /** Sets whether function times should include embedded function times - called by the config file parser */
+  static void set_net_func_times(boolean p_net_func_times);
+  
   /** Returns the current stack depth */
   static int depth() { return current_depth; }
   /** Inserts a new function call entry into the call stack database */
@@ -181,12 +262,18 @@ public:
   /** Removes the last entry from the call stack database */
   static void remove_stack();
   /** Adds the elapsed time to all entries in the call stack database */
-  static void update_stack_elapsed(double elapsed);
+  static void update_stack_elapsed(timeval elapsed);
 private:
   /** The current stack depth (starts from 0)*/
   static int current_depth;
   /** The call stack database */
   static Vector<call_stack_timer_item_t> call_stack_timer_db;
+  /** If true, line times will not include the execution times of functions called
+    * in that line */
+  static boolean net_line_times;
+  /** If true, function times will not include the execution times of functions
+    * called in that function */
+  static boolean net_func_times;
 };
 
 #endif /* PROFILER_HH */
index b3163867164693757f858868b00adea8f3b9deb1..72947e8b8d7546aee3b960b0f62dbe80dc4fefaf 100644 (file)
@@ -340,7 +340,7 @@ int RAW_encode_enum_type(const TTCN_Typedescriptor_t& p_td,
   my_raw.ptroffset       = p_td.raw->ptroffset;
   my_raw.unit            = p_td.raw->unit;
   TTCN_Typedescriptor_t my_descr = { p_td.name, 0, &my_raw, NULL, NULL, NULL,
-    TTCN_Typedescriptor_t::DONTCARE };
+    NULL, TTCN_Typedescriptor_t::DONTCARE };
   INTEGER i(integer_value);
   i.RAW_encode(my_descr, myleaf);
   //  myleaf.align=0;//p_td.raw->endianness==ORDER_MSB?min_bits_enum-fl:fl-min_bits_enum;
@@ -369,7 +369,7 @@ int RAW_decode_enum_type(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff,
   my_raw.ptroffset       = p_td.raw->ptroffset;
   my_raw.unit            = p_td.raw->unit;
   TTCN_Typedescriptor_t my_descr = { p_td.name, 0, &my_raw, NULL, NULL, NULL,
-    TTCN_Typedescriptor_t::DONTCARE };
+    NULL, TTCN_Typedescriptor_t::DONTCARE };
   INTEGER i;
   /*  if(p_td.raw->endianness==ORDER_MSB)
    buff.increase_pos_bit(fl-min_bits_enum);*/
diff --git a/core/RefdIndex.hh b/core/RefdIndex.hh
new file mode 100644 (file)
index 0000000..2b2f4a6
--- /dev/null
@@ -0,0 +1,55 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2000-2015 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
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef REFDINDEX_HH
+#define REFDINDEX_HH
+
+#ifdef TITAN_RUNTIME_2
+
+/** This class contains the functions needed for adding and removing referenced
+  * indexes to record of/set of types and the optional type (only in RT2).
+  * By default the functions are empty.*/
+class RefdIndexInterface
+{
+public:
+  virtual ~RefdIndexInterface() {}
+  virtual void add_refd_index(int) {}
+  virtual void remove_refd_index(int) {}
+};
+
+/** References to record of/set of elements through 'out' and 'inout' function
+  * parameters are handled by this class.
+  * Usage: create instances of this class before the function call (one instance
+  * for each referenced index), and place the instances and the function call in
+  * a block (so the destructor is called immediately after the function call).
+  * This way the referenced indexes are cleaned up even if the function call ends
+  * with an exception (DTE) */
+class RefdIndexHandler
+{
+public:
+  RefdIndexHandler(RefdIndexInterface* p_container, int p_index)
+  {
+    container = p_container;
+    index = p_index;
+    container->add_refd_index(index);
+  }
+  
+  ~RefdIndexHandler()
+  {
+    container->remove_refd_index(index);
+  }
+  
+private:
+  RefdIndexInterface* container;
+  int index;
+};
+
+#endif /* TITAN_RUNTIME_2 */
+
+#endif /* REFDINDEX_HH */
+
index 24a8a9cc4f502b43a7b69ea2e9830726531babd5..25e07bb9d2105347e67e8914d304641b5f1a88c0 100644 (file)
@@ -41,6 +41,7 @@
 #include "Charstring.hh"
 #include "Fd_And_Timeout_User.hh"
 #include <TitanLoggerApi.hh>
+#include "Profiler.hh"
 
 namespace API = TitanLoggerApi;
 
@@ -403,6 +404,7 @@ int TTCN_Runtime::hc_main(const char *local_addr, const char *MC_addr,
       TTCN_Communication::set_local_address(local_addr);
     TTCN_Communication::set_mc_address(MC_addr, MC_port);
     TTCN_Communication::connect_mc();
+    Module_List::send_versions();
     executor_state = HC_IDLE;
     TTCN_Communication::send_version();
     initialize_component_process_tables();
@@ -2303,6 +2305,9 @@ void TTCN_Runtime::process_create_ptc(component component_reference,
       "state.");
     return;
   }
+  
+  // let the HC's TTCN-3 Profiler know of this new PTC
+  ttcn3_prof.add_ptc(component_reference);
 
   // clean Emergency log buffer before fork, to avoid duplication
   TTCN_Logger::ring_buffer_dump(false);
index e4d7375a5e3c948bc284018c88c2cc6eb6323808..0c2430675f31ea5040e6a2f5f7cd9848ecaba9f7 100644 (file)
@@ -22,6 +22,9 @@
 #include "Encdec.hh"
 #include "TitanLoggerApi.hh"
 #include "TCov.hh"
+#ifdef LINUX
+#include <execinfo.h>
+#endif  
 
 #ifdef LICENSE
 #include "../common/license.h"
 const char * stored_argv = "Unidentified program";
 
 static const char segfault[] = ": Segmentation fault occurred\n";
+static const char abortcall[] = ": Abort was called\n";
 
-void signal_handler(int)
+void signal_handler(int signum)
 {
   int retval;
   retval = write(STDERR_FILENO, stored_argv, strlen(stored_argv));
+  if(signum==SIGSEGV){
   retval = write(STDERR_FILENO, segfault , sizeof(segfault)-1); // sizeof includes \0
+  } else {
+  retval = write(STDERR_FILENO, abortcall , sizeof(abortcall)-1); // sizeof includes \0
+  }
+#ifdef LINUX
+  int nptrs;
+  void *buffer[100];
+  nptrs = backtrace(buffer, 100);
+  backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
+  
+  fflush(stderr);
+#endif
   (void)retval;
   TTCN_Logger::close_file();
 
+  signal(SIGABRT, SIG_DFL);
   abort();
 }
 
@@ -65,6 +82,7 @@ int main(int argc, char *argv[])
   sigemptyset(&act.sa_mask);
   act.sa_flags = 0;
   sigaction(SIGSEGV, &act, 0);
+  sigaction(SIGABRT, &act, 0);
 
 #ifdef MEMORY_DEBUG
   debug_new_counter.set_program_name(argv[0]);
index 4877d9533b854eac53f713d9ec95ba00efe07e46..42e32a7d6d3436a663a49c35e36364976a3bb913 100644 (file)
@@ -14,6 +14,7 @@
 #include <fcntl.h>
 #include <errno.h>
 
+#include <sys/select.h>
 #include <sys/types.h>
 #include <poll.h>
 #ifdef USE_EPOLL
index 91ddd7204416d02fcbc4288d99cef18c6cb8802e..d0b57c4a49c355a7499e3488ae5839a6691dfb4c 100644 (file)
@@ -268,6 +268,9 @@ const TTCN_TEXTdescriptor_t BOOLEAN_text_ = { NULL, NULL, NULL, NULL,
 const TTCN_TEXTdescriptor_t CHARSTRING_text_ = { NULL, NULL, NULL, NULL,
   NULL, NULL, NULL, { NULL } };
 
+const TTCN_TEXTdescriptor_t UNIVERSAL_CHARSTRING_text_ = { NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, { NULL } };
+
 const TTCN_TEXTdescriptor_t BITSTRING_text_ = { NULL, NULL, NULL, NULL,
   NULL, NULL, NULL, { NULL } };
 
index 4d3962d92de8be6a6b66d36bc8caac8bb86cd6aa..7a2483310423e937250386f938e8969536f83596 100644 (file)
@@ -121,6 +121,7 @@ extern const TTCN_TEXTdescriptor_t CHARSTRING_text_;
 extern const TTCN_TEXTdescriptor_t BITSTRING_text_;
 extern const TTCN_TEXTdescriptor_t HEXSTRING_text_;
 extern const TTCN_TEXTdescriptor_t OCTETSTRING_text_;
+extern const TTCN_TEXTdescriptor_t UNIVERSAL_CHARSTRING_text_;
 
 /** @} end of TEXT group */
 
index 405a340e65cb18b9af3dad66199b6783f316ed2a..6fb4305eb15577406a456ae828cf5e503f4f3297 100644 (file)
 
 #ifdef TITAN_RUNTIME_2
 #include "RT2/TitanLoggerApiSimple.hh"
+#include "RT2/PreGenRecordOf.hh"
 #else
 #include "RT1/TitanLoggerApiSimple.hh"
+#include "RT1/PreGenRecordOf.hh"
 #endif
 
 #include "Module_list.hh"
@@ -70,5 +72,6 @@
 #include "JSON.hh"
 #include "Error.hh"
 #include "XmlReader.hh"
+#include "Profiler.hh"
 
 #endif
index 44ccdc483f527ab62c4abf98d57fc2f79626404a..9b3a0d192518edd391321839cee2d811ecc982d0 100644 (file)
@@ -12,6 +12,7 @@
 
 #ifdef TITAN_RUNTIME_2
 #include "Struct_of.hh"
+#include "RefdIndex.hh"
 struct TTCN_Typedescriptor_t;
 struct Erroneous_descriptor_t;
 #endif
@@ -113,7 +114,11 @@ public:
 #endif
 };
 
-class Restricted_Length_Template : public Base_Template {
+class Restricted_Length_Template : public Base_Template
+#ifdef TITAN_RUNTIME_2
+  , public RefdIndexInterface
+#endif
+{
 protected:
   enum length_restriction_type_t {
     NO_LENGTH_RESTRICTION = 0,
@@ -160,12 +165,6 @@ public:
 
   boolean is_omit() const;
   boolean is_any_or_omit() const;
-  
-#ifdef TITAN_RUNTIME_2
-  // Dummy functions, only used in record of/set of value in RT2
-  void add_refd_index(int) {}
-  void remove_refd_index(int) {}
-#endif
 };
 
 #ifndef TITAN_RUNTIME_2
index 330f4f27b4fe44c75b3707cfae2a590c2d3216ef..9b7f53444650b76e34c3f32a94a94f60cce319f8 100644 (file)
@@ -19,6 +19,7 @@
 #include "Logger.hh"
 #include "Encdec.hh"
 #include "Addfunc.hh" // for unichar2int
+#include "TEXT.hh"
 #include <string>
 #include <iostream>
 #include <stdint.h>
@@ -200,7 +201,7 @@ UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
   other_value.must_bound("Initialization of a universal charstring with an "
     "unbound universal charstring element.");
   if (charstring) {
-    cstr = CHARSTRING(other_value.get_uchar().uc_cell);
+    cstr = CHARSTRING((const char)(other_value.get_uchar().uc_cell));
     val_ptr = NULL;
   } else {
     init_struct(1);
@@ -1068,6 +1069,13 @@ void UNIVERSAL_CHARSTRING::encode(const TTCN_Typedescriptor_t& p_td,
     TTCN_EncDec_ErrorContext::error_internal
       ("No RAW descriptor available for type '%s'.", p_td.name);
     break;}
+  case TTCN_EncDec::CT_TEXT: {
+    TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
+    if(!p_td.text)
+      TTCN_EncDec_ErrorContext::error_internal
+        ("No TEXT descriptor available for type '%s'.", p_td.name);
+    TEXT_encode(p_td,p_buf);
+    break;}
   case TTCN_EncDec::CT_XER: {
     TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
     unsigned XER_coding=va_arg(pvar, unsigned);
@@ -1117,6 +1125,24 @@ void UNIVERSAL_CHARSTRING::decode(const TTCN_Typedescriptor_t& p_td,
     TTCN_EncDec_ErrorContext::error_internal
       ("No RAW descriptor available for type '%s'.", p_td.name);
     break;}
+  case TTCN_EncDec::CT_TEXT: {
+    Limit_Token_List limit;
+    TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name);
+    if(!p_td.text)
+      TTCN_EncDec_ErrorContext::error_internal
+        ("No TEXT descriptor available for type '%s'.", p_td.name);
+    const unsigned char *b=p_buf.get_data();
+    if(b[p_buf.get_len()-1]!='\0'){
+      p_buf.set_pos(p_buf.get_len());
+      p_buf.put_zero(8,ORDER_LSB);
+      p_buf.rewind();
+    }
+    if(TEXT_decode(p_td,p_buf,limit)<0)
+      ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
+               "Can not decode type '%s', because invalid or incomplete"
+               " message was received"
+               , p_td.name);
+    break;}
   case TTCN_EncDec::CT_XER : {
     unsigned XER_coding=va_arg(pvar, unsigned);
     XmlReaderWrap reader(p_buf);
@@ -1200,6 +1226,198 @@ UNIVERSAL_CHARSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
   new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
   return new_tlv;
 }
+int UNIVERSAL_CHARSTRING::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
+  TTCN_Buffer& buff, Limit_Token_List& limit, boolean no_err, boolean /*first_call*/)
+{
+  int decoded_length = 0;
+  int str_len = 0;
+  clean_up();
+  if (p_td.text->begin_decode) {
+    int tl;
+    if ((tl = p_td.text->begin_decode->match_begin(buff)) < 0) {
+      if (no_err) return -1;
+      TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
+        "The specified token '%s' not found for '%s': ",
+        (const char*) *(p_td.text->begin_decode), p_td.name);
+      return 0;
+    }
+    decoded_length += tl;
+    buff.increase_pos(tl);
+  }
+  //  never return "not enough bits"
+  //  if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
+
+  if (p_td.text->select_token) {
+    int tl;
+    if ((tl = p_td.text->select_token->match_begin(buff)) < 0) {
+      if (no_err) return -1;
+      else tl = 0;
+    }
+    str_len = tl;
+  }
+  // The length restriction needs some more work
+/*  else if (   p_td.text->val.parameters
+    &&        p_td.text->val.parameters->decoding_params.min_length != -1) {
+    str_len = p_td.text->val.parameters->decoding_params.min_length;
+  }*/
+  else if (p_td.text->end_decode) {
+    int tl;
+    if ((tl = p_td.text->end_decode->match_first(buff)) < 0) {
+      if (no_err) return -1;
+      else tl = 0;
+    }
+    str_len = tl;
+  }
+  else if (limit.has_token()) {
+    int tl;
+    if ((tl = limit.match(buff)) < 0) tl = buff.get_read_len() - 1;
+    str_len = tl;
+  }
+  else {
+    str_len = buff.get_read_len() - 1;
+  }
+
+// only utf8 is supported now.
+  decode_utf8(str_len,buff.get_read_data());
+
+  decoded_length += str_len;
+  buff.increase_pos(str_len);
+
+// Case conversion is an another study
+// and it is locale dependent
+/*  if (  p_td.text->val.parameters
+    &&  p_td.text->val.parameters->decoding_params.convert != 0) {
+    if (p_td.text->val.parameters->decoding_params.convert == 1) {
+      for (int a = 0; a < str_len; a++) {
+        val_ptr->chars_ptr[a] = toupper(val_ptr->chars_ptr[a]);
+      }
+    }
+    else {
+      for (int a = 0; a < str_len; a++) {
+        val_ptr->chars_ptr[a] = tolower(val_ptr->chars_ptr[a]);
+      }
+    }
+  }*/
+  if (p_td.text->end_decode) {
+    int tl;
+    if ((tl = p_td.text->end_decode->match_begin(buff)) < 0) {
+      if (no_err) return -1;
+      TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
+        "The specified token '%s' not found for '%s': ",
+        (const char*) *(p_td.text->end_decode), p_td.name);
+      return 0;
+    }
+    decoded_length += tl;
+    buff.increase_pos(tl);
+  }
+  return decoded_length;
+}
+
+int UNIVERSAL_CHARSTRING::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
+                 TTCN_Buffer& buff) const{
+  int encoded_length=0;
+  if(p_td.text->begin_encode){
+    buff.put_cs(*p_td.text->begin_encode);
+    encoded_length+=p_td.text->begin_encode->lengthof();
+  }
+  if(!is_bound()) {
+    TTCN_EncDec_ErrorContext::error
+      (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value.");
+    if(p_td.text->end_encode){
+      buff.put_cs(*p_td.text->end_encode);
+      encoded_length+=p_td.text->end_encode->lengthof();
+    }
+    return encoded_length;
+  }
+
+// The length restriction and case conversion will be added later
+//  if(p_td.text->val.parameters==NULL){
+
+    int base_size=buff.get_len(); // strore the current length of the data 
+                                   // in the buffer
+    
+    encode_utf8(buff);
+    
+    encoded_length+=buff.get_len()-base_size;  // calculate the number of the
+                                               // stored octets
+
+/*  } else {
+    int chars_before=0;
+    int chars_after=0;
+    if(val_ptr->n_chars<p_td.text->val.parameters->coding_params.min_length){
+      switch(p_td.text->val.parameters->coding_params.just){
+        case -1: //left
+          chars_after=p_td.text->
+              val.parameters->coding_params.min_length-val_ptr->n_chars;
+          break;
+        case 0:{  // center
+          int pad=p_td.text->
+              val.parameters->coding_params.min_length-val_ptr->n_chars;
+          chars_after=pad/2;
+          chars_before=pad-chars_after;
+          break;
+          }
+        case 1:  // right
+        default:
+          chars_before=p_td.text->
+              val.parameters->coding_params.min_length-val_ptr->n_chars;
+          break;
+      }
+    }
+    if(chars_before){
+      unsigned char* p=NULL;
+      size_t len=chars_before;
+      buff.get_end(p,len);
+      for(int a=0;a<chars_before;a++) p[a]=(unsigned char)' ';
+      buff.increase_length(chars_before);
+      encoded_length+=chars_before;
+    }
+
+    switch(p_td.text->val.parameters->coding_params.convert){
+      case -1:{ //lower_case
+        unsigned char* p=NULL;
+        size_t len=val_ptr->n_chars;
+        buff.get_end(p,len);
+        for(int a=0;a<val_ptr->n_chars;a++)
+            p[a]=(unsigned char)tolower(val_ptr->chars_ptr[a]);
+        buff.increase_length(val_ptr->n_chars);
+        break;
+        }
+      case 0:{  // no conversion
+        buff.put_cs(*this);
+        break;
+        }
+      case 1:  // upper_case
+      default:
+        {
+        unsigned char* p=NULL;
+        size_t len=val_ptr->n_chars;
+        buff.get_end(p,len);
+        for(int a=0;a<val_ptr->n_chars;a++)
+            p[a]=(unsigned char)toupper(val_ptr->chars_ptr[a]);
+        buff.increase_length(val_ptr->n_chars);
+        break;
+        }
+    }
+    encoded_length+=val_ptr->n_chars;
+
+    if(chars_after){
+      unsigned char* p=NULL;
+      size_t len=chars_after;
+      buff.get_end(p,len);
+      for(int a=0;a<chars_after;a++) p[a]=(unsigned char)' ';
+      buff.increase_length(chars_after);
+      encoded_length+=chars_after;
+    }
+  }
+*/
+
+  if(p_td.text->end_encode){
+    buff.put_cs(*p_td.text->end_encode);
+    encoded_length+=p_td.text->end_encode->lengthof();
+  }
+  return encoded_length;
+}
 
 void UNIVERSAL_CHARSTRING::encode_utf8(TTCN_Buffer& buf, bool addBOM /*= false*/) const
 {
@@ -2214,7 +2432,9 @@ void UNIVERSAL_CHARSTRING::decode_utf8(int n_octets,
     // count all octets except the continuing octets (10xxxxxx)
     if ((octets_ptr[i] & 0xC0) != 0x80) n_uchars++;
   }
-  // allocate enough memory
+  // allocate enough memory, start from clean state
+  clean_up();
+  charstring=false;
   init_struct(n_uchars);
   n_uchars = 0;
 
@@ -2676,22 +2896,13 @@ UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
 {
   other_value.must_bound("Assignment of an unbound universal charstring value "
     "to a universal charstring element.");
-  if (other_value.val_ptr->n_uchars != 1)
+  int other_value_size = other_value.charstring ? other_value.cstr.val_ptr->n_chars :
+    other_value.val_ptr->n_uchars;
+  if (other_value_size != 1)
     TTCN_error("Assignment of a universal charstring value with length other "
       "than 1 to a universal charstring element.");
   bound_flag = TRUE;
-  const universal_char& uchar = other_value.val_ptr->uchars_ptr[0];
-  if (str_val.charstring) {
-    if (uchar.is_char())
-      str_val.cstr.val_ptr->chars_ptr[uchar_pos] = uchar.uc_cell;
-    else {
-      str_val.convert_cstr_to_uni();
-      str_val.val_ptr->uchars_ptr[uchar_pos] = uchar;
-    }
-  } else {
-    str_val.copy_value();
-    str_val.val_ptr->uchars_ptr[uchar_pos] = uchar;
-  }
+  *this = other_value[0];
   return *this;
 }
 
index 62ea9fbf953588f53d5f1a6d1ba90ba31c57a8b7..5d2e66a61642b62b93e794f20b5183eaa1da8206 100644 (file)
@@ -318,6 +318,10 @@ public:
   boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
                          const ASN_BER_TLV_t& p_tlv, unsigned L_form);
   
+  int TEXT_encode(const TTCN_Typedescriptor_t&,
+                 TTCN_Buffer&) const;
+  int TEXT_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&,  Limit_Token_List&,
+                  boolean no_err=FALSE, boolean first_call=TRUE);
   int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int, embed_values_enc_struct_t*) const;
   int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int, embed_values_dec_struct_t*);
   /** Decodes UTF-8 into the internal representation (UCS4-BE)
index 604ca048f95e60730eacac3fbd23723e45ac8eba..78262afc400cd9ed3ce07821a02f919f29d08490 100644 (file)
@@ -19,6 +19,11 @@ class Base_Type;
 #ifdef TITAN_RUNTIME_2
 class Record_Of_Type;
 class Erroneous_descriptor_t;
+#else
+namespace PreGenRecordOf {
+  class PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING;
+  class PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING__OPTIMIZED;
+}
 #endif
 class TTCN_Module;
 
@@ -255,6 +260,9 @@ struct XERdescriptor_t
     * or invalid ("anyElement except ...") namespace URIs. 
     * The unqualified namespace is marked by an empty string ("").*/
   const char** ns_uris; 
+  
+  /** Points to the element type's XER descriptor in case of 'record of' and 'set of' types */
+  const XERdescriptor_t* oftype_descr;
 };
 
 /** Information related to the embedded values in XML encoding
@@ -273,11 +281,10 @@ struct embed_values_enc_struct_t
   /** Erroneous descriptor index for the embedded values (for negative tests) */
   int embval_err_descr_idx;
 #else
-  /** Stores the array of embedded values as a Base_Type (use get_embedded_value
-    * to retrieve values - temporarily disabled) */
-  const Base_Type* embval_array;
-  /** Stores the size of the embedded value array */
-  int embval_size;
+  /** Stores the array of embedded values (regular record-of) */
+  const PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING* embval_array_reg;
+  /** Stores the array of embedded values (optimized record-of) */
+  const PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING__OPTIMIZED* embval_array_opt;
 #endif
   /** Stores the index of the next embedded value to be read */
   int embval_index;
@@ -293,9 +300,10 @@ struct embed_values_dec_struct_t
   /** Stores the array of embedded values */
   Record_Of_Type* embval_array;
 #else
-  /** Stores the array of embedded values as a Base_type (use set_embedded_value
-    * to insert new values - temporarily disabled) */
-  Base_Type* embval_array;
+  /** Stores the array of embedded values (regular record-of) */
+  PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING* embval_array_reg;
+  /** Stores the array of embedded values (optimized record-of) */
+  PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING__OPTIMIZED* embval_array_opt;
 #endif
   /** Stores the number of embedded values that are currently in the array,
     * and the index where the next one should be inserted */
@@ -414,7 +422,7 @@ void check_namespace_restrictions(const XERdescriptor_t& p_td, const char* p_xml
   extern const XERdescriptor_t type_name##_xer_ = { \
     { xmlname ">\n", xmlname ">\n" }, \
     { 2+sizeof(xmlname)-1, 2+sizeof(xmlname)-1 }, \
-    0UL, WHITESPACE_PRESERVE, NULL, NULL, 0, 0, NULL }
+    0UL, WHITESPACE_PRESERVE, NULL, NULL, 0, 0, NULL, NULL }
 // The compiler should fold the two identical strings into one
 
 # define XER_STRUCT_COPY(cpy,original) \
index 4d96260b1aa2990abd05c792e4cf5af9a164cb6b..dafbf2d1d45387ababba9205a0ebf6c50c4b3648 100644 (file)
@@ -35,6 +35,8 @@
 
 #include "../common/dbgnew.hh"
 
+#include "Profiler.hh"
+
 extern string_map_t *config_defines;
 
 #define yylval config_process_lval
@@ -276,6 +278,25 @@ TTCNSTRINGPARSING_COMPONENT "$#&&&(#TTCNSTRINGPARSING_COMPONENT$#&&^#% "
 
 . /* eat unnecessary chars */
 
+}
+
+<SC_PROFILER>{HEX}+ {
+  /* numeric statistics filter (check this before checking for NUMBERs) */
+  yylval.uint_val = 0;
+  while(0 != *yytext) {
+    yylval.uint_val *= 16;
+    if ('0' <= *yytext && '9' >= *yytext) {
+      yylval.uint_val += *yytext - '0';
+    }
+    else if ('a' <= *yytext && 'f' >= *yytext) {
+      yylval.uint_val += *yytext - 'a' + 10;
+    }
+    else {
+      yylval.uint_val += *yytext - 'A' + 10;
+    }
+    ++yytext;
+  }
+  return ProfilerStatsFlag;
 }
 
        /* Values */
@@ -966,12 +987,170 @@ LOG_ALL  {
 
 <SC_PROFILER>
 {
-  [Dd]isable[Pp]rofiler   return DisableProfilerKeyword;
-  [Dd]isable[Cc]overage   return DisableCoverageKeyword;
-  [Dd]ata[Bb]ase[Ff]ile   return DatabaseFileKeyword;
-  [Aa]ggregate[Dd]ata     return AggregateDataKeyword;
-  [Ss]tatistics[Ff]ile    return StatisticsFileKeyword;
-  [Dd]isable[Ss]tatistics return DisableStatisticsKeyword;
+  [Dd]isable[Pp]rofiler     return DisableProfilerKeyword;
+  [Dd]isable[Cc]overage     return DisableCoverageKeyword;
+  [Dd]ata[Bb]ase[Ff]ile     return DatabaseFileKeyword;
+  [Aa]ggregate[Dd]ata       return AggregateDataKeyword;
+  [Ss]tatistics[Ff]ile      return StatisticsFileKeyword;
+  [Dd]isable[Ss]tatistics   return DisableStatisticsKeyword;
+  [Ss]tatistics[Ff]ilter    return StatisticsFilterKeyword;
+  [Ss]tart[Aa]utomatically  return StartAutomaticallyKeyword;
+  [Nn]et[Ll]ine[Tt]imes     return NetLineTimesKeyword;
+  [Nn]et[Ff]unction[Tt]imes return NetFunctionTimesKeyword;
+  
+  /* statistics filters */
+  [Nn]umber[Oo]f[Ll]ines {
+    yylval.uint_val = TTCN3_Profiler::STATS_NUMBER_OF_LINES;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Dd]ata[Rr]aw {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_DATA_RAW;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Dd]ata[Rr]aw {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_DATA_RAW;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Aa]vg[Rr]aw {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_AVG_RAW;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Aa]vg[Rr]aw {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_AVG_RAW;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Tt]imes[Ss]orted[Bb]y[Mm]od {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_TIMES_SORTED_BY_MOD;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Tt]imes[Ss]orted[Bb]y[Mm]od {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_TIMES_SORTED_BY_MOD;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Tt]imes[Ss]orted[Tt]otal {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_TIMES_SORTED_TOTAL;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Tt]imes[Ss]orted[Tt]otal {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_TIMES_SORTED_TOTAL;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Cc]ount[Ss]orted[Bb]y[Mm]od {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_COUNT_SORTED_BY_MOD;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Cc]ount[Ss]orted[Bb]y[Mm]od {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_COUNT_SORTED_BY_MOD;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Cc]ount[Ss]orted[Tt]otal {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_COUNT_SORTED_TOTAL;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Cc]ount[Ss]orted[Tt]otal {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_COUNT_SORTED_TOTAL;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Aa]vg[Ss]orted[Bb]y[Mm]od {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_AVG_SORTED_BY_MOD;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Aa]vg[Ss]orted[Bb]y[Mm]od {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_AVG_SORTED_BY_MOD;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Aa]vg[Ss]orted[Tt]otal {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_AVG_SORTED_TOTAL;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Aa]vg[Ss]orted[Tt]otal {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_AVG_SORTED_TOTAL;
+    return ProfilerStatsFlag;
+  }
+  [Tt]op10[Ll]ine[Tt]imes {
+    yylval.uint_val = TTCN3_Profiler::STATS_TOP10_LINE_TIMES;
+    return ProfilerStatsFlag;
+  }
+  [Tt]op10[Ff]unc[Tt]imes {
+    yylval.uint_val = TTCN3_Profiler::STATS_TOP10_FUNC_TIMES;
+    return ProfilerStatsFlag;
+  }
+  [Tt]op10[Ll]ine[Cc]ount {
+    yylval.uint_val = TTCN3_Profiler::STATS_TOP10_LINE_COUNT;
+    return ProfilerStatsFlag;
+  }
+  [Tt]op10[Ff]unc[Cc]ount {
+    yylval.uint_val = TTCN3_Profiler::STATS_TOP10_FUNC_COUNT;
+    return ProfilerStatsFlag;
+  }
+  [Tt]op10[Ll]ine[Aa]vg {
+    yylval.uint_val = TTCN3_Profiler::STATS_TOP10_LINE_AVG;
+    return ProfilerStatsFlag;
+  }
+  [Tt]op10[Ff]unc[Aa]vg {
+    yylval.uint_val = TTCN3_Profiler::STATS_TOP10_FUNC_AVG;
+    return ProfilerStatsFlag;
+  }
+  [Uu]nused[Ll]ines {
+    yylval.uint_val = TTCN3_Profiler::STATS_UNUSED_LINES;
+    return ProfilerStatsFlag;
+  }
+  [Uu]nused[Ff]unc {
+    yylval.uint_val = TTCN3_Profiler::STATS_UNUSED_FUNC;
+    return ProfilerStatsFlag;
+  }
+  [Aa]ll[Rr]aw[Dd]ata {
+    yylval.uint_val = TTCN3_Profiler::STATS_ALL_RAW_DATA;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Dd]ata[Ss]orted[Bb]y[Mm]od {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_DATA_SORTED_BY_MOD;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Dd]ata[Ss]orted[Bb]y[Mm]od {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_DATA_SORTED_BY_MOD;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Dd]ata[Ss]orted[Tt]otal {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_DATA_SORTED_TOTAL;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Dd]ata[Ss]orted[Tt]otal {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_DATA_SORTED_TOTAL;
+    return ProfilerStatsFlag;
+  }
+  [Ll]ine[Dd]ata[Ss]orted {
+    yylval.uint_val = TTCN3_Profiler::STATS_LINE_DATA_SORTED;
+    return ProfilerStatsFlag;
+  }
+  [Ff]unc[Dd]ata[Ss]orted {
+    yylval.uint_val = TTCN3_Profiler::STATS_FUNC_DATA_SORTED;
+    return ProfilerStatsFlag;
+  }
+  [Aa]ll[Dd]ata[Ss]orted {
+    yylval.uint_val = TTCN3_Profiler::STATS_ALL_DATA_SORTED;
+    return ProfilerStatsFlag;
+  }
+  [Tt]op10[Ll]ine[Dd]ata {
+    yylval.uint_val = TTCN3_Profiler::STATS_TOP10_LINE_DATA;
+    return ProfilerStatsFlag;
+  }
+  [Tt]op10[Ff]unc[Dd]ata {
+    yylval.uint_val = TTCN3_Profiler::STATS_TOP10_FUNC_DATA;
+    return ProfilerStatsFlag;
+  }
+  [Tt]op10[Aa]ll[Dd]ata {
+    yylval.uint_val = TTCN3_Profiler::STATS_TOP10_ALL_DATA;
+    return ProfilerStatsFlag;
+  }
+  [Uu]nused[Dd]ata {
+    yylval.uint_val = TTCN3_Profiler::STATS_UNUSED_DATA;
+    return ProfilerStatsFlag;
+  }
+  [Aa]ll {
+    yylval.uint_val = TTCN3_Profiler::STATS_ALL;
+    return ProfilerStatsFlag;
+  }
 }
 
 <SC_EXECUTE>control            return ControlKeyword;
index 92c2097982d567b54068a04efc47472b24058a26..28dce692f7680b4383606f3e6a638ff60f906818 100644 (file)
@@ -219,12 +219,17 @@ string_map_t *config_defines;
 %token Retry
 %token Delete
 %token TtcnStringParsingKeyword
-%token DisableProfilerKeyword   "DisableProfiler"
-%token DisableCoverageKeyword   "DisableCoverage"
-%token DatabaseFileKeyword      "DatabaseFile"
-%token AggregateDataKeyword     "AggregateData"
-%token StatisticsFileKeyword    "StatisticsFile"
-%token DisableStatisticsKeyword "DisableStatistics"
+%token DisableProfilerKeyword    "DisableProfiler"
+%token DisableCoverageKeyword    "DisableCoverage"
+%token DatabaseFileKeyword       "DatabaseFile"
+%token AggregateDataKeyword      "AggregateData"
+%token StatisticsFileKeyword     "StatisticsFile"
+%token DisableStatisticsKeyword  "DisableStatistics"
+%token StatisticsFilterKeyword   "StatisticsFilter"
+%token StartAutomaticallyKeyword "StartAutomatically"
+%token NetLineTimesKeyword       "NetLineTimes"
+%token NetFunctionTimesKeyword   "NetFunctionTimes"
+%token <uint_val> ProfilerStatsFlag "profiler statistics filter"
 
 %type <int_val> IntegerValue
 %type <float_val> FloatValue
@@ -269,6 +274,7 @@ string_map_t *config_defines;
 %type <module_param_length_restriction> LengthMatch
 %type <str_val> PatternChunk PatternChunkList
 %type <int_native> IndexItemIndex LengthBound
+%type <uint_val> ProfilerStatsFlags
 
 %destructor { Free($$); }
 ArrayRef
@@ -1688,6 +1694,10 @@ ProfilerSetting:
 | AggregateDataSetting
 | StatisticsFileSetting
 | DisableStatisticsSetting
+| StatisticsFilterSetting
+| StartAutomaticallySetting
+| NetLineTimesSetting
+| NetFunctionTimesSetting
 ;
 
 DisableProfilerSetting:
@@ -1726,6 +1736,46 @@ DisableStatisticsSetting:
   }
 ;
 
+StatisticsFilterSetting:
+  StatisticsFilterKeyword AssignmentChar ProfilerStatsFlags {
+    ttcn3_prof.reset_stats_flags();
+    ttcn3_prof.add_stats_flags($3);
+  }
+| StatisticsFilterKeyword ConcatChar ProfilerStatsFlags {
+    ttcn3_prof.add_stats_flags($3);
+  }
+;
+
+ProfilerStatsFlags:
+  ProfilerStatsFlag                        { $$ = $1; }
+| ProfilerStatsFlag '&' ProfilerStatsFlags { $$ = $1 | $3; }
+| ProfilerStatsFlag '|' ProfilerStatsFlags { $$ = $1 | $3; }
+;
+
+StartAutomaticallySetting:
+  StartAutomaticallyKeyword AssignmentChar BooleanValue {
+    if ($3) {
+      ttcn3_prof.start();
+    }
+    else {
+      ttcn3_prof.stop();
+    }
+  }
+;
+
+NetLineTimesSetting:
+  NetLineTimesKeyword AssignmentChar BooleanValue {
+    TTCN3_Stack_Depth::set_net_line_times($3);
+  }
+;
+
+NetFunctionTimesSetting:
+  NetFunctionTimesKeyword AssignmentChar BooleanValue {
+    TTCN3_Stack_Depth::set_net_func_times($3);
+  }
+;
+
+
 /**************** [TESTPORT_PARAMETERS] ****************************/
 
 TestportParametersSection:
@@ -2207,8 +2257,6 @@ boolean process_config_file(const char *file_name)
   string_map_free(config_defines);
   config_defines = NULL;
 
-  ttcn3_prof.init_data_file();
-
   return !error_flag;
 }
 
index c3389472e8623e0e31ea97b5d804de3f5930128d..189fa743f54e78132097a53377bd4c384c638389 100644 (file)
@@ -856,7 +856,7 @@ int Record_Of_Type::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
     }
     return encoded_length;
   }
-  const TTCN_Typedescriptor_t* elem_descr = get_elem_descr();
+  const TTCN_Typedescriptor_t* elem_descr = p_td.oftype_descr;
   for(int a=0;a<get_nof_elements();a++) {
     if(a!=0 && p_td.text->separator_encode) {
       buff.put_cs(*p_td.text->separator_encode);
@@ -942,9 +942,9 @@ int Record_Of_Type::TEXT_encode_negtest(const Erroneous_descriptor_t* p_err_desc
       }
       if (emb_descr) {
         encoded_length += get_at(a)->TEXT_encode_negtest(
-          emb_descr,*get_elem_descr(),buff);
+          emb_descr,*p_td.oftype_descr,buff);
       } else {
-        encoded_length += get_at(a)->TEXT_encode(*get_elem_descr(),buff);
+        encoded_length += get_at(a)->TEXT_encode(*p_td.oftype_descr,buff);
       }
       need_separator=true;
     }
@@ -1012,7 +1012,7 @@ int Record_Of_Type::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
   while(TRUE){
     Base_Type* val = create_elem();
     pos=buff.get_pos();
-    int len = val->TEXT_decode(*get_elem_descr(),buff,limit,TRUE);
+    int len = val->TEXT_decode(*p_td.oftype_descr,buff,limit,TRUE);
     if(len==-1 || (len==0 && !limit.has_token())){
       buff.set_pos(pos);
       delete val;
@@ -1103,7 +1103,7 @@ ASN_BER_TLV_t* Record_Of_Type::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
     TTCN_EncDec_ErrorContext ec;
     for(int elem_i=0; elem_i<get_nof_elements(); elem_i++) {
       ec.set_msg("Component #%d: ", elem_i);
-      new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV(*get_elem_descr(), p_coding));
+      new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV(*p_td.oftype_descr, p_coding));
     }
     if (is_set()) new_tlv->sort_tlvs();
   }
@@ -1156,10 +1156,10 @@ ASN_BER_TLV_t* Record_Of_Type::BER_encode_TLV_negtest(const Erroneous_descriptor
         ec.set_msg("Component #%d: ", elem_i);
         if (emb_descr) {
           new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV_negtest(
-            emb_descr, *get_elem_descr(), p_coding));
+            emb_descr, *p_td.oftype_descr, p_coding));
         } else {
           new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV(
-            *get_elem_descr(), p_coding));
+            *p_td.oftype_descr, p_coding));
         }
       }
 
@@ -1199,7 +1199,7 @@ boolean Record_Of_Type::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
   TTCN_EncDec_ErrorContext ec_1("Component #");
   TTCN_EncDec_ErrorContext ec_2("0: ");
   while(BER_decode_constdTLV_next(stripped_tlv, V_pos, L_form, tmp_tlv)) {
-    get_at(get_nof_elements())->BER_decode_TLV(*get_elem_descr(), tmp_tlv, L_form);
+    get_at(get_nof_elements())->BER_decode_TLV(*p_td.oftype_descr, tmp_tlv, L_form);
     ec_2.set_msg("%d: ", val_ptr->n_elements);
   }
   return TRUE;
@@ -1232,7 +1232,7 @@ int Record_Of_Type::RAW_decode(const TTCN_Typedescriptor_t& p_td,
     set_size(0);
   }
   int start_field = get_nof_elements(); // append at the end
-  TTCN_Typedescriptor_t const& elem_descr = *get_elem_descr();
+  TTCN_Typedescriptor_t const& elem_descr = *p_td.oftype_descr;
   if (p_td.raw->fieldlength || sel_field != -1) {
     if (sel_field == -1) sel_field = p_td.raw->fieldlength;
     for (int a = 0; a < sel_field; a++) {
@@ -1250,7 +1250,6 @@ int Record_Of_Type::RAW_decode(const TTCN_Typedescriptor_t& p_td,
       if (!first_call) return -1;
       goto finished;
     }
-    int ext_bit = rawdec_ebv();
     while (limit > 0) {
       start_of_field = buff.get_pos_bit();
       Base_Type* field_bt = get_at(a); // non-const, extend the record-of
@@ -1267,12 +1266,11 @@ int Record_Of_Type::RAW_decode(const TTCN_Typedescriptor_t& p_td,
       decoded_length += decoded_field_length;
       limit -= decoded_field_length;
       a++;
-      if (ext_bit != 1/*XDEFNO*/&& ext_bit != -1/*XDEFDEFAULT*/) {
-        // ext_bit here may be 2 (XDEFYES) or 3 (XDEFREVERSE).
-        // (ext_bit != 2) is   0           or 1
+      if (EXT_BIT_NO != p_td.raw->extension_bit) {
+        // (EXT_BIT_YES != p_td.raw->extension_bit) is 0 or 1
         // This is the opposite value of what the bit needs to be to signal
         // the end of decoding, because x-or is the equivalent of !=
-        if ((ext_bit != 2/*XDEFYES*/) ^ buff.get_last_bit()) {
+        if ((EXT_BIT_YES != p_td.raw->extension_bit) ^ buff.get_last_bit()) {
           goto finished;
         }
       }
@@ -1294,7 +1292,7 @@ int Record_Of_Type::RAW_encode(const TTCN_Typedescriptor_t& p_td, RAW_enc_tree&
   myleaf.rec_of = TRUE;
   myleaf.body.node.num_of_nodes = encoded_num_of_records;
   myleaf.body.node.nodes = init_nodes_of_enc_tree(encoded_num_of_records);
-  TTCN_Typedescriptor_t const& elem_descr = *get_elem_descr();
+  TTCN_Typedescriptor_t const& elem_descr = *p_td.oftype_descr;
   for (int a = 0; a < encoded_num_of_records; a++) {
     const Base_Type *field_bt = get_at(a);
     myleaf.body.node.nodes[a] = new RAW_enc_tree(TRUE, &myleaf, &(myleaf.curr_pos), a, elem_descr.raw);
@@ -1345,7 +1343,7 @@ int Record_Of_Type::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr
       continue;
     const Erroneous_values_t *err_vals = p_err_descr->next_field_err_values(i, values_idx);
     const Erroneous_descriptor_t *emb_descr = p_err_descr->next_field_emb_descr(i, edescr_idx);
-    TTCN_Typedescriptor_t const& elem_descr = *get_elem_descr();
+    TTCN_Typedescriptor_t const& elem_descr = *p_td.oftype_descr;
     if (err_vals && err_vals->before) {
       if (err_vals->before->errval == NULL)
         TTCN_error("internal error: erroneous before value missing");
@@ -1388,11 +1386,11 @@ int Record_Of_Type::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr
         myleaf.body.node.nodes[node_pos] = new RAW_enc_tree(TRUE, &myleaf,
           &(myleaf.curr_pos), node_pos, elem_descr.raw);
         encoded_length += get_at(i)->RAW_encode_negtest(emb_descr, 
-          *get_elem_descr(), *myleaf.body.node.nodes[node_pos++]);
+          *p_td.oftype_descr, *myleaf.body.node.nodes[node_pos++]);
       } else {
         myleaf.body.node.nodes[node_pos] = new RAW_enc_tree(TRUE, &myleaf,
           &(myleaf.curr_pos), node_pos, elem_descr.raw);
-        encoded_length += get_at(i)->RAW_encode(*get_elem_descr()
+        encoded_length += get_at(i)->RAW_encode(*p_td.oftype_descr
           *myleaf.body.node.nodes[node_pos++]);
       }
     }
@@ -1421,7 +1419,7 @@ int Record_Of_Type::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr
   return myleaf.length = encoded_length;
 }
 
-int Record_Of_Type::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
+int Record_Of_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
 {
   if (!is_bound()) {
     TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
@@ -1432,7 +1430,7 @@ int Record_Of_Type::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_
   int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
   
   for(int i = 0; i < get_nof_elements(); ++i) {
-    int ret_val = get_at(i)->JSON_encode(*get_elem_descr(), p_tok);
+    int ret_val = get_at(i)->JSON_encode(*p_td.oftype_descr, p_tok);
     if (0 > ret_val) break;
     enc_len += ret_val;
   }
@@ -1458,7 +1456,7 @@ int Record_Of_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenize
     // Read value tokens until we reach some other token
     size_t buf_pos = p_tok.get_buf_pos();
     Base_Type* val = create_elem();
-    int ret_val = val->JSON_decode(*get_elem_descr(), p_tok, p_silent);
+    int ret_val = val->JSON_decode(*p_td.oftype_descr, p_tok, p_silent);
     if (JSON_ERROR_INVALID_TOKEN == ret_val) {
       // undo the last action on the buffer
       p_tok.set_buf_pos(buf_pos);
@@ -1634,7 +1632,7 @@ char **Record_Of_Type::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool
     if (val_ptr) for (int i = 0; i < get_nof_elements(); ++i) {
       size_t num_new = 0;
       char **new_namespaces = get_at(i)->collect_ns(
-        *get_elem_descr()->xer, num_new, def_ns_1);
+        *p_td.oftype_descr, num_new, def_ns_1);
       merge_ns(collected_ns, num_collected, new_namespaces, num_new);
       def_ns = def_ns || def_ns_1; // alas, no ||=
     }
@@ -1786,6 +1784,8 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
   }
   else { // not ANY-ATTRIBUTES
     unsigned int sub_flavor = flavor | XER_RECOF | (p_td.xer_bits & (XER_LIST));
+    TTCN_EncDec_ErrorContext ec_0("Index ");
+    TTCN_EncDec_ErrorContext ec_1;
 
     for (int i = 0; i < nof_elements; ++i) {
       if (i > 0 && !own_tag && 0 != emb_val &&
@@ -1794,8 +1794,9 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
           UNIVERSAL_CHARSTRING_xer_, p_buf, flavor | EMBED_VALUES, indent+1, 0);
         ++emb_val->embval_index;
       }
+      ec_1.set_msg("%d: ", i);
       if (exer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');
-      get_at(i)->XER_encode(*get_elem_descr()->xer, p_buf,
+      get_at(i)->XER_encode(*p_td.oftype_descr, p_buf,
         sub_flavor, indent+own_tag, emb_val);
     }
 
@@ -1824,7 +1825,7 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
  * @param indent indentation level
  * @return number of bytes generated
  */
-int Record_Of_Type::encode_element(int i,
+int Record_Of_Type::encode_element(int i, const XERdescriptor_t& p_td,
   const Erroneous_values_t* ev, const Erroneous_descriptor_t* ed,
   TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent, embed_values_enc_struct_t* emb_val) const
 {
@@ -1869,10 +1870,10 @@ int Record_Of_Type::encode_element(int i,
   } else {
     ec.set_msg("Component #%d: ", i);
     if (ed) {
-      get_at(i)->XER_encode_negtest(ed, *get_elem_descr()->xer, p_buf, sub_flavor, indent, emb_val);
+      get_at(i)->XER_encode_negtest(ed, p_td, p_buf, sub_flavor, indent, emb_val);
     } else {
       // the "real" encoder
-      get_at(i)->XER_encode(*get_elem_descr()->xer, p_buf, sub_flavor, indent, emb_val);
+      get_at(i)->XER_encode(p_td, p_buf, sub_flavor, indent, emb_val);
     }
   }
 
@@ -2069,8 +2070,8 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr
           ev0_i = emb_val->embval_err->next_field_err_values(emb_val->embval_index, emb_val->embval_err_val_idx);
           ed0_i = emb_val->embval_err->next_field_emb_descr (emb_val->embval_index, emb_val->embval_err_descr_idx);
         }
-        emb_val->embval_array->encode_element(emb_val->embval_index, ev0_i, ed0_i,
-          p_buf, flavor | EMBED_VALUES, indent + own_tag, 0);
+        emb_val->embval_array->encode_element(emb_val->embval_index, UNIVERSAL_CHARSTRING_xer_,
+          ev0_i, ed0_i, p_buf, flavor | EMBED_VALUES, indent + own_tag, 0);
         ++emb_val->embval_index;
       }
 
@@ -2079,7 +2080,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr
       const Erroneous_descriptor_t* emb_descr =
         p_err_descr->next_field_emb_descr (i, edescr_idx);
 
-      encode_element(i, err_vals, emb_descr, p_buf, sub_flavor, indent+own_tag, emb_val);
+      encode_element(i, *p_td.oftype_descr, err_vals, emb_descr, p_buf, sub_flavor, indent+own_tag, emb_val);
 
       // omit_after value -1 becomes "very big"
       if ((unsigned int)i >= (unsigned int)p_err_descr->omit_after) break;
@@ -2146,7 +2147,7 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
       pos += strlen(str) + 1;
       // Construct a new XML Reader with the current token.
       TTCN_Buffer buf2;
-      const XERdescriptor_t& sub_xer = *get_elem_descr()->xer;
+      const XERdescriptor_t& sub_xer = *p_td.oftype_descr;
       buf2.put_c('<');
       write_ns_prefix(sub_xer, buf2);
 
@@ -2233,7 +2234,7 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
              * belong to the embedded type, the record-of has already ended. */
             if (!own_tag && !can_start_v(
               (const char*)reader.LocalName(), (const char*)reader.NamespaceUri(),
-              *get_elem_descr()->xer, flavor | UNTAGGED))
+              p_td, flavor | UNTAGGED))
             {
               for (; success == 1 && reader.Depth() > depth; success = reader.Read()) ;
               // We should now be back at the same depth as we started.
@@ -2241,7 +2242,7 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
             }
             ec_1.set_msg("%d: ", get_nof_elements());
             /* The call to the non-const get_at() creates the element */
-            get_at(get_nof_elements())->XER_decode(*get_elem_descr()->xer, reader, flavor, emb_val);
+            get_at(get_nof_elements())->XER_decode(*p_td.oftype_descr, reader, flavor, emb_val);
             if (0 != emb_val && !own_tag && get_nof_elements() > 1) {
               ++emb_val->embval_index;
             }
@@ -4690,8 +4691,8 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
           ev0_0 = ed0->next_field_err_values(0, embed_values_val_idx);
           ed0_0 = ed0->next_field_emb_descr (0, embed_values_descr_idx);
         }
-        sub_len += embed_values->encode_element(0, ev0_0, ed0_0,
-          p_buf, flavor | EMBED_VALUES, indent+!omit_tag, 0);
+        sub_len += embed_values->encode_element(0, UNIVERSAL_CHARSTRING_xer_,
+          ev0_0, ed0_0, p_buf, flavor | EMBED_VALUES, indent+!omit_tag, 0);
       }
     }
 
@@ -4844,8 +4845,8 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
             ev0_i = ed0->next_field_err_values(emb_val->embval_index, emb_val->embval_err_val_idx);
             ed0_i = ed0->next_field_emb_descr (emb_val->embval_index, emb_val->embval_err_descr_idx);
           }
-          embed_values->encode_element(emb_val->embval_index, ev0_i, ed0_i,
-            p_buf, flavor | EMBED_VALUES, indent + !omit_tag, 0);
+          embed_values->encode_element(emb_val->embval_index, UNIVERSAL_CHARSTRING_xer_,
+            ev0_i, ed0_i, p_buf, flavor | EMBED_VALUES, indent + !omit_tag, 0);
           ++emb_val->embval_index;
         }
       } //for
diff --git a/etc/xsd/TXD.xsd b/etc/xsd/TXD.xsd
deleted file mode 100644 (file)
index e2730e9..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-XML Schema for JunitLogger plugin
-
- 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
--->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
-        targetNamespace="http://schemas.ericsson.com/TXD"
-        xmlns:txd=      "http://schemas.ericsson.com/TXD"
-        elementFormDefault="qualified">
-
-  <xs:import schemaLocation="TPD.xsd"/>
-
-  <xs:element name="Titan_Execution_Descriptor" type="txd:TXD_Type"/>
-
-  <xs:complexType name="TXD_Type">
-      <xs:sequence>
-        <xs:choice>
-          <xs:annotation>
-            <xs:documentation>
-              A choice between describing how to build the project &lt;build&gt;
-              or providing the location of a pre-built &lt;executable&gt;
-              These two are mutually exclusive.
-            </xs:documentation>
-          </xs:annotation>
-
-          <xs:element name="Build">
-            <xs:annotation>
-              <xs:documentation>
-                Describes the way to build the product from source,
-                using TPDs.
-              </xs:documentation>
-            </xs:annotation>
-            <xs:complexType>
-              <xs:sequence>
-                <xs:element name="Projects">
-                  <xs:complexType>
-                    <xs:sequence>
-                      <xs:element name="Project" minOccurs="1" maxOccurs="unbounded" type="txd:ProjectType" />
-                      <!-- see below -->
-                    </xs:sequence>
-                  </xs:complexType>
-                </xs:element>
-                <xs:element name="MasterConfiguration" type="ConfigurationType" minOccurs="0">
-                  <xs:annotation>
-                    <xs:documentation>
-                      Override configuration settings in TPDs
-                    </xs:documentation>
-                  </xs:annotation>
-                </xs:element>
-              </xs:sequence>
-            </xs:complexType>
-          </xs:element>
-
-          <xs:element name="Executable">
-            <xs:annotation>
-              <xs:documentation>
-                Specifies the location of an already built executable
-              </xs:documentation>
-            </xs:annotation>
-            <xs:complexType>
-              <xs:attribute name="location" />
-            </xs:complexType>
-          </xs:element>
-        </xs:choice>
-
-        <!--
-        Runners
-        -->
-        <xs:element name="Run" minOccurs="0" maxOccurs="1">
-          <xs:annotation>
-            <xs:documentation>
-              Describes how to run the test.
-              There can be at most one "Run" which may contain various runners
-            </xs:documentation>
-          </xs:annotation>
-          <xs:complexType>
-            <xs:choice minOccurs="1" maxOccurs="unbounded">
-              <xs:element name="SingleModeRun">
-                <xs:complexType>
-                  <xs:sequence>
-                    <xs:element name="WorkingDirectory"  type="xs:string"/>
-                    <xs:element name="ETS_Name"          type="xs:string" minOccurs="0"/>
-                    <!-- ETS_Name may be deduced from the build information -->
-                    <xs:element name="ConfigurationFile" type="xs:string"/>
-                  </xs:sequence>
-                </xs:complexType>
-              </xs:element>
-              <xs:element name="ParallelRun">
-                <xs:complexType>
-                  <xs:sequence>
-                    <xs:element name="WorkingDirectory"  type="xs:string"/>
-                    <xs:element name="ETS_Name"          type="xs:string" minOccurs="0"/>
-                    <!-- ETS_Name may be deduced from the build information -->
-                    <xs:element name="ConfigurationFile" type="xs:string"/>
-                    <xs:element name="HostControllers" minOccurs="0" maxOccurs="1">
-                      <xs:complexType>
-                        <xs:sequence>
-                          <xs:element name="HostController" minOccurs="1" maxOccurs="unbounded">
-                            <!--
-                            Empty <HostControllers> with no <HostController> is not allowed.
-                            Omit the entire <HostControllers> instead.
-                            -->
-                            <xs:complexType>
-                              <xs:sequence>
-                                <xs:element type="xs:string" name="Name"/>
-                                <xs:element type="xs:string" name="HostId"     minOccurs="0"/>
-                                <xs:element type="xs:string" name="WorkingDirectory" minOccurs="0"/>
-                                <xs:element type="xs:string" name="Executable" minOccurs="0"/>
-                                <!--
-                                HostId, WorkingDir and Executable may be omitted, if not referenced by <Command>
-                                -->
-                                <xs:element type="xs:string" name="Command"/>
-                              </xs:sequence>
-                            </xs:complexType>
-                          </xs:element>
-                        </xs:sequence>
-                      </xs:complexType>
-                    </xs:element>
-                  </xs:sequence>
-                </xs:complexType>
-              </xs:element>
-              <xs:element name="CustomRun" type="xs:string">
-                <!-- TODO: is a simple string enough? -->
-              </xs:element>
-            </xs:choice>
-          </xs:complexType>
-        </xs:element>
-      </xs:sequence>
-  </xs:complexType>
-
-  <xs:complexType name="ProjectType">
-    <xs:annotation>
-      <xs:documentation>
-        Describes a referenced project
-      </xs:documentation>
-    </xs:annotation>
-    <xs:sequence>
-      <xs:element name="Configurations">
-        <xs:complexType>
-          <xs:sequence>
-            <xs:element name="Configuration" minOccurs="0" maxOccurs="unbounded" >
-              <xs:complexType>
-                <!-- Optional: put in a <sequence> if sub-elements are needed -->
-                <xs:attribute name="name" use="required" />
-              </xs:complexType>              
-            </xs:element>
-          </xs:sequence>
-        </xs:complexType>
-      </xs:element>
-    </xs:sequence>
-    <xs:attribute name="name" use="optional">
-      <xs:annotation>
-        <xs:documentation>
-          Optional name of the project. Can be used as reference in the TXD itself.
-          The TPD is identified by the "path" attribute, below.
-        </xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="path" use="required">
-      <xs:annotation>
-        <xs:documentation>
-          This is the filename of the TPD file. Paths are relative to the TXD
-          itself, or absolute.
-        </xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-</xs:schema>
index 4510b010ee8008b6c1977837b4072b7c298cc123..49b8a3e8de4ffad153be9c32d782950c15c9f640 100644 (file)
@@ -9,9 +9,9 @@
 :lang eng.
 .*
 :docname.Test Description
-:docno.8/152 91-CRL 113 200/2 Uen
-:rev.A
-:date.2012-06-27
+:docno.8/152 91-CRL 113 200/5 Uen
+:rev.C
+:date.2015-04-27
 .*
 :prep.ETH/XZR Kristof Szabados (+36 1 437 7256)
 :appr.ETH/XZ (Roland Gecse)
index 285f4e098531d561d74045dc63035b756800a76f..e3a6a6c07c516bc254eab3249bfe40cb28f49a0e 100755 (executable)
@@ -14,9 +14,9 @@
 
 .* Document header information
 :docname.Test Description
-:docno.24/152 91-CRL 113 200/4 Uen
-:rev.PA6
-:date.2014-04-01
+:docno.24/152 91-CRL 113 200/5 Uen
+:rev.C
+:date.2015-04-27
 
 :prep.ETH/RZX Norbert Bartha (ethnba)
 :appr.ETH/RZX (Csaba Koppany)
index 6a80b4896ec3dcb0b8fd6e1684e157629645e6aa..e22683fda632cfeb91e19272211d0224131f2b5a 100644 (file)
@@ -15,8 +15,8 @@
 .* Document header information
 :docname.Test Description
 :docno.xx/152 91-CRL 113 200/3 Uen
-:rev.A
-:date.2013-13-14
+:rev.C
+:date.2015-04-27
 
 :prep.ETH/XZR Jeno Balasko
 :appr.ETH/XZR (Elemer Lelik)
index 6a48c1af804c7d57e4e6aade909e8ae10a1bb07c..19926d924da268278f0520f2f44e7a793ce927f2 100644 (file)
@@ -14,9 +14,9 @@
 
 .* Document header information
 :docname.Test Description
-:docno.xx/152 91-CRL 113 200/2 Uen
-:rev.A
-:date.2013-01-16
+:docno.xx/152 91-CRL 113 200/5 Uen
+:rev.C
+:date.2015-04-27
 
 :prep.ETH/RZX Jeno Balasko (ethbaat)
 :appr.ETH/RZX (Gyula Koos)
index 02c2cdf9d63e9caf8500fb5048ef9eb60b69db73..fd145b621d0e8fb9da0c73ac919aea3246194538 100644 (file)
@@ -9,9 +9,9 @@
 :lang eng.
 .*
 :docname.Test Description
-:docno.7/152 91-CRL 113 200/2 Uen
+:docno.7/152 91-CRL 113 200/5 Uen
 :rev.A
-:date.2013-02-01
+:date.2015-04-27
 .*
 :prep.ETH/XZR Jeno Balasko (+36 1 437 7760)
 :appr.ETH/XZ (Gyula Koos)
index 4e33f50bae8d3d3e7a25e867fc065b8f21bb5b6a..d3dedc04fdcc264e568d383621c17639db9e570a 100644 (file)
@@ -14,9 +14,9 @@
 
 .* Document header information
 :docname.Test Description
-:docno. Uen
-:rev.PA1
-:date.2005.02.03.
+:docno. 12/15291-CRL200/5 Uen
+:rev.A
+:date.2015-04-27
 
 :prep.ETH/RZD Endre Szalai (+36 1 437 7796)
 :appr.ETH/RZ (Zsolt Szendrei)
index 834ce8d5ccbf1507f7250424634bc874130b24ba..f4436d6ac143bdee568a17772b2828b1fdc50792 100644 (file)
@@ -14,9 +14,9 @@
 
 .* Document header information
 :docname.Test Description
-:docno.
+:docno.20/15291-CRL200/5 Uen
 :rev.
-:date.2005.01.31.
+:date.2015-04-27
 
 :prep.ETH/RZD Endre Szalai (+36 1 437 7796)
 :appr.
@@ -33,7 +33,7 @@
 :xmp tab=2.
 REV   DATE         PREPARED   CHANGE
 __________________________________________________
--     2005-01-31   ETHESI     New document for TITAN R6
+-     2005-01-31   ETHESI     New document for TITAN R1.6
 :exmp.
 .*---------------------------------------------------------------------*
 :h2.Purpose
index 89dea16945df83485b54b46df28c793ab5ff4eef..3d0552ce95438829bf1b0a76ffce6cca3bbeaca5 100644 (file)
 
 .* Document header information
 :docname.Test Description
-:docno.22/152 91-CRL 113 200/3 Uen
+:docno.22/152 91-CRL 113 200/5 Uen
 :rev.A
-:date.2013-01-17
+:date.2015-04-27
 
-:prep.ETH/XZR Krisztian Pandi
+:prep.ETH/XZ Jeno Balasko
 :appr.ETH/XZ (Gyula Koos)
 :checked.ETHGRY
 
index ce629bd05915008f7fc533eb40f45fde71f9e053..03373a9c41385950c84c77d0371fe77420d6dfc5 100644 (file)
@@ -9,9 +9,9 @@ text.
 :lang eng.
 .*
 :docname.Test Description
-:docno.
-:rev.PA1
-:date.2011.11.21
+:docno. xy/152 91-CRL 113 200/5 Uen
+:rev.A
+:date.2015-04-27
 .*
 :prep.ETH/XZR ETHBAAT
 :subresp.ETHBAAT
index 6c66e1973d90cf1fcf9a5ed118cf2ff8d0151c37..fde96ede26c23b9fabb8d92bb2229514734ade53 100644 (file)
@@ -8,8 +8,8 @@
 .* Document header information
 :docname.Test Description
 :docno.xx/152 91-CRL 113 200 Uen
-:rev.PA1
-:date.2011-11-16
+:rev.A
+:date.2015-04-27
 
 :prep.ETH/RZX Jeno Balasko (ethbaat)
 :appr.ETH/RZX (Roland Gecse)
index 36678584a8aaba7440509832829d0182cdad269f..3011ec228af79f9263f7dffd03ec1fb712eda28e 100644 (file)
@@ -9,9 +9,9 @@ text.
 :lang eng.
 .*
 :docname.Test Description
-:docno.
+:docno.xz/152 91-CRL 113 200 Uen
 :rev.PA3
-:date.2013-01-16
+:date.2015-04-27
 .*
 :prep.ETH/XZR ETHBAAT
 :subresp.ETHBAAT
index 37e1db1328b96c9acd6a8208ae59fe5556dddf36..f4c5b926da42ae5a6af71901f4963aeab490126b 100644 (file)
 
 .* Document header information
 :docname.Test Description
-:docno.12/152 91-CRL 113 200/3 Uen
+:docno.12/152 91-CRL 113 200/5 Uen
 :rev.A
-:date.2013-01-17
+:date.2015-04-27
 
-:prep.ETH/XZR Krisztian Pandi
+:prep.ETH/XZR Jeno Balasko
 :appr.ETH/XZ (Gyula Koos)
 :checked.ETHGRY
 
index e769c1841f9fde9925dae9343d84c06f6f40e94a..5ced083cd47f735959bdcdb80bba6a195d8996d3 100644 (file)
 
 .* Document header information
 :docname.Test Description
-:docno.14/152 91-CRL 113 200/3 Uen
+:docno.14/152 91-CRL 113 200/5 Uen
 :rev.A
-:date.2013-01-17
+:date.2015-04-27
 
-:prep.ETH/XZR Krisztian Pandi
-:appr.ETH/XZ (Gyula Koos)
+:prep.ETH/XZ Jeno Balasko
+:appr.ETH/XZ (Elemer Lelik)
 :checked.ETHGRY
 
 :title.Test description of the TTCN-3 Semantic Analyzer: Scope Rules
index 46eef824d8e84c2dc53cab5f99bddf62a05c9b9e..bde23e488082b780240ae669337c3f0cb842cd6f 100644 (file)
@@ -16,9 +16,9 @@
 :docname.Test Description
 :docno.15/152 91-CRL 113 200/3 Uen
 :rev.A
-:date.2013-01-17
+:date.2015-04-27
 
-:prep.ETH/XZR Krisztian Pandi
+:prep.ETH/XZ Jeno Balasko
 :appr.ETH/XZ (Gyula Koos)
 :checked.ETHGRY
 
index 4db626a156f9c42d3eaa5be3e8d7029621edab92..86e414e2443f138ade7805bf32fe82c522d71c33 100644 (file)
 
 .* Document header information
 :docname.Test Description
-:docno.16/152 91-CRL 113 200/3 Uen
+:docno.16/152 91-CRL 113 200/5 Uen
 :rev.A
-:date.2013-01-17
+:date.2015-04-27
 
-:prep.ETH/XZR Krisztian        Pandi
+:prep.ETH/XZ Jeno Balasko
 :appr.ETH/XZ (Gyula Koos)
 :checked.ETHGRY
 
index c6402d6c9e72f5fe23b205fd710ea6a1a678b48b..b86039917c06ad1a861cbc48def61d20f046d175 100644 (file)
@@ -16,9 +16,9 @@
 :docname.Test Description
 :docno.17/152 91-CRL 113 200/3 Uen
 :rev.A
-:date.2013-01-17
+:date.2015-04-27
 
-:prep.ETH/XZR Krisztian Pandi
+:prep.ETH/XZ Jeno Balasko
 :appr.ETH/XZ (Gyula Koos)
 :checked.EKRISZA
 
@@ -16537,7 +16537,7 @@ ConsoleMask := WARNING | ERROR | TESTCASE | STATISTICS
 ModuleA
 <END_MODULE>
 <RESULT IF_PASS COUNT 1>
-(?im)Dynamic test case error: Accessing an element in an unbound value of type @ModuleA.t_recof.
+(?im)Dynamic test case error: Accessing an element in an unbound value of type @PreGenRecordOf.PREGEN_RECORD_OF_INTEGER.
 <END_RESULT>
 <END_TC>
 :exmp.
@@ -16577,7 +16577,7 @@ ConsoleMask := WARNING | ERROR | TESTCASE | STATISTICS
 ModuleA
 <END_MODULE>
 <RESULT IF_PASS COUNT 1>
-(?im)Dynamic test case error: Index overflow in a value of type @ModuleA.t_recof: The index is 10, but the value has only 2 elements.
+(?im)Dynamic test case error: Index overflow in a value of type @PreGenRecordOf.PREGEN_RECORD_OF_INTEGER: The index is 10, but the value has only 2 elements.
 <END_RESULT>
 <END_TC>
 :exmp.
@@ -16617,7 +16617,7 @@ ConsoleMask := WARNING | ERROR | TESTCASE | STATISTICS
 ModuleA
 <END_MODULE>
 <RESULT IF_PASS COUNT 1>
-(?im)Dynamic test case error: Accessing an element in an unbound value of type @ModuleA.t_setof.
+(?im)Dynamic test case error: Accessing an element in an unbound value of type @PreGenRecordOf.PREGEN_SET_OF_INTEGER.
 <END_RESULT>
 <END_TC>
 :exmp.
@@ -16657,7 +16657,7 @@ ConsoleMask := WARNING | ERROR | TESTCASE | STATISTICS
 ModuleA
 <END_MODULE>
 <RESULT IF_PASS COUNT 1>
-(?im)Dynamic test case error: Index overflow in a value of type @ModuleA.t_setof: The index is 10, but the value has only 2 elements.
+(?im)Dynamic test case error: Index overflow in a value of type @PreGenRecordOf.PREGEN_SET_OF_INTEGER: The index is 10, but the value has only 2 elements.
 <END_RESULT>
 <END_TC>
 :exmp.
index 99987ce00d4040567eb82085e242c04af3fee3af..10878ccfc78b3d1df56c8361c70a9333798afbf0 100644 (file)
@@ -14,9 +14,9 @@
 
 .* Document header information
 :docname.Test Description
-:docno.18/152 91-CRL 113 200/3 Uen
+:docno.18/152 91-CRL 113 200/5 Uen
 :rev.A
-:date.2013-01-17
+:date.2015-04-27
 
 :prep.ETH/XZR Krisztian Pandi
 :appr.ETH/XZ (Gyula Koos)
index f136affdd2f4fae2e741d63220f6e237282eb2d4..9076fc2cabc09dc651d55ca367118ea77d63f36d 100644 (file)
 
 .* Document header information
 :docname.Test Description
-:docno.20/152 91-CRL 113 200/3 Uen
+:docno.xx/152 91-CRL 113 200/5 Uen
 :rev.A
-:date.2013-01-17
+:date.2015-04-27
 
-:prep.ETH/XZR Krisztian Pandi
+:prep.ETH/XZ Jeno Balasko
 :appr.ETH/XZ (Gyula Koos)
 :checked.ETHGRY
 
@@ -41,9 +41,10 @@ D     2007-06-08   EJNOSZA    Updates for TITAN R7B (expected error messages for
 E     2008-10-01   EKRISZA    Updates for TITAN R7E
 F     2010-01-18   EKRISZA    Updated for TITAN R8C
 K     2011-10-10   EKRISZA    Updated for TITAN R8H
-A     2011-12-12   EKRISZA     Updated for release
-A     2012-06-27   EFERKOV     Updated for release
-A     2013-01-17   EKRIPND     Updated for release
+A     2011-12-12   EKRISZA    Updated for release
+A     2012-06-27   EFERKOV    Updated for release
+A     2013-01-17   EKRIPND    Updated for release
+A        2015-04-27   ETHBAAT    Updated for release
 :exmp.
 
 .*---------------------------------------------------------------------*
index db2b40fc7bd0f54e4018c8565317a471f89a5ac2..b1daa6a209427b4d7e5cd76082bcef1bcbbac59b 100644 (file)
 
 .* Document header information
 :docname.Test Description
-:docno.20/152 91-CRL 113 200/3 Uen
+:docno.2x/152 91-CRL 113 200/5 Uen
 :rev.A
-:date.2013-01-17
+:date.2015-04-27
 
-:prep.ETH/XZR Krisztian Pandi
+:prep.ETH/XZ Jeno Balasko
 :appr.ETH/XZ (Gyula Koos)
 :checked.ETHGRY
 
@@ -33,7 +33,7 @@
 :xmp tab=2.
 REV   DATE         PREPARED   CHANGE
 __________________________________________________
--     2005-02-19   EGBOTAT    New document for TITAN R6
+-     2005-02-19   EGBOTAT    New document for TITAN R1.6
 -     2005-06-30   ETIBHRA    Added select-case, alive, interleave tests
 -     2005-08-16   ETIBHRA    Deleted select-case, alive, interleave tests
 -     2007-12-03   ETHNBA     TCs for IsBound are added
@@ -3644,22 +3644,19 @@ testcase tc() runs on Empty
 module bad_arguments
 {
 type component empty { }
-type record of integer intlist1
-type record of integer intlist2
+type record of integer intlist
 testcase tc () runs on empty
 {
   var integer a := 0
   var charstring cs_1 := "My name is JJ"
   var bitstring bs_1 := '11'B
   var charstring cs_2 := replace("My name is JJ", -1, 2, "xx")
-  var intlist1 il1 := { 1, 2, 3 }
-  var intlist2 il2 := { 4 }
+  var intlist il1 := { 1, 2, 3 }
   cs_2 := replace("My name is JJ", 1, 2, '11'B)
   cs_2 := replace("My name is JJ", 100, 2, "x")
   cs_2 := replace("My name is JJ", a, 100, "x")
   cs_2 := replace(cs_1, 1, 2, bs_1)
   cs_2 := replace(cs_1, 1.0, 2, "xx")
-  il1 := replace(il1, 1, 1, il2)
   il1 := replace(il1, 1, 1, cs_1[10])
 }
 }
@@ -3670,11 +3667,8 @@ testcase tc () runs on empty
 <RESULT COUNT 2>
 (?is)\berror:.+?Fourth operand of operation `replace\(\)' is of type `bitstring', but a value of type `charstring' was expected here
 <END_RESULT>
-<RESULT LTRT COUNT 1>
-(?is)\berror:.+?Fourth operand of operation `replace\(\)' is of type `\@bad_arguments.intlist2', but a value of type `\@bad_arguments.intlist1' was expected here
-<END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror:.+?Fourth operand of operation `replace\(\)' is of type `charstring', but a value of type `\@bad_arguments.intlist1' was expected here
+(?is)\berror:.+?Fourth operand of operation `replace\(\)' is of type `charstring', but a value of type `\@bad_arguments.intlist' was expected here
 <END_RESULT>
 <RESULT COUNT 1>
 (?is)\berror:.+?The sum of second operand `index' \(100\) and third operand `len' \(2\) is greater than the length of the first operand \(13\)
@@ -4301,31 +4295,6 @@ control {
 <END_TC>
 :exmp.
 
-.*---------------------------------------------------------------------*
-:h3.Adhoc:: TR 935 - concatenation of incompatible list types
-.*---------------------------------------------------------------------*
-:xmp tab=0.
-<TC - TR 935 - concatenation of incompatible list types>
-<COMPILE>
-<VERDICT_LEAF PASS>
-<MODULE TTCN TR935 TR935.ttcn>
-module TR935 {
-type record of integer intlist1
-type record of integer intlist2
-control {
-  var intlist1 il1 := { 1, 2, 3 }
-  var intlist2 il2 := { 4 }
-  il1 := il1 & il2
-  // Merge this small test-case later.
-}
-}
-<END_MODULE>
-<RESULT LTRT COUNT 1>
-(?is)\berror: The operands of operation `&' should be of compatible types
-<END_RESULT>
-<END_TC>
-:exmp.
-
 .*---------------------------------------------------------------------*
 :h3.Adhoc:: Type Compatibility - Sample tests for structured types
 .*---------------------------------------------------------------------*
@@ -4376,13 +4345,13 @@ ro2 := substr(myrec1 : t_myrecof3, 0, 1)  // !OK
 <RESULT LTRT COUNT 1>
 (?is)\berror: Type mismatch: a value of type `\@Compat1.myrecof1' was expected instead of `integer\[4\]'
 <END_RESULT>
-<RESULT LTRT COUNT 3>
+<RESULT LTRT COUNT 2>
 (?is)\berror: The operands of operation `==' should be of compatible types
 <END_RESULT>
 <RESULT FTRT COUNT 1>
 (?is)\berror: Type mismatch: `\@Compat1.myrecof1' and `integer\[4\]' are not compatible: Incompatible record of/SEQUENCE OF subtypes
 <END_RESULT>
-<RESULT FTRT COUNT 1>
+<RESULT COUNT 1>
 (?is)\berror: Type mismatch: `@Compat1.myrecof1' and `@Compat1.myrecof3' are not compatible: Incompatible record of/SEQUENCE OF subtypes
 <END_RESULT>
 <RESULT LTRT COUNT 1>
@@ -6116,13 +6085,7 @@ module module1
 <RESULT COUNT 1>
 (?is)\berror: \{  \} is not a valid value for type `\@module1.myro1' which has subtype length\(1\)
 <END_RESULT>
-<RESULT LTRT COUNT 2>
-(?is)\berror: The operands of operation `==' should be of compatible types
-<END_RESULT>
-<RESULT LTRT COUNT 1>
-(?is)\berror: Type mismatch: a value or template of type `\@module1.myro1' was expected instead of `\@module1.myro2'
-<END_RESULT>
-<RESULT FTRT COUNT 3>
+<RESULT COUNT 3>
 (?is)\berror: Type mismatch: `\@module1.myro1' and `\@module1.myro2' are not compatible: Incompatible record of/SEQUENCE OF subtypes
 <END_RESULT>
 <RESULT COUNT 1>
@@ -6202,13 +6165,7 @@ module module1
 <RESULT COUNT 1>
 (?is)\berror: \{  \} is not a valid value for type `\@module1.myso1' which has subtype length\(1\)
 <END_RESULT>
-<RESULT LTRT COUNT 2>
-(?is)\berror: The operands of operation `==' should be of compatible types
-<END_RESULT>
-<RESULT LTRT COUNT 1>
-(?is)\berror: Type mismatch: a value or template of type `\@module1.myso1' was expected instead of `\@module1.myso2'
-<END_RESULT>
-<RESULT FTRT COUNT 3>
+<RESULT COUNT 3>
 (?is)\berror: Type mismatch: `\@module1.myso1' and `\@module1.myso2' are not compatible: Incompatible set of/SET OF subtypes
 <END_RESULT>
 <RESULT COUNT 20>
@@ -8323,10 +8280,10 @@ Temp
 :exmp.
 
 .*---------------------------------------------------------------------*
-:h3.Adhoc:: modulepar invalid simple type: component, port, default
+:h3.Adhoc:: modulepar invalid simple type: port
 .*---------------------------------------------------------------------*
 :xmp tab=0.
-<TC - Adhoc::modulepar invalid type - component, port, default>
+<TC - Adhoc::modulepar invalid type - port>
 <COMPILE>
 <VERDICT_LEAF FAIL>
 <MODULE TTCN Temp Temp.ttcn>
@@ -8343,76 +8300,7 @@ module Temp {
   type default default_DT;
 }
 <END_MODULE>
-<RESULT IF_FAIL COUNT 3>
-(?is)\berror:
-<END_RESULT>
-<RESULT IF_FAIL POSITIVE>
-(?im)\bnotify\b.+?\bcode\b.+?\bnot\b.+?\bgenerated\b
-<END_RESULT><END_TC>
-:exmp.
-
-.*------------------------------------------------------------------------------------*
-:h3.Adhoc:: modulepar invalid compound type: record, set with component, default
-.*------------------------------------------------------------------------------------*
-:xmp tab=0.
-<TC - Adhoc::modulepar invalid type - compound type>
-<COMPILE>
-<VERDICT_LEAF FAIL>
-<MODULE TTCN Temp Temp.ttcn>
-module Temp {
-  modulepar invalidRec tsp_Rec;
-  modulepar invalidSet tsp_Set;
-  modulepar invalidUnion tsp_Union;
-  type record invalidRec {
-    integer varI1,
-    default_DT varDT,
-    charstring varStr
-  }
-  type set invalidSet {
-    integer varI2,
-    comp_CT varCT1,
-    charstring varStr
-  }
-  type union invalidUnion {
-    integer varI3,
-    comp_CT varCT2
-  }
-  type default default_DT;
-  type component comp_CT {
-       var integer v_int := 0;
-  }
-}
-<END_MODULE>
-<RESULT IF_FAIL COUNT 3>
-(?is)\berror:
-<END_RESULT>
-<RESULT IF_FAIL POSITIVE>
-(?im)\bnotify\b.+?\bcode\b.+?\bnot\b.+?\bgenerated\b
-<END_RESULT><END_TC>
-:exmp.
-
-.*------------------------------------------------------------------------------------*
-:h3.Adhoc:: modulepar invalid list: record of, set of and array with component, default
-.*------------------------------------------------------------------------------------*
-:xmp tab=0.
-<TC - Adhoc::modulepar invalid list - record of, set of and array with component, default>
-<COMPILE>
-<VERDICT_LEAF FAIL>
-<MODULE TTCN Temp Temp.ttcn>
-module Temp {
-  modulepar ListRec tsp_ListRec;
-  modulepar ListSet tsp_listSet;
-  modulepar compArrayType tsp_compArray;
-  type record of comp_CT ListRec;
-  type set of default_DT ListSet;
-  type comp_CT compArrayType[3];
-  type default default_DT;
-  type component comp_CT {
-       var integer v_int := 0;
-  }
-}
-<END_MODULE>
-<RESULT IF_FAIL COUNT 3>
+<RESULT IF_FAIL COUNT 1>
 (?is)\berror:
 <END_RESULT>
 <RESULT IF_FAIL POSITIVE>
@@ -8448,7 +8336,7 @@ module Temp {
 <RESULT IF_FAIL COUNT 1>
 (?im)\bcircular\b.+?\breference\b
 <END_RESULT>
-<RESULT IF_FAIL COUNT 2>
+<RESULT IF_FAIL COUNT 1>
 (?is)\berror:
 <END_RESULT>
 <RESULT IF_FAIL POSITIVE>
index fd201d4c0c4176e910755edc2b2ac3b151acabc8..9b834137d9b5dccad4840fcc0b171d3b157c71b6 100644 (file)
@@ -9,9 +9,9 @@
 :lang eng.
 .*
 :docname.Test Description
-:docno.21/152 91-CRL 113 200/2 Uen
+:docno.21/152 91-CRL 113 200/5 Uen
 :rev.A
-:date.2012-06-27
+:date.2015-04-27
 .*
 :prep.ETH/XZR Ferenc Kovacs (+36 1 439 5511)
 :appr.ETH/XZ (Roland Gecse)
index 73c46e7f9a523b72012f225dbfc2c609642ad034..6c2d49bfba7ea3a508906835d40b1b8ee0cec78f 100755 (executable)
@@ -78,7 +78,7 @@ proc _compiler {message} {
 
 }
 
-proc _executor {message coverage_args rt_2} {
+proc _executor {message coverage_args} {
        global sh_id
 
        if {![file exists Makefile]} {
@@ -162,12 +162,11 @@ set tc_counter 0
 set err_counter 0
 set errpostfix "_error"
 set coverage_args ""
-set rt_2 ""
 set start_date [exec date +"%H:%M:%S"]
 
 if {[lindex $argv 0] == "-coverage"} {set argv [lrange $argv 1 end]; set coverage_args "COVERAGE=1"; puts "Coverage mode enabled!"}
 # RT2 comes after coverage
-if {[lindex $argv 0] == "-rt2"}      {set argv [lrange $argv 1 end]; set rt_2 "RT2=2"; puts "Function-test runtime enabled!"}
+if {[lindex $argv 0] == "-rt2"}      {set argv [lrange $argv 1 end]; set env(RT2) yes; puts "Function-test runtime enabled!"}
 
 set errorfilename $argv$errpostfix
 
@@ -249,9 +248,9 @@ while {$i <= $tc_counter} {
        }
 
        if {([string length $result_mess] > 3)&&($tc_state != "execute")&&($tc_state != "pure_execute")} {_compiler $result_mess}
-       if {([string length $Line] > 3)&&($tc_state == "execute")} {_executor $result_mess $coverage_args $rt_2}
+       if {([string length $Line] > 3)&&($tc_state == "execute")} {_executor $result_mess $coverage_args}
        if {([string length $Line] > 3)&&($tc_state == "pure_execute")} {
-               _executor $result_mess $coverage_args $rt_2
+               _executor $result_mess $coverage_args
        }
 
        incr i
index 098c99a1e0d0ffe32e46fc3cc666c4b780db49b5..e110cb134264b34b6a7271af0b5949855d5e9a83 100644 (file)
@@ -9,12 +9,12 @@
 :lang eng.
 .*
 :docname.Test Description
-:docno.7/152 91-CRL 113 200/4 Uen
+:docno.9/152 91-CRL 113 200/5 Uen
 :rev.A
-:date.2014-04-29
+:date.2015-04-27
 .*
 :prep.ETH/XZ Botond Baranyi
-:appr.ETH/XZ (Jeno Balasko)
+:appr.ETH/XZ (Elemer Lelik)
 :checked.ETHBAAT
 .*
 :title.Test description - XER coder
@@ -828,7 +828,7 @@ control {
 
 <RESULT>
 
-Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': While checking anyElement: XML namespace "http://www.somewhere.com" is not in the allowed namespace list.
+Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': Index 0: While checking anyElement: XML namespace "http://www.somewhere.com" is not in the allowed namespace list.
 
 <END_TC>  
   
@@ -875,7 +875,7 @@ control {
 
 <RESULT>
 
-Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': While checking anyElement: XML namespace "http://www.somewhereelse.com" is not in the allowed namespace list.
+Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': Index 0: While checking anyElement: XML namespace "http://www.somewhereelse.com" is not in the allowed namespace list.
 
 <END_TC>  
   
@@ -924,7 +924,7 @@ control {
 
 <RESULT>
 
-Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': While checking anyElement: XML namespace "http://www.someotherplace.com" is not in the allowed namespace list.
+Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': Index 0: While checking anyElement: XML namespace "http://www.someotherplace.com" is not in the allowed namespace list.
 
 <END_TC>  
   
@@ -1124,7 +1124,7 @@ control {
 
 <RESULT>
 
-Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': While checking anyElement: The unqualified XML namespace is in the excluded namespace list.
+Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': Index 0: While checking anyElement: The unqualified XML namespace is in the excluded namespace list.
 
 <END_TC>  
   
@@ -1171,7 +1171,7 @@ control {
 
 <RESULT>
 
-Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': While checking anyElement: XML namespace "http://www.somewhere.com" is in the excluded namespace list.
+Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': Index 0: While checking anyElement: XML namespace "http://www.somewhere.com" is in the excluded namespace list.
 
 <END_TC>  
   
@@ -1218,7 +1218,7 @@ control {
 
 <RESULT>
 
-Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': While checking anyElement: XML namespace "http://www.somewhereelse.com" is in the excluded namespace list.
+Dynamic test case error: While XER-decoding type '@Temp.any_elem_rec_of': Index 0: While checking anyElement: XML namespace "http://www.somewhereelse.com" is in the excluded namespace list.
 
 <END_TC>  
   
index 458f786c0c7725b5e73773bf4e43fdc44ffa0591..860c9b06e00f2cb20da5ba5a7f7624facfee12c2 100644 (file)
Binary files a/function_test/doc/TTCN3_Executor_TestReport.doc and b/function_test/doc/TTCN3_Executor_TestReport.doc differ
index 3c4191bd744ef62901d50b2be148c6dd70c9875d..55bbae00d9435db9f64cdfdb10f059cab39ef54a 100644 (file)
@@ -26,17 +26,17 @@ exception execute extension external fail false float float2int        \
 float2str for from function friend get_stringencoding getcall getreply getverdict goto group \
 hex2bit hex2int hex2oct hex2str hexstring if ifpresent import in       \
 inconc infinity inout int2bit int2char int2float int2hex int2oct       \
-int2str int2unichar integer interleave ischosen ispresent isvalue kill killed \
+int2str int2unichar integer interleave isbound ischosen ispresent isvalue kill killed \
 label language length lengthof log map match message mixed mod         \
 modifies module modulepar mtc noblock none not not4b nowait null objid \
 oct2bit oct2char oct2hex oct2int oct2str oct2unichar octetstring of omit on        \
 operators optional or or4b out override param pass pattern permutation \
 port public private procedure raise read receive record recursive regexp rem remove_bom repeat \
-reply return rnd running runs select self send sender set setverdict   \
+replace reply return rnd running runs select self send sender set setverdict   \
 signature sizeof start stop str2bit str2float str2hex \
-str2int str2oct subset substr superset system template testcase        \
-timeout timer to trigger true type unichar2int unichar2oct union universal unmap   \
-value valueof var variant verdicttype while with xor xor4b))
+str2int str2oct subset substr superset system template testcase testcasename \
+timeout timer to trigger true type unichar2char unichar2int unichar2oct union universal unmap   \
+value valueof var variant verdicttype while with xor xor4b profiler))
 
 IMAGE_FILES := $(addprefix images/, $(addsuffix .jpg, ao left right up)) images/titan_transparent.gif
 
index 4768cfbe86bed409cc2974aff83192bea3d53e46..944626b78fe89e698c99f373ccfced8e99afe831 100644 (file)
@@ -23,7 +23,7 @@
     <td><a href="../titan_main.html" alt="contents"><img border="0" src="../images/ao.jpg" width="53" height="40"></a></td>
     <td><a href="../titan_index.html" alt="index"><img border="0" src="../images/up.jpg" width="53" height="40"></a></td>
     <td><a href="omit.html" alt="previous"><img border="0" src="../images/left.jpg" width="53" height="40"></a></td>
-    <td><a href="optional.html" alt="next"><img border="0" src="../images/right.jpg" width="53" height="40"></a></td>
+    <td><a href="operators.html" alt="next"><img border="0" src="../images/right.jpg" width="53" height="40"></a></td>
   </tr>
 </table>
 <p><br clear="all">
index e08e10e289164f02134c581fd6d196d71264050a..66c7482f4e88bbb3ed0df1905290197f43082053 100644 (file)
@@ -22,8 +22,8 @@
   <tr>
     <td><a href="../titan_main.html" alt="contents"><img border="0" src="../images/ao.jpg" width="53" height="40"></a></td>
     <td><a href="../titan_index.html" alt="index"><img border="0" src="../images/up.jpg" width="53" height="40"></a></td>
-    <td><a href="altstep.html" alt="previous"><img border="0" src="../images/left.jpg" width="53" height="40"></a></td>
-    <td><a href="and4b.html" alt="next"><img border="0" src="../images/right.jpg" width="53" height="40"></a></td>
+    <td><a href="on.html" alt="previous"><img border="0" src="../images/left.jpg" width="53" height="40"></a></td>
+    <td><a href="optional.html" alt="next"><img border="0" src="../images/right.jpg" width="53" height="40"></a></td>
   </tr>
 </table>
 <p><br clear="all">
index 41ed700c0ac8d6ff63c4689f5d22d3badca74e21..22c315789d321c1461f26e9a5ed2180160337dde 100644 (file)
@@ -22,7 +22,7 @@
   <tr>
     <td><a href="../titan_main.html" alt="contents"><img border="0" src="../images/ao.jpg" width="53" height="40"></a></td>
     <td><a href="../titan_index.html" alt="index"><img border="0" src="../images/up.jpg" width="53" height="40"></a></td>
-    <td><a href="on.html" alt="previous"><img border="0" src="../images/left.jpg" width="53" height="40"></a></td>
+    <td><a href="operators.html" alt="previous"><img border="0" src="../images/left.jpg" width="53" height="40"></a></td>
     <td><a href="or.html" alt="next"><img border="0" src="../images/right.jpg" width="53" height="40"></a></td>
   </tr>
 </table>
index 9c773f922f83881ab22ee910662f85ef41439b6b..11a0b8153fb6dd456ace73891193d90ba296ec5d 100644 (file)
@@ -23,7 +23,7 @@
     <td><a href="../titan_main.html" alt="contents"><img border="0" src="../images/ao.jpg" width="53" height="40"></a></td>
     <td><a href="../titan_index.html" alt="index"><img border="0" src="../images/up.jpg" width="53" height="40"></a></td>
     <td><a href="private.html" alt="previous"><img border="0" src="../images/left.jpg" width="53" height="40"></a></td>
-    <td><a href="public.html" alt="next"><img border="0" src="../images/right.jpg" width="53" height="40"></a></td>
+    <td><a href="profiler.html" alt="next"><img border="0" src="../images/right.jpg" width="53" height="40"></a></td>
   </tr>
 </table>
 <p><br clear="all">
diff --git a/help/info/profiler.html b/help/info/profiler.html
new file mode 100644 (file)
index 0000000..1f5c2bf
--- /dev/null
@@ -0,0 +1,134 @@
+<!--
+ 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
+ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta http-equiv="Content-Language" content="en-us">
+<title>profiler</title>
+</head>
+<body bgcolor="#DAD3C5" vlink="#0094D2" link="#003258">
+<table align="left" border="0" cellspacing="0" cellpadding="0" valign=top>
+  <tr>
+    <td width=105 height=40><a href="https://projects.eclipse.org/projects/tools.titan"><img src="../images/titan_transparent.gif" border=0 width=105 height=40 align="left" alt="Titan"></a></td>
+  </tr>
+</table>
+<table border="0" align="right" cellpadding="0" cellspacing="0">
+  <tr>
+    <td><a href="../titan_main.html" alt="contents"><img border="0" src="../images/ao.jpg" width="53" height="40"></a></td>
+    <td><a href="../titan_index.html" alt="index"><img border="0" src="../images/up.jpg" width="53" height="40"></a></td>
+    <td><a href="procedure.html" alt="previous"><img border="0" src="../images/left.jpg" width="53" height="40"></a></td>
+    <td><a href="public.html" alt="next"><img border="0" src="../images/right.jpg" width="53" height="40"></a></td>
+  </tr>
+</table>
+<p><br clear="all">
+</p>
+<hr>
+<h1>@profiler</h1>
+<hr align="left" width="75%">
+<p>The keyword is used to start or stop the profiling or check if the profiling started or not.&nbsp;</p>
+<p>By default the profiler is automatically started for each component when the program starts.&nbsp;This can be changed in the configuration file.&nbsp;</p>
+<p>Detailed description can be found in the Programmers' Reference Guide.</p>
+
+<blockquote>
+<p>1. <a href="#1">Stopping the profiler</a></p>
+<p>2. <a href="#2">Starting the profiler</a></p>
+<p>3. <a href="#3">Checking the profiler running state</a></p>
+</blockquote>
+
+
+
+<p>Related keywords:</p>
+<ul>
+  <li><a href="start.html"><b><font face="Courier New" color="#003258" size="4">start</font></b></a></li>
+  <li><a href="stop.html"><b><font face="Courier New" color="#003258" size="4">stop</font></b></a></li>
+   <li><a href="running.html"><b><font face="Courier New" color="#003258" size="4">running</font></b></a></li>
+</ul>
+
+<hr align="left" width="75%">
+<h3>1. <a name="#1">Stopping the profiler</a></h3>
+
+<div align="center">
+<center>
+<table border="0" width="90%" bgcolor="#FFB599" cellpadding="4">
+  <tr>
+    <td width="100%">
+    <h3 align="center"><font face="Courier New" color="#003258" size="5"><b>@profiler.stop</b></font></h3>
+    </td>
+  </tr>
+</table>
+</center>
+</div>
+
+<hr align="left" width="50%">
+<p>The profiler can be stopped using the <font face="Courier New"><b>@profiler.stop</b></font> command.&nbsp;This only affects profiling and code coverage in the current component</p>
+<p>When stopped the profiler does not measure new data. </p>
+<p>This command has no effect if the profiler is already stopped.</p>
+
+<hr align="left" width="75%">
+<h3>2. <a name="#2">Starting the profiler</a></h3>
+
+<hr align="left" width="75%">
+
+
+<div align="center">
+<center>
+<table border="0" width="90%" bgcolor="#FFB599" cellpadding="4">
+  <tr>
+    <td width="100%">
+    <h3 align="center"><font face="Courier New" color="#003258" size="5"><b>@profiler.start</b></font></h3>
+    </td>
+  </tr>
+</table>
+</center>
+</div>
+<p>A stopped profiler can be restarted with the <font face="Courier New"><b>@profiler.start</b></font> command.&nbsp;This only affects profiling and code coverage in the current component.</p>
+<p>Similarly, this has no effect if the profiler is already running.</p>
+
+<p>The execution count of a function is measured at the start of the function, thus if the profiler is stopped when the function is called, its call will not be measured, even if the profiler is restarted during the function’s execution.</p>
+
+
+<hr align="left" width="75%">
+<h3>3. <a name="#3">Checking the profiler running state</a></h3>
+
+
+
+<div align="center">
+<center>
+<table border="0" width="90%" bgcolor="#FFB599" cellpadding="4">
+  <tr>
+    <td width="100%">
+    <h3 align="center"><font face="Courier New" color="#003258" size="5"><b>@profiler.running</b></font></h3>
+    </td>
+  </tr>
+</table>
+</center>
+</div>
+
+<hr align="left" width="75%">
+<p>The boolean value <font face="Courier New"><b>@profiler.running</b></font> stores the state of the profiler in the current component (true if it’s running or false if it’s stopped).</p>
+
+<hr align="left" width="75%">
+<h3>Example:</h3>
+
+<p><font face="Courier New">  function f1(inout integer x) runs on C<br/>
+{<br/>
+&nbsp;&nbsp;var boolean stop_prof := not @profiler.running;<br/>
+&nbsp;&nbsp;@profiler.start;<br/>
+&nbsp;&nbsp;x := x + c1;<br/>
+&nbsp;&nbsp;if (stop_prof) {<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;@profiler.stop;<br/>
+&nbsp;&nbsp;}<br/>
+}<br>
+</font>
+<p>
+
+<p>This function is always profiled and returns the profiler to its original state.</p>
+
+</body>
+</html>
index c98d49ac22985a4d9c00f1f9de2cca677ef483c6..7448a817f5c51dc5860cad4c702f8db1893ff989 100644 (file)
@@ -22,7 +22,7 @@
   <tr>
     <td><a href="../titan_main.html" alt="contents"><img border="0" src="../images/ao.jpg" width="53" height="40"></a></td>
     <td><a href="../titan_index.html" alt="index"><img border="0" src="../images/up.jpg" width="53" height="40"></a></td>
-    <td><a href="procedure.html" alt="previous"><img border="0" src="../images/left.jpg" width="53" height="40"></a></td>
+    <td><a href="profiler.html" alt="previous"><img border="0" src="../images/left.jpg" width="53" height="40"></a></td>
     <td><a href="raise.html" alt="next"><img border="0" src="../images/right.jpg" width="53" height="40"></a></td>
   </tr>
 </table>
index 474c7b85a68b9b5ae6491f3a338c89677fa74611..40abdc673a195e4d632da5ef82ab63870572dc6e 100644 (file)
 <blockquote>
 <p>1. <a href="#Checking components">Checking components</a></p>
 <p>2. <a href="#timer">Checking timers</a></p>
+<p>3. <a href="profiler.html#2">Starting the profiler</a></p>
 </blockquote>
 <hr align="left" width="75%">
-<p>1. <a name="Checking components">Checking components</a></p>
+<h3>1. <a name="Checking components">Checking components</a></h3>
 <hr align="left" width="50%">
 <p>The operation is used to <a href="#Example 1a">check</a> whether a given parallel test component is running (i.e., has neither timed out nor been stopped). The Boolean value true is returned if
 the component have been started but not yet terminated or stopped, false otherwise.</p>
@@ -53,6 +54,7 @@ the component have been started but not yet terminated or stopped, false otherwi
   <li><a href="any.html"><b><font face="Courier New" color="#003258" size="4">any</font></b></a></li>
   <li><a href="component.html"> <b><font face="Courier New" color="#003258" size="4">component</font></b> </a></li>
   <li><a href="create.html"><b><font face="Courier New" color="#003258" size="4">create</font></b></a></li>
+  <li><a href="profiler.html"><b><font face="Courier New" color="#003258" size="4">@profiler</font></b></a></li>
 </ul>
 <hr align="left" width="50%">
 <div align="center">
@@ -85,16 +87,16 @@ the component have been started but not yet terminated or stopped, false otherwi
   </li>
 </ul>
 <hr align="left" width="50%">
-<p><a href="#Example 1a">Examples</a></p>
+<p>See <a href="#Example 1a">Examples</a></p>
 <hr align="left" width="75%">
-<p>2. <a name="timer">Checking&nbsp; timers</a></p>
+<h3>2. <a name="timer">Checking&nbsp; timers</a></h3>
 <hr align="left" width="50%">
 <p>The operation is used to <a href="#timer_start">check</a> whether a given timer is running (i.e., has neither timed out nor been stopped). The Boolean value true is returned if the timer is
 running, false otherwise.</p>
 <ul>
   <li>The operation does not block TTCN-3 program execution, i.e., it reflects the momentarily state of the timer and does not wait for timeout.</li>
   <li><a name="stop_all">The</a> keyword <a href="any.html"><b><font face="Courier New" color="#003258" size="4">any</font></b></a> may be used to check whether <a href="#default">at least
-  one timer</a> is runnig.</li>
+  one timer</a> is running.</li>
 </ul>
 <p>Related keywords:</p>
 <ul>
@@ -123,16 +125,18 @@ running, false otherwise.</p>
   <p><i>timer_identifier</i> is the&nbsp;name used to refer to the timer. It must begin with a letter, may contain letters, numbers and underscore characters.</p>
   </li>
 </ul>
-<hr align="left" width="75%" color="#0094D2">
-<p>It is possible to check a member of an <a href="#array">timer array</a>.</p>
-<hr align="left" width="50%" color="#0094D2">
+<hr align="left" width="50%">
+<p>It is possible to check a member of a <a href="#array">timer array</a>.</p>
+<hr align="left" width="50%">
+<p>See <a href="#Example 1c">Example 1c</a></p>
+<hr align="left" width="50%">
 <div align="center">
 <center>
 <table border="0" width="90%" bgcolor="#FFB599" cellpadding="4">
   <tr>
     <td width="100%">
     <h3 align="center"><font face="Courier New" color="#003258" size="5"><b></b></font> &nbsp; <i>timer_identifier</i><font face="Courier New" color="#003258" size="5"><b>[</b></font><i>array_index</i><font
-      face="Courier New" color="#003258" size="5"><b>].runnig; </b></font></h3>
+      face="Courier New" color="#003258" size="5"><b>].running; </b></font></h3>
     </td>
   </tr>
 </table>
@@ -147,17 +151,19 @@ running, false otherwise.</p>
   <p><i>array_index</i> points out the timer to be checked.</p>
   </li>
 </ul>
-<hr align="left" width="50%">
+<hr align="left" width="75%">
+<h3>Examples</h3>
 <p><a name="Example 1a">Example 1a</a>:</p>
 <p><font face="Courier New">var boolean v_Tbana := vc_metro.running;<br>
 </font>
 <p>The variable v_Tbana gets the value true if the component with the reference vc_metro is running.</p>
 <hr align="left" width="50%">
+
 <p>Example 1b:</p>
 <p><font face="Courier New">var boolean v_Ubahn := all component.running;</font>
 <p>The variable v_Ubahn will true if all started parallel components are still running.</p>
 <hr align="left" width="50%">
-<p>Example 1c:</p>
+<p><a href="#Example 1c">Example 1c</a></p>
 <p><font face="Courier New">var boolean v_metropolitain := any component.running;&nbsp;<br>
 </font>
 <p>The variable v_metropolitain is true if at least one parallel component is still running.</p>
@@ -178,6 +184,6 @@ running, false otherwise.</p>
 <hr align="left" width="25%">
 <hr align="left" width="25%">
 <p><a HREF="BNF.html#runningop">BNF definition</a> of <font face="Courier New">component running</font></p>
-<p><a HREF="BNF.html#runningtimerop">BNF definition</a> of <font face="Courier New">timer runnig</font></p>
+<p><a HREF="BNF.html#runningtimerop">BNF definition</a> of <font face="Courier New">timer runnnig</font></p>
 </body>
 </html>
index 65b655a6f58f7ffd716186621e5172e06621eb0a..dec0f968d06784c89a3a1ac27eddea2db1585698 100644 (file)
 <p>1. <a href="#1"> Starting a component</a></p>
 <p>2. <a href="#Starting a port">Starting a port</a></p>
 <p>3. <a href="##1">Starting a timer</a></p>
+<p>4. <a href="profiler.html#2">Starting the profiler</a></p>
 </blockquote>
 <hr align="left" width="75%">
-<p>1. <a name="#1">Starting a component</a></p>
+<h3>1. <a name="#1">Starting a component</a></h3>
 <hr align="left" width="50%">
 <p>When a parallel test component is created it is not executing any behavior yet.
-<p>The start operation can be used to execute the required function on the addressed<a href="#component_start">parallel test component</a>.</p>
+<p>The start operation can be used to execute the required function on the addressed <a href="#component_start">parallel test component</a>.</p>
 <p>The function will be executed remotely, thus the start operation does not block execution on the component on which it was invoked.
 <p>Normal parallel test components can only be started once, but alive parallel test components may execute several functions consecutively.
 <P>Some limitations apply to the argument function:
@@ -61,6 +62,7 @@
   <li><a href="killed.html"><b><font face="Courier New" color="#003258" size="4">killed</font></b></a></li>
   <li><a href="running.html"><b><font face="Courier New" color="#003258" size="4">running</font></b></a></li>
   <li><a href="stop.html"><b><font face="Courier New" color="#003258" size="4">stop</font></b></a></li>
+  <li><a href="profiler.html"><b><font face="Courier New" color="#003258" size="4">@profiler</font></b></a></li>
 </ul>
 <hr align="left" width="50%">
 <div align="center">
@@ -87,7 +89,7 @@
   </li>
 </ul>
 <hr align="left" width="75%">
-<p>2. <a name="Starting a port">Starting a port</a></p>
+<h3>2. <a name="Starting a port">Starting a port</a></h3>
 <hr align="left" width="50%">
 <p>The keyword may be used to start a <a href="#Example 2a">port</a>.</p>
 <ul>
   </li>
 </ul>
 <hr align="left" width="75%">
-<p>3. <a name="timer">Starting a timer</a></p>
+<h3>3. <a name="timer">Starting a timer</a></h3>
 <hr align="left" width="50%">
 <p>The keyword may be used to indicate that a <a href="#timer_start">timer should start running</a>.</p>
 <ul>
   Otherwise it is optional and overwrites the default value. The value is measured in seconds; <a href="float.html"><b><font face="Courier New" color="#003258" size="4">float</font></b></a>ing point
   value must be used.</li>
 </ul>
-<hr align="left" width="75%" color="#0094D2">
+<hr align="left" width="50%"/>
 <p>It is possible to start a member of an <a href="#array">timer array</a>.</p>
-<hr align="left" width="50%" color="#0094D2">
+<hr align="left" width="50%"/>
 <div align="center">
 <center>
 <table border="0" width="90%" bgcolor="#FFB599" cellpadding="4">
index 8978e338f6565cb8cda8d2dec2a0bb73f9253a4d..0bc493c5bd6ee247e6e3f374a8b0b87d2fdd549b 100644 (file)
 <p>1. <a href="#Terminating a test component">Stopping components</a></p>
 <p>2. <a href="#Starting a port">Stopping ports</a></p>
 <p>3. <a href="#timer">Stopping timers</a></p>
+<p>4. <a href="profiler.html#1">Stopping the profiler</a></p>
 </blockquote>
 <hr align="left" width="75%">
-<p>0. <a name="Terminating execution">Terminating execution</a></p>
+<h3>0. <a name="Terminating execution">Terminating execution</a></h3>
 <p>The stop statement is used to terminate test execution. Whenever a stop statement is reached, the execution of the underlying testcase is immediately terminatef. The result of execution will be
 error.
 <hr align="left" width="50%">
@@ -55,7 +56,9 @@ error.
 <hr align="left" width="50%">
 <p><a href="#Example1b">Examples:</a></p>
 <hr align="left" width="75%">
-<p>1. <a name="Terminating a test component">Stopping components</a></p>
+
+
+<h3>1. <a name="Terminating a test component">Stopping components</a></h3>
 <ul>
   <li>When used in a test case, altstep or function that are executed on a test component, the keyword terminates the relevant test component;</li>
   <li>when used in the control part of a module or in a function used by the control part of a module, it terminates the execution of the module control part.</li>
@@ -68,6 +71,7 @@ error.
   <li><a href="all.html"><b><font face="Courier New" color="#003258" size="4">all</font></b></a></li>
   <li><a href="component.html"> <b><font face="Courier New" color="#003258" size="4">component</font></b> </a></li>
   <li><a href="create.html"><b><font face="Courier New" color="#003258" size="4">create</font></b></a></li>
+  <li><a href="profiler.html"><b><font face="Courier New" color="#003258" size="4">@profiler</font></b></a></li>
 </ul>
 <hr align="left" width="50%">
 <div align="center">
@@ -99,9 +103,11 @@ error.
   </li>
 </ul>
 <hr align="left" width="50%">
-<p><a href="#Example 4:">Examples</a></p>
+<p>See <a href="#Example 4:">Examples</a></p>
 <hr align="left" width="75%">
-<p>2. <a name="Starting a port">Stopping a port</a></p>
+
+
+<h3>2. <a name="Stopping a port">Stopping a port</a></h3>
 <hr align="left" width="50%">
 <p>The keyword may be used to stop a <a href="#Example 2a">port</a>.</p>
 <ul>
@@ -141,7 +147,7 @@ error.
   </li>
 </ul>
 <hr align="left" width="75%">
-<p>3. <a name="timer">Stopping&nbsp; timers</a></p>
+<h3>3. <a name="timer">Stopping&nbsp; timers</a></h3>
 <hr align="left" width="50%">
 <p>The keyword may be used to indicate that a <a href="#timer_start">timer should stop running</a>.</p>
 <ul>
@@ -177,9 +183,9 @@ error.
   <p><i>timer_identifier</i> is the&nbsp;name used to refer to the timer. It must begin with a letter, may contain letters, numbers and underscore characters.</p>
   </li>
 </ul>
-<hr align="left" width="75%" color="#0094D2">
+<hr align="left" width="50%">
 <p>It is possible to stop a member of an <a href="#array">timer array</a>.</p>
-<hr align="left" width="50%" color="#0094D2">
+<hr align="left" width="50%">
 <div align="center">
 <center>
 <table border="0" width="90%" bgcolor="#FFB599" cellpadding="4">
@@ -198,7 +204,7 @@ error.
   <p><i>timer_identifier</i> is the&nbsp;name used to refer to the timer. It must begin with a letter, may contain letters, numbers and underscore characters.</p>
   </li>
   <li>
-  <p><i>array_index</i> points out the timer to be stoped.</p>
+  <p><i>array_index</i> points out the timer to be stopped.</p>
   </li>
 </ul>
 <p><a href="#timer_start">Examples</a></p>
index 5e17b135ee1b328c53e96f349749759c2eb23d64..a35510a29f811609eb01f80636a7b700f2b0c9d4 100644 (file)
@@ -89,8 +89,8 @@
   </tr>
   <tr>
     <td width="17%"><a name="d"></a><a href="info/deactivate.html">deactivate</a></td>
-    <td width="17%"><a href="info/decvalue.html">decvalue</a></td>
     <td width="17%"><a href="info/decode_base64.html">decode_base64</a></td>
+    <td width="17%"><a href="info/decvalue.html">decvalue</a></td>
     <td width="17%"><a href="info/default.html">default</a></td>
     <td width="17%"><a href="info/disconnect.html">disconnect</a></td>
     <td width="17%"><a href="info/display.html">display</a></td>
     <td width="17%"><a href="info/procedure.html">procedure</a></td> 
  </tr>
  <tr>
+    <td width="17%"><a href="info/profiler.html">@profiler</a></td>
     <td width="17%"><a href="info/public.html">public</a></td>
     <td width="17%">&nbsp;</td>
     <td width="17%">&nbsp;</td>
     <td width="17%">&nbsp;</td>
     <td width="17%">&nbsp;</td>
     <td width="17%">&nbsp;</td>
-    <td width="17%">&nbsp;</td>
   </tr>
   <tr>
     <td width="17%"><a name="r"></a><a href="info/raise.html">raise</a></td>
     <td width="17%">&nbsp;</td>
   </tr>
   <tr>
-    <td width="17%"><a name="s"></a><a href="info/self.html">self</a></td>
     <td width="17%"><a href="info/select.html">select</a></td>
+    <td width="17%"><a name="s"></a><a href="info/self.html">self</a></td>
     <td width="17%"><a href="info/send.html">send</a></td>
     <td width="17%"><a href="info/sender.html">sender</a></td>
     <td width="17%"><a href="info/set.html">set</a></td>
     <td width="17%">&nbsp;</td>
   </tr>
   <tr>
-    <td width="17%"><a name="u"></a><a href="info/unichar2int.html">unichar2int</a></td>
     <td width="17%"><a href="info/unichar2char.html">unichar2char</a></td>
+    <td width="17%"><a name="u"></a><a href="info/unichar2int.html">unichar2int</a></td>
     <td width="17%"><a href="info/unichar2oct.html">unichar2oct</a></td>
     <td width="17%"><a href="info/union.html">union</a></td>
     <td width="17%"><a href="info/universal.html">universal</a></td>
     <td width="17%">&nbsp;</td>
     <td width="17%">&nbsp;</td>
   </tr>
+   <tr>
+    <td width="17%"><a name="@"></a><a href="info/profiler.html">@profiler</a></td>
+    <td width="17%">&nbsp;</td>
+    <td width="17%">&nbsp;</td>
+    <td width="17%">&nbsp;</td>
+    <td width="17%">&nbsp;</td>
+    <td width="17%">&nbsp;</td>
+    <td width="17%">&nbsp;</td>
+  </tr>
 </table>
 </center>
 </div>
index c866f9d531819c7d91ffc7734e7d3c116f217432..1c7e9a32eb44525546dc6c8be9aabf0a049014bd 100644 (file)
@@ -57,7 +57,9 @@
       <a href="titan_index.html#u">U</a>
       <a href="titan_index.html#v">V</a>
       <a href="titan_index.html#w">W</a>
-      <a href="titan_index.html#x">X</a></p>
+      <a href="titan_index.html#x">X</a>
+         <a href="titan_index.html#@">@</a>
+         </p>
     </li>
   </ul>
   </li>
diff --git a/loggerplugins/JUnitLogger2/JUnitLogger2.cc b/loggerplugins/JUnitLogger2/JUnitLogger2.cc
new file mode 100644 (file)
index 0000000..825056e
--- /dev/null
@@ -0,0 +1,346 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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
+///////////////////////////////////////////////////////////////////////////////
+#include "JUnitLogger2.hh"
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <sys/time.h>
+
+extern "C"
+{
+  // It's a static plug-in, destruction is done in the destructor.  We need
+  // `extern "C"' for some reason.
+  ILoggerPlugin *create_junit_logger() { return new JUnitLogger2(); }
+}
+
+extern "C" {
+  ILoggerPlugin *create_plugin() { return new JUnitLogger2(); }
+  void destroy_plugin(ILoggerPlugin *plugin) { delete plugin; }
+}
+
+TestSuite::~TestSuite()
+{  
+  for (TestCases::const_iterator it = testcases.begin(); it != testcases.end(); ++it) {
+         delete (*it);
+       }
+}
+
+JUnitLogger2::JUnitLogger2()
+: filename_stem_(NULL), testsuite_name_(mcopystr("Titan")), filename_(NULL), file_stream_(NULL)
+{
+  // Overwrite values set by the base class constructor
+  
+  fprintf(stderr, "construct junitlogger\n");
+  major_version_ = 2;
+  minor_version_ = 0;
+  name_ = mcopystr("JUnitLogger");
+  help_ = mcopystr("JUnitLogger writes JUnit-compatible XML");
+  dte_reason = "";
+  //printf("%5lu:constructed\n", (unsigned long)getpid());
+}
+
+JUnitLogger2::~JUnitLogger2()
+{
+  //printf("%5lu:desstructed\n", (unsigned long)getpid());
+  close_file();
+
+  Free(name_);
+  Free(help_);
+  Free(filename_);
+  Free(testsuite_name_);
+  Free(filename_stem_);
+  name_ = help_ = filename_ = filename_stem_ = NULL;
+  file_stream_ = NULL;
+}
+
+void JUnitLogger2::init(const char */*options*/)
+{
+//printf("%5lu:init\n", (unsigned long)getpid());
+  fprintf(stderr, "Initializing `%s' (v%u.%u): %s\n", name_, major_version_, minor_version_, help_);
+}
+
+void JUnitLogger2::fini()
+{
+  //puts("fini");
+  //fprintf(stderr, "JUnitLogger2 finished logging for PID: `%lu'\n", (unsigned long)getpid());
+}
+
+void JUnitLogger2::set_parameter(const char *parameter_name, const char *parameter_value) {
+//puts("set_par");
+  if (!strcmp("filename_stem", parameter_name)) {
+    if (filename_stem_ != NULL)
+      Free(filename_stem_);
+    filename_stem_ = mcopystr(parameter_value);
+  } else if (!strcmp("testsuite_name", parameter_name)) {
+    if (filename_stem_ != NULL)
+      Free(testsuite_name_);
+    testsuite_name_ = mcopystr(parameter_value);
+  } else {
+    fprintf(stderr, "Unsupported parameter: `%s' with value: `%s'\n",
+      parameter_name, parameter_value);
+  }
+}
+
+void JUnitLogger2::open_file(bool is_first) {
+  if (is_first) {
+    if (filename_stem_ == NULL) {
+      filename_stem_ = mcopystr("junit-xml");
+    }
+  }
+
+  if (file_stream_ != NULL) return; // already open
+
+  if (!TTCN_Runtime::is_single() && !TTCN_Runtime::is_mtc()) return; // don't bother, only MTC has testcases
+
+  filename_ = mprintf("%s-%lu.log", filename_stem_, (unsigned long)getpid());
+
+  file_stream_ = fopen(filename_, "w");
+  if (!file_stream_) {
+    fprintf(stderr, "%s was unable to open log file `%s', reinitialization "
+      "may help\n", plugin_name(), filename_);
+    return;
+  }
+
+  is_configured_ = true;
+  time(&(testsuite.start_ts));
+  testsuite.ts_name = testsuite_name_;
+}
+
+void JUnitLogger2::close_file() {  
+  if (file_stream_ != NULL) {
+    time(&(testsuite.end_ts));
+    testsuite.write(file_stream_);
+    fclose(file_stream_);
+    file_stream_ = NULL;
+  }
+  if (filename_) {
+    Free(filename_);
+    filename_ = NULL;
+  }
+}
+
+void JUnitLogger2::log(const TitanLoggerApi::TitanLogEvent& event,
+  bool /*log_buffered*/, bool /*separate_file*/,
+  bool /*use_emergency_mask*/)
+{
+  if (file_stream_ == NULL) return;
+
+  const TitanLoggerApi::LogEventType_choice& choice = event.logEvent().choice();
+  
+  switch (choice.get_selection()) {
+    case TitanLoggerApi::LogEventType_choice::ALT_testcaseOp: {
+      const TitanLoggerApi::TestcaseEvent_choice& tcev = choice.testcaseOp().choice();  
+    
+      switch (tcev.get_selection()) {
+        case TitanLoggerApi::TestcaseEvent_choice::ALT_testcaseStarted: {
+          testcase.tc_name = tcev.testcaseStarted().testcase__name();
+          // remember the start time
+          testcase.tc_start = 1000000LL * (long long)event.timestamp().seconds() + (long long)event.timestamp().microSeconds();
+          break; }
+
+        case TitanLoggerApi::TestcaseEvent_choice::ALT_testcaseFinished: {
+          const TitanLoggerApi::TestcaseType& tct = tcev.testcaseFinished();
+          testcase.reason = tct.reason();
+          testcase.module_name = tct.name().module__name();
+          
+          const TitanLoggerApi::TimestampType& ts = event.timestamp();
+          long long tc_end = 1000000LL * (long long)ts.seconds() + (long long)ts.microSeconds();
+          testcase.time = (tc_end - testcase.tc_start) / 1000000.0;
+
+          testcase.setTCVerdict(event);
+          testcase.dte_reason = dte_reason.data();
+          dte_reason = "";
+          testsuite.addTestCase(testcase);
+          testcase.reset();
+          break; }
+
+        case TitanLoggerApi::TestcaseEvent_choice::UNBOUND_VALUE:
+          testcase.verdict = TestCase::Unbound;
+          break; } // switch testcaseOp().choice.get_selection()
+
+      break; } // testcaseOp
+      
+    case TitanLoggerApi::LogEventType_choice::ALT_errorLog: {// A DTE is about to be thrown
+      const TitanLoggerApi::Categorized& cat = choice.errorLog();
+      dte_reason = escape_xml_element(cat.text());
+      break; }
+   
+    default: break;
+  } // switch event.logEvent().choice().get_selection()
+
+  fflush(file_stream_);
+}
+
+CHARSTRING JUnitLogger2::escape_xml(const CHARSTRING& xml_str, int escape_chars) {
+  expstring_t escaped = NULL;
+  int len = xml_str.lengthof();
+  for (int i=0; i<len; i++) {
+    char c = *(((const char*)xml_str)+i);
+    switch (c) {
+    case '<':
+      if (escape_chars&LT) escaped = mputstr(escaped, "&lt;");
+      else escaped = mputc(escaped, c);
+      break;
+    case '>':
+      if (escape_chars&GT) escaped = mputstr(escaped, "&gt;");
+      else escaped = mputc(escaped, c);
+      break;
+    case '"':
+      if (escape_chars&QUOT) escaped = mputstr(escaped, "&quot;");
+      else escaped = mputc(escaped, c);
+      break;
+    case '\'':
+      if (escape_chars&APOS) escaped = mputstr(escaped, "&apos;");
+      else escaped = mputc(escaped, c);
+      break;
+    case '&':
+      if (escape_chars&AMP) escaped = mputstr(escaped, "&amp;");
+      else escaped = mputc(escaped, c);
+      break;
+    default:
+      escaped = mputc(escaped, c);
+    }
+  }
+  CHARSTRING ret_val(escaped);
+  Free(escaped);
+  return ret_val;
+}
+
+void TestCase::writeTestCase(FILE* file_stream_) const{
+  switch(verdict){
+    case None: {
+      fprintf(file_stream_, "  <testcase classname='%s' name='%s' time='%f'>\n", module_name.data(), tc_name.data(), time);
+      fprintf(file_stream_, "    <skipped>no verdict</skipped>\n");
+      fprintf(file_stream_, "  </testcase>\n");
+      break; }
+    case Fail:  {
+      fprintf(file_stream_, "  <testcase classname='%s' name='%s' time='%f'>\n", module_name.data(), tc_name.data(), time);
+      fprintf(file_stream_, "    <failure type='fail-verdict'>%s\n", reason.data());
+      fprintf(file_stream_, "%s\n", stack_trace.data());
+      fprintf(file_stream_, "    </failure>\n");
+      fprintf(file_stream_, "  </testcase>\n");
+      break; }
+    case Error:  {
+      fprintf(file_stream_, "  <testcase classname='%s' name='%s' time='%f'>\n", module_name.data(), tc_name.data(), time);
+      fprintf(file_stream_, "    <error type='DTE'>%s</error>\n", dte_reason.data());
+      fprintf(file_stream_, "  </testcase>\n");
+      break; }
+    default: 
+      fprintf(file_stream_, "  <testcase classname='%s' name='%s' time='%f'/>\n", module_name.data(), tc_name.data(), time);
+      break;
+  }
+  fflush(file_stream_);
+}
+
+void TestSuite::addTestCase(const TestCase& testcase) {
+       testcases.push_back(new TestCase(testcase));
+       all++;
+       switch(testcase.verdict) {
+    case TestCase::Fail: failed++; break;
+    case TestCase::None: skipped++; break;
+    case TestCase::Error: error++; break;
+    case TestCase::Inconc: inconc++; break;
+    default: break;
+       }
+}
+
+void TestSuite::write(FILE* file_stream_) {
+  double difftime_ = difftime(end_ts, start_ts);
+  fprintf(file_stream_, "<?xml version=\"1.0\"?>\n"
+    "<testsuite name='%s' tests='%d' failures='%d' errors='%d' skipped='%d' inconc='%d' time='%.2f'>\n",
+    ts_name.data(), all, failed, error, skipped, inconc, difftime_);
+  fflush(file_stream_);
+  
+  for (TestCases::const_iterator it = testcases.begin(); it != testcases.end(); ++it) {
+         (*it)->writeTestCase(file_stream_);
+       }
+       
+  fprintf(file_stream_, "</testsuite>\n");
+  fflush(file_stream_);
+}
+
+void TestCase::setTCVerdict(const TitanLoggerApi::TitanLogEvent& event){
+  TitanLoggerApi::Verdict tc_verdict = event.logEvent().choice().testcaseOp().choice().testcaseFinished().verdict();
+  switch (tc_verdict) {
+    case TitanLoggerApi::Verdict::UNBOUND_VALUE:
+    case TitanLoggerApi::Verdict::UNKNOWN_VALUE:
+      // should not happen
+      break;
+
+    case TitanLoggerApi::Verdict::v0none:
+      verdict = TestCase::None;
+      break;
+
+    case TitanLoggerApi::Verdict::v1pass:
+      verdict = TestCase::Pass;
+      break;
+
+    case TitanLoggerApi::Verdict::v2inconc:
+      verdict = TestCase::Inconc;
+      break;
+
+    case TitanLoggerApi::Verdict::v3fail: {
+      verdict = TestCase::Fail;
+      addStackTrace(event);
+      break; }
+
+    case TitanLoggerApi::Verdict::v4error:
+      verdict = TestCase::Error;
+      break;
+  }
+}
+
+void TestCase::addStackTrace(const TitanLoggerApi::TitanLogEvent& event){
+// Add a stack trace
+  const TitanLoggerApi::TitanLogEvent_sourceInfo__list& stack = event.sourceInfo__list();
+  
+  int stack_depth = stack.size_of();
+  for (int i=0; i < stack_depth; ++i) {
+    const TitanLoggerApi::LocationInfo& location = stack[i];
+    
+    stack_trace += "      ";
+    stack_trace += location.filename();
+    stack_trace += ":";
+    stack_trace += int2str(location.line());
+    stack_trace += " ";
+    stack_trace += location.ent__name();
+    stack_trace += " ";
+    
+    // print the location type
+    switch (location.ent__type()) {
+    case TitanLoggerApi::LocationInfo_ent__type:: UNKNOWN_VALUE:
+    case TitanLoggerApi::LocationInfo_ent__type:: UNBOUND_VALUE:
+      // can't happen
+      break;
+    case TitanLoggerApi::LocationInfo_ent__type::unknown:
+      // do nothing
+      break;
+    case TitanLoggerApi::LocationInfo_ent__type::controlpart:
+      stack_trace += "control part";
+      break;
+    case TitanLoggerApi::LocationInfo_ent__type::testcase__:
+      stack_trace += "testcase";
+      break;
+    case TitanLoggerApi::LocationInfo_ent__type::altstep__:
+      stack_trace += "altstep";
+      break;
+    case TitanLoggerApi::LocationInfo_ent__type::function__:
+      stack_trace += "function";
+      break;
+    case TitanLoggerApi::LocationInfo_ent__type::external__function:
+      stack_trace += "external function";
+      break;
+    case TitanLoggerApi::LocationInfo_ent__type::template__:
+      stack_trace += "template";
+      break;
+    }
+    
+    if(i<stack_depth-1) stack_trace += "\n";
+  }
+}
diff --git a/loggerplugins/JUnitLogger2/JUnitLogger2.hh b/loggerplugins/JUnitLogger2/JUnitLogger2.hh
new file mode 100644 (file)
index 0000000..7029815
--- /dev/null
@@ -0,0 +1,119 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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
+///////////////////////////////////////////////////////////////////////////////
+#ifndef JUnitLogger_HH2
+#define JUnitLogger_HH2
+
+namespace TitanLoggerApi { class TitanLogEvent; }
+
+#ifndef TITAN_RUNTIME_2
+#include "RT1/TitanLoggerApi.hh"
+#else
+#include "RT2/TitanLoggerApi.hh"
+#endif
+
+#include "ILoggerPlugin.hh"
+#include <stdio.h>
+#include <string>
+#include <vector>
+
+struct TestCase{
+       typedef enum {
+               Pass,
+               Inconc,
+               Fail,
+               Error,
+               None,
+               Unbound
+       } Verdict;
+       
+       Verdict verdict;
+       std::string tc_name;
+       std::string module_name;
+       std::string reason;
+       std::string dte_reason;
+       std::string stack_trace;
+       long long tc_start;
+       double time;
+       
+       TestCase():tc_name(""), module_name(""), reason(""), dte_reason(""), stack_trace(""), tc_start(0), time(0.0){}
+       
+       void writeTestCase(FILE* file_stream_) const;
+       void setTCVerdict(const TitanLoggerApi::TitanLogEvent& event);
+       void addStackTrace(const TitanLoggerApi::TitanLogEvent& event);
+  void reset() {
+    tc_name = "";
+    module_name = ""; 
+    reason = "";
+    dte_reason = "";
+    stack_trace = "";
+    tc_start = 0;
+    time = 0.0;
+  }
+};
+
+
+struct TestSuite {
+       typedef std::vector<TestCase*> TestCases;
+       
+//  TitanLoggerApi::TimestampType timestamp; TODO
+  std::string ts_name;
+       int all;
+       int skipped;
+       int failed;
+       int error;
+       int inconc;
+       TestCases testcases;
+  time_t start_ts;
+  time_t end_ts;
+
+       TestSuite():ts_name(""), all(0), skipped(0), failed(0), error(0), inconc(0) {}
+       ~TestSuite();
+       
+  void addTestCase(const TestCase& element);
+       void write(FILE* file_stream_);
+       
+};
+
+class JUnitLogger2: public ILoggerPlugin
+{
+public:
+  JUnitLogger2();
+  virtual ~JUnitLogger2();
+  inline bool is_static() { return false; }
+  void init(const char *options = 0);
+  void fini();
+
+  void log(const TitanLoggerApi::TitanLogEvent& event, bool log_buffered,
+           bool separate_file, bool use_emergency_mask);
+  void set_parameter(const char *parameter_name, const char *parameter_value);
+  // do not implement ILoggerPlugin::set_file_name();
+  // it gets a filename skeleton and can't expand it.
+
+  virtual void open_file(bool /*is_first*/);
+  virtual void close_file();
+
+  enum xml_escape_char_t { LT=0x01, GT=0x02, QUOT=0x04, APOS=0x08, AMP=0x10 };
+  CHARSTRING escape_xml(const CHARSTRING& xml_str, int escape_chars);
+  CHARSTRING escape_xml_attribute(const CHARSTRING& attr_str) { return escape_xml(attr_str, QUOT|AMP); }
+  CHARSTRING escape_xml_element(const CHARSTRING& elem_str) { return escape_xml(elem_str, LT|AMP); }
+  CHARSTRING escape_xml_comment(const CHARSTRING& comm_str) { return escape_xml(comm_str, AMP); /* FIXME: --> should be escaped too */ }
+  
+private:
+  // parameters
+  char *filename_stem_;
+  char *testsuite_name_;
+  // working values
+  char *filename_;
+  TestSuite testsuite;
+  TestCase testcase;
+  std::string dte_reason;
+  
+  FILE *file_stream_;
+};
+
+#endif  // JUnitLogger_HH2
diff --git a/loggerplugins/JUnitLogger2/Makefile b/loggerplugins/JUnitLogger2/Makefile
new file mode 100644 (file)
index 0000000..98bb575
--- /dev/null
@@ -0,0 +1,96 @@
+###############################################################################
+# 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
+###############################################################################
+# Makefile for the JUnitLogger2 plugin.  Unfortunately, we'll need four different
+# libraries for each plugin...  Plugin version information must be
+# synchronized with the code.
+
+TOP    := ../..
+include   ../../Makefile.cfg
+
+LIB_DIR := $(TTCN3_DIR)/lib
+
+MAJOR := 0
+MINOR := 0
+
+SOURCES := JUnitLogger2.cc
+STATIC_SOURCES := ${SOURCES}
+HEADERS := $(SOURCES:.cc=.hh)
+OBJECTS := $(SOURCES:.cc=.o)
+OBJECTS_RT2 := $(addprefix FT/,$(OBJECTS))
+
+SHARED_LIB              := libjunitlogger2.so
+SHARED_LIB_RT2          := libjunitlogger2-rt2.so
+SHARED_LIB_PARALLEL     := libjunitlogger2-parallel.so
+SHARED_LIB_PARALLEL_RT2 := libjunitlogger2-parallel-rt2.so
+
+CPPFLAGS += -I../../core -I$(ABS_SRC)/../../common -I$(ABS_SRC)/../../core
+# RT2 needs core2 (for RT2/TitanLoggerAPI.hh) in addition to core
+CPPFLAGS_RT2 := $(CPPFLAGS) -I$(ABS_SRC)/../../core2 -DTITAN_RUNTIME_2
+
+CXXFLAGS += -Werror
+
+LDFLAGS              += -g -L$(ABS_SRC)/../../core  -Wl,-soname,$(SHARED_LIB).$(MAJOR)              -o $(SHARED_LIB).$(MAJOR).$(MINOR)
+LDFLAGS_RT2          += -g -L$(ABS_SRC)/../../core2 -Wl,-soname,$(SHARED_LIB_RT2).$(MAJOR)          -o $(SHARED_LIB_RT2).$(MAJOR).$(MINOR)
+LDFLAGS_PARALLEL     += -g -L$(ABS_SRC)/../../core  -Wl,-soname,$(SHARED_LIB_PARALLEL).$(MAJOR)     -o $(SHARED_LIB_PARALLEL).$(MAJOR).$(MINOR)
+LDFLAGS_PARALLEL_RT2 += -g -L$(ABS_SRC)/../../core2 -Wl,-soname,$(SHARED_LIB_PARALLEL_RT2).$(MAJOR) -o $(SHARED_LIB_PARALLEL_RT2).$(MAJOR).$(MINOR)
+
+LIBS              := -lttcn3-dynamic
+LIBS_RT2          := -lttcn3-rt2-dynamic
+LIBS_PARALLEL     := -lttcn3-parallel-dynamic
+LIBS_PARALLEL_RT2 := -lttcn3-rt2-parallel-dynamic
+
+TARGETS := $(SHARED_LIB) $(SHARED_LIB_PARALLEL) $(SHARED_LIB_RT2) $(SHARED_LIB_PARALLEL_RT2)
+# .so with .major appended:
+TARGETS_MAJOR       := $(addsuffix .$(MAJOR), $(TARGETS))
+# .so with .major.minor appended:
+TARGETS_MAJOR_MINOR := $(addsuffix .$(MINOR), $(TARGETS_MAJOR))
+
+# OBJECTS_RT2, TARGETS_MAJOR and TARGETS_MAJOR_MINOR are non-standard make variables,
+# not taken into account by "clean" in Makefile.genrules
+# Delete them as "miscellaneous" files.
+TOBECLEANED := $(OBJECTS_RT2) $(TARGETS_MAJOR) $(TARGETS_MAJOR_MINOR)
+
+all run: $(TARGETS)
+
+$(SHARED_LIB): $(OBJECTS)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $? $(LIBS) -shared
+       ln -sf $@.$(MAJOR).$(MINOR) $@.$(MAJOR)
+       ln -sf $@.$(MAJOR) $@
+
+$(SHARED_LIB_RT2): $(OBJECTS_RT2)
+       $(CXX) $(CPPFLAGS_RT2) $(CXXFLAGS) $(LDFLAGS_RT2) $? $(LIBS_RT2) -shared
+       ln -sf $@.$(MAJOR).$(MINOR) $@.$(MAJOR)
+       ln -sf $@.$(MAJOR) $@
+
+$(SHARED_LIB_PARALLEL): $(OBJECTS)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS_PARALLEL) $? $(LIBS_PARALLEL) -shared
+       ln -sf $@.$(MAJOR).$(MINOR) $@.$(MAJOR)
+       ln -sf $@.$(MAJOR) $@
+
+$(SHARED_LIB_PARALLEL_RT2): $(OBJECTS_RT2)
+       $(CXX) $(CPPFLAGS_RT2) $(CXXFLAGS) $(LDFLAGS_PARALLEL_RT2) $? $(LIBS_PARALLEL_RT2) -shared
+       ln -sf $@.$(MAJOR).$(MINOR) $@.$(MAJOR)
+       ln -sf $@.$(MAJOR) $@
+
+$(OBJECTS): $(SOURCES)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $?
+
+# The `-o $@' stuff is necessary, otherwise the result will be put into the
+# current directory.
+$(OBJECTS_RT2): $(SOURCES)
+       mkdir -p FT
+       $(CXX) $(CPPFLAGS_RT2) $(CXXFLAGS) -c $? -o $@
+
+dep:
+       @echo Doing nothing...
+
+install: $(SHARED_LIB) $(SHARED_LIB_RT2) $(SHARED_LIB_PARALLEL) $(SHARED_LIB_PARALLEL_RT2)
+       mkdir -p $(LIB_DIR)
+       cp $(SHARED_LIB)* $(SHARED_LIB_RT2)* $(SHARED_LIB_PARALLEL)* $(SHARED_LIB_PARALLEL_RT2)* $(LIB_DIR)
+
+include ../../Makefile.genrules
index 0d1dd8bed08f3c572911067a5b3ec6ab01a5ad24..19b40d502b4172c9d6a7234c97b993308c96a2aa 100644 (file)
@@ -6,7 +6,7 @@
 # http://www.eclipse.org/legal/epl-v10.html
 ###############################################################################
 DIRS := \
-JUnitLogger TSTLogger
+JUnitLogger TSTLogger JUnitLogger2
 
 all run dep clean distclean install:
        for d in $(DIRS); do $(MAKE) -C $$d $@ || exit 1; done
index 5d1514e268ac6668e62a51f710430f61fc923f34..c29a2736e714755713e1ad009612817f1debfeed 100644 (file)
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <string.h>
 #include <netdb.h>
+#include <sys/select.h>
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
index be8c19348570b7609793f42f1e5d9dc99736f366..12978bdb7b2776f8dfc96a02a25e1e8689055666 100644 (file)
@@ -323,6 +323,12 @@ IPV6 [0-9A-Fa-f:.]+(%[0-9A-Za-z]+)?
   /* SC_cstring */
 
 
+<SC_PROFILER>{HEX}+ {
+  /* numeric statistics filter (check this before checking NUMBERs) */
+  RETURN(ProfilerStatsFlag);
+}
+
+
        /* Values */
 
 {NUMBER} {
@@ -560,12 +566,56 @@ WARNING_UNQUALIFIED RETURN(LoggingBit);
 
 <SC_PROFILER>
 {
-[Dd]isable[Pp]rofiler   return DisableProfilerKeyword;
-[Dd]isable[Cc]overage   return DisableCoverageKeyword;
-[Dd]ata[Bb]ase[Ff]ile   return DatabaseFileKeyword;
-[Aa]ggregate[Dd]ata     return AggregateDataKeyword;
-[Ss]tatistics[Ff]ile    return StatisticsFileKeyword;
-[Dd]isable[Ss]tatistics return DisableStatisticsKeyword;
+  [Dd]isable[Pp]rofiler     RETURN(DisableProfilerKeyword);
+  [Dd]isable[Cc]overage     RETURN(DisableCoverageKeyword);
+  [Dd]ata[Bb]ase[Ff]ile     RETURN(DatabaseFileKeyword);
+  [Aa]ggregate[Dd]ata       RETURN(AggregateDataKeyword);
+  [Ss]tatistics[Ff]ile      RETURN(StatisticsFileKeyword);
+  [Dd]isable[Ss]tatistics   RETURN(DisableStatisticsKeyword);
+  [Ss]tatistics[Ff]ilter    RETURN(StatisticsFilterKeyword);
+  [Ss]tart[Aa]utomatically  RETURN(StartAutomaticallyKeyword);
+  [Nn]et[Ll]ine[Tt]imes     RETURN(NetLineTimesKeyword);
+  [Nn]et[Ff]unction[Tt]imes RETURN(NetFunctionTimesKeyword);
+  
+  /* statistics filters */
+  [Nn]umber[Oo]f[Ll]ines |
+  [Ll]ine[Dd]ata[Rr]aw |
+  [Ff]unc[Dd]ata[Rr]aw |
+  [Ll]ine[Aa]vg[Rr]aw |
+  [Ff]unc[Aa]vg[Rr]aw |
+  [Ll]ine[Tt]imes[Ss]orted[Bb]y[Mm]od |
+  [Ff]unc[Tt]imes[Ss]orted[Bb]y[Mm]od |
+  [Ll]ine[Tt]imes[Ss]orted[Tt]otal |
+  [Ff]unc[Tt]imes[Ss]orted[Tt]otal |
+  [Ll]ine[Cc]ount[Ss]orted[Bb]y[Mm]od |
+  [Ff]unc[Cc]ount[Ss]orted[Bb]y[Mm]od |
+  [Ll]ine[Cc]ount[Ss]orted[Tt]otal |
+  [Ff]unc[Cc]ount[Ss]orted[Tt]otal |
+  [Ll]ine[Aa]vg[Ss]orted[Bb]y[Mm]od |
+  [Ff]unc[Aa]vg[Ss]orted[Bb]y[Mm]od |
+  [Ll]ine[Aa]vg[Ss]orted[Tt]otal |
+  [Ff]unc[Aa]vg[Ss]orted[Tt]otal |
+  [Tt]op10[Ll]ine[Tt]imes |
+  [Tt]op10[Ff]unc[Tt]imes |
+  [Tt]op10[Ll]ine[Cc]ount |
+  [Tt]op10[Ff]unc[Cc]ount |
+  [Tt]op10[Ll]ine[Aa]vg |
+  [Tt]op10[Ff]unc[Aa]vg |
+  [Uu]nused[Ll]ines |
+  [Uu]nused[Ff]unc |
+  [Aa]ll[Rr]aw[Dd]ata |
+  [Ll]ine[Dd]ata[Ss]orted[Bb]y[Mm]od |
+  [Ff]unc[Dd]ata[Ss]orted[Bb]y[Mm]od |
+  [Ll]ine[Dd]ata[Ss]orted[Tt]otal |
+  [Ff]unc[Dd]ata[Ss]orted[Tt]otal |
+  [Ll]ine[Dd]ata[Ss]orted |
+  [Ff]unc[Dd]ata[Ss]orted |
+  [Aa]ll[Dd]ata[Ss]orted |
+  [Tt]op10[Ll]ine[Dd]ata |
+  [Tt]op10[Ff]unc[Dd]ata |
+  [Tt]op10[Aa]ll[Dd]ata |
+  [Uu]nused[Dd]ata |
+  [Aa]ll RETURN(ProfilerStatsFlag);
 }
 
 <SC_EXECUTE>control            RETURN(ControlKeyword);
@@ -935,6 +985,7 @@ static boolean whether_update_buffer()
   case SC_LOGGING:
   case SC_TESTPORT_PARAMETERS:
   case SC_EXTERNAL_COMMANDS:
+  case SC_PROFILER:
     return TRUE;
   default:
     return FALSE;
index 496d4f3994ff8b7c949d82ec3f58e2af4899b305..fa787f2a22bb3c6eac9d940e0c5b310532e44738 100644 (file)
@@ -165,12 +165,17 @@ static void yyprint(FILE *file, int type, const YYSTYPE& value);
 %token Re_try /* Retry clashes with an enum in Qt */
 %token Delete
 
-%token DisableProfilerKeyword   "DisableProfiler"
-%token DisableCoverageKeyword   "DisableCoverage"
-%token DatabaseFileKeyword      "DatabaseFile"
-%token AggregateDataKeyword     "AggregateData"
-%token StatisticsFileKeyword    "StatisticsFile"
-%token DisableStatisticsKeyword "DisableStatistics"
+%token DisableProfilerKeyword    "DisableProfiler"
+%token DisableCoverageKeyword    "DisableCoverage"
+%token DatabaseFileKeyword       "DatabaseFile"
+%token AggregateDataKeyword      "AggregateData"
+%token StatisticsFileKeyword     "StatisticsFile"
+%token DisableStatisticsKeyword  "DisableStatistics"
+%token StatisticsFilterKeyword   "StatisticsFilter"
+%token StartAutomaticallyKeyword "StartAutomatically"
+%token NetLineTimesKeyword       "NetLineTimes"
+%token NetFunctionTimesKeyword   "NetFunctionTimes"
+%token ProfilerStatsFlag        "profiler statistics flag"
 
 %type <int_val> IntegerValue
 %type <float_val> FloatValue KillTimerValue
@@ -706,6 +711,10 @@ ProfilerSetting:
 | AggregateDataSetting
 | StatisticsFileSetting
 | DisableStatisticsSetting
+| StatisticsFilterSetting
+| StartAutomaticallySetting
+| NetLineTimesSetting
+| NetFunctionTimesSetting
 ;
 
 DisableProfilerSetting:
@@ -732,6 +741,29 @@ DisableStatisticsSetting:
   DisableStatisticsKeyword AssignmentChar BooleanValue
 ;
 
+StatisticsFilterSetting:
+  StatisticsFilterKeyword AssignmentChar ProfilerStatsFlags
+| StatisticsFilterKeyword ConcatChar ProfilerStatsFlags
+;
+
+ProfilerStatsFlags:
+  ProfilerStatsFlag
+| ProfilerStatsFlag '&' ProfilerStatsFlags
+| ProfilerStatsFlag '|' ProfilerStatsFlags
+;
+
+StartAutomaticallySetting:
+  StartAutomaticallyKeyword AssignmentChar BooleanValue
+;
+
+NetLineTimesSetting:
+  NetLineTimesKeyword AssignmentChar BooleanValue
+;
+
+NetFunctionTimesSetting:
+  NetFunctionTimesKeyword AssignmentChar BooleanValue
+;
+
 /******************* [TESTPORT_PARAMETERS] section *******************/
 
 TestportParametersSection:
index 9a7ae8abe42d049f84047f601152f88afcc46b24..e5d0ca05d4e2e29e37a124f78a6a0e0bfadcb648 100644 (file)
@@ -121,6 +121,7 @@ void MainController::add_poll_fd(int fd)
 {
   if (fd < 0) return;
   epoll_event event;
+  memset(&event,0,sizeof(event));
   event.events = EPOLLIN;
   event.data.fd = fd;
   if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event) < 0)
@@ -132,6 +133,7 @@ void MainController::remove_poll_fd(int fd)
 {
   if (fd < 0) return;
   epoll_event event;
+  memset(&event,0,sizeof(event));
   event.events = EPOLLIN;
   event.data.fd = fd;
   if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &event) < 0)
index 700b984225c7ba7dee6b6ea47fd4ffdb4e077d82..960342c60e985fca68636d10e2936584ab040f54 100755 (executable)
@@ -63,11 +63,12 @@ proc wait_mc_prompt {} {
 
 proc error_cleanup {error_msg error_retcode} {
     global mctr_id hc_id
+    puts "ttcn3_start: error: $error_msg"
     send -i $mctr_id "exit\r"
     expect -i $mctr_id eof
+    expect -i $hc_id eof
     wait -i $hc_id
     wait -i $mctr_id
-    puts "ttcn3_start: error: $error_msg"
     exit $error_retcode
 }
 
@@ -245,6 +246,8 @@ expect {
     } -i $hc_id -re ".*\r" {
        exp_continue
     } -i $mctr_id "New HC connected from " {
+    } -i $hc_id eof {
+        error_cleanup "Host Controller with id $hc_id stopped unexpectedly" 10
     }
 }
 
index 1cf8b9a6ad63151036527121d4d7283911288573..4b85e6ded30394063264287e81392cd4287e9076 100644 (file)
@@ -21,7 +21,7 @@ nonMandatoryPar logFiles logger_control namedActualParameters \
 assignmentNotation omitdef anytype RAW implicitMsgEncoding pattern_quadruples \
 macros visibility hexstrOper ucharstrOper objidOper CRTR00015758 slider \
 XML ipv6 implicitOmit testcase_defparam transparent HQ16404 cfgFile \
-all_from lazyEval tryCatch text2ttcn json junitlogger ttcn2json
+all_from lazyEval tryCatch text2ttcn json junitlogger ttcn2json profiler
 
 ifdef DYN
 DIRS += loggerplugin
index fc5cb934a87687ca7d03259fa0ad414fddc05121..47007d0047a2ed9eddf873277ea43a7a0b77353c 100644 (file)
@@ -219,6 +219,94 @@ testcase decode_emb_array() runs on EMB
   CHECK_DECODE(exer_dec_emb_outer, str_emb_array_w_holes, Outer, c_emb_array_w_holes);
 }
 
+// same as before, but the embedded values are stored in an optimized record-of
+type record Outer2 {
+  record of universal charstring embed_values,
+  integer attr,
+  octetstring bytes,
+  RoInner stuff
+} with {
+  variant "name as 'Outer'";
+  extension(embed_values) "optimize:memalloc";
+  variant "embedValues";
+  variant(attr) "attribute";
+  variant(bytes) "name as 'Bytes'";
+  variant(stuff) "untagged";
+}
+
+DECLARE_EXER_ENCODERS(Outer2, emb_outer2);
+
+const Outer2 c_emb_array2 := {
+  embed_values := { "one", "two", "three", "four", "five", "six" },
+  attr := 48,
+  bytes := 'DEADBEEF'O,
+  stuff := { { 3, "abc" }, { 4, "def" }, { -6, "red" }, { 118, "blue" } }
+}
+
+const Outer2 c_emb_array_w_holes2 := {
+  embed_values := { "one", "", "three", "", "five" },
+  attr := 48,
+  bytes := 'DEADBEEF'O,
+  stuff := { { 3, "abc" }, { 4, "def" }, { -6, "red" }, { 118, "blue" } }
+}
+
+testcase encode_emb_array_opt() runs on EMB
+{
+  CHECK_METHOD(exer_enc_emb_outer2, c_emb_array2, str_emb_array);
+  CHECK_METHOD(exer_enc_emb_outer2, c_emb_array_w_holes2, str_emb_array_w_holes);
+}
+
+testcase decode_emb_array_opt() runs on EMB
+{
+  CHECK_DECODE(exer_dec_emb_outer2, str_emb_array, Outer2, c_emb_array2);
+  CHECK_DECODE(exer_dec_emb_outer2, str_emb_array_w_holes, Outer2, c_emb_array_w_holes2);
+}
+
+// same as before, but one of the embedded record-ofs is optimized
+type record length (1..infinity) of Inner RoInner2 with { extension "optimize:memalloc" };
+
+type record Outer3 {
+  record of universal charstring embed_values,
+  integer attr,
+  octetstring bytes,
+  RoInner2 stuff
+} with {
+  variant "name as 'Outer'";
+  extension(embed_values) "optimize:memalloc";
+  variant "embedValues";
+  variant(attr) "attribute";
+  variant(bytes) "name as 'Bytes'";
+  variant(stuff) "untagged";
+}
+
+DECLARE_EXER_ENCODERS(Outer3, emb_outer3);
+
+const Outer3 c_emb_array3 := {
+  embed_values := { "one", "two", "three", "four", "five", "six" },
+  attr := 48,
+  bytes := 'DEADBEEF'O,
+  stuff := { { 3, "abc" }, { 4, "def" }, { -6, "red" }, { 118, "blue" } }
+}
+
+const Outer3 c_emb_array_w_holes3 := {
+  embed_values := { "one", "", "three", "", "five" },
+  attr := 48,
+  bytes := 'DEADBEEF'O,
+  stuff := { { 3, "abc" }, { 4, "def" }, { -6, "red" }, { 118, "blue" } }
+}
+
+testcase encode_emb_array_opt2() runs on EMB
+{
+  CHECK_METHOD(exer_enc_emb_outer3, c_emb_array3, str_emb_array);
+  CHECK_METHOD(exer_enc_emb_outer3, c_emb_array_w_holes3, str_emb_array_w_holes);
+}
+
+testcase decode_emb_array_opt2() runs on EMB
+{
+  CHECK_DECODE(exer_dec_emb_outer3, str_emb_array, Outer3, c_emb_array3);
+  CHECK_DECODE(exer_dec_emb_outer3, str_emb_array_w_holes, Outer3, c_emb_array_w_holes3);
+}
+
 control {
   execute(encode_emb());
   execute(decode_emb());
@@ -226,8 +314,12 @@ control {
   execute(decode_emb_all());
   execute(encode_emb_any());
   execute(decode_emb_any());
-  //execute(encode_emb_array()); - this functionality was temporarily removed in RT1
-  //execute(decode_emb_array());
+  execute(encode_emb_array());
+  execute(decode_emb_array());
+  execute(encode_emb_array_opt());
+  execute(decode_emb_array_opt());
+  execute(encode_emb_array_opt2());
+  execute(decode_emb_array_opt2());
 }
 
 }
index 8ae35fd8524df9424a5e318bdd4653932764a39e..8fff1eb671674599ac1adc000bb1d38c9f141a6b 100644 (file)
@@ -41,7 +41,7 @@ CPPFLAGS += -D$(PLATFORM)
 CXXFLAGS += -g -W -Wformat=2
 
 # Flags for the linker:
-LDFLAGS += -g -rdynamic
+#LDFLAGS += -g -rdynamic
 WIN32_LIBS += -liconv
 FREEBSD_LIBS += -liconv
 
index 6c9e7aaf36ec7dcc2c048a0345ca7c40020127a6..893350c800138b1b93d5b89d39a8fa1e52eb6704 100755 (executable)
@@ -51,6 +51,7 @@ my %versions = (
 # built-in modules for the logger
 'TitanLoggerApi' => '',
 'TitanLoggerControl' => '',
+'PreGenRecordOf' => '',
 );
 
 
diff --git a/regression_test/all_from/all_from_subtype.ttcn b/regression_test/all_from/all_from_subtype.ttcn
new file mode 100644 (file)
index 0000000..421e9c1
--- /dev/null
@@ -0,0 +1,191 @@
+/******************************************************************************
+ * Copyright (c) 2000-2015 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
+ ******************************************************************************/
+
+// subtyping and the 'all from' clause
+module all_from_subtype {
+
+import from types all;
+import from functions all;
+
+/* * * * integer * * * */
+template RoI t_RoI1 := { 1, 2, (6..9) };
+template RoI t_RoI2 := { 1, ?, 3 };
+const RoI c_RoI := { 20, 21, 22 };
+
+template PosInt t_posint1 := (0, all from t_RoI1);
+template PosInt t_posint1_exp := (0, 1, 2, (6..9));
+
+template PosInt t_posint2 := (all from c_RoI, 50, 100);
+template PosInt t_posint2_exp := (20, 21, 22, 50, 100);
+
+template PosInt t_posint3 := (10, all from c_RoI, 30, all from t_RoI1);
+template PosInt t_posint3_exp := (10, 20, 21, 22, 30, 1, 2, (6..9));
+
+template ShortRoI t_sroi1 := { 0, (all from t_RoI1, 10), 20 };
+template ShortRoI t_sroi1_exp := { 0, (1, 2, (6..9), 10), 20 };
+
+template ShortRoI t_sroi2 := ( { 1, 2, 3 }, { permutation (all from t_RoI2) } );
+template ShortRoI t_sroi2_exp := ( { 1, 2, 3 }, { permutation (1, ?, 3) } );
+
+testcase tc_all_from_subtype_integer() runs on A
+{
+  if (log2str(t_posint1) != log2str(t_posint1_exp)) {
+    setverdict(fail, "Expected: ", t_posint1_exp, ", got: ", t_posint1);
+  }
+  if (log2str(t_posint2) != log2str(t_posint2_exp)) {
+    setverdict(fail, "Expected: ", t_posint2_exp, ", got: ", t_posint2);
+  }
+  if (log2str(t_posint3) != log2str(t_posint3_exp)) {
+    setverdict(fail, "Expected: ", t_posint3_exp, ", got: ", t_posint3);
+  }
+  if (log2str(t_sroi1) != log2str(t_sroi1_exp)) {
+    setverdict(fail, "Expected: ", t_sroi1_exp, ", got: ", t_sroi1);
+  }
+  if (log2str(t_sroi2) != log2str(t_sroi2_exp)) {
+    setverdict(fail, "Expected: ", t_sroi2_exp, ", got: ", t_sroi2);
+  }
+  setverdict(pass);
+}
+
+/* * * * float * * * */
+template RoF t_RoF := { (-10.0..-2.5), -1.0, 0.0 };
+const RoF c_RoF := { -0.3, -0.2, -0.1 };
+
+template NegFloat t_negfloat := (all from t_RoF, -2.0, all from c_RoF, -100.0);
+template NegFloat t_negfloat_exp := ((-10.0..-2.5), -1.0, 0.0, -2.0, -0.3, -0.2, -0.1, -100.0);
+
+template ShortRoF t_srof := { permutation (all from c_RoF) };
+template ShortRoF t_srof_exp := { permutation (-0.3, -0.2, -0.1) };
+
+testcase tc_all_from_subtype_float() runs on A
+{
+  if (log2str(t_negfloat) != log2str(t_negfloat_exp)) {
+    setverdict(fail, "Expected: ", t_negfloat_exp, ", got: ", t_negfloat);
+  }
+  if (log2str(t_srof) != log2str(t_srof_exp)) {
+    setverdict(fail, "Expected: ", t_srof_exp, ", got: ", t_srof);
+  }
+  setverdict(pass);
+}
+
+/* * * * bitstring * * * */
+template RoBS t_RoBS := { '1010'B, ? };
+const RoBS c_RoBS := { '11011000'B, '00110011'B, '10101010'B };
+
+template ByteString t_bytestr := ('00000000'B, all from c_RoBS, '11111111'B);
+template ByteString t_bytestr_exp := ('00000000'B, '11011000'B, '00110011'B, '10101010'B, '11111111'B);
+
+template ShortRoBS t_srobs := { '1'B, permutation (all from t_RoBS) };
+template ShortRoBS t_srobs_exp := { '1'B, permutation ('1010'B, ?) };
+
+testcase tc_all_from_subtype_bitstring() runs on A
+{
+  if (log2str(t_bytestr) != log2str(t_bytestr_exp)) {
+    setverdict(fail, "Expected: ", t_bytestr_exp, ", got: ", t_bytestr);
+  }
+  if (log2str(t_srobs) != log2str(t_srobs_exp)) {
+    setverdict(fail, "Expected: ", t_srobs_exp, ", got: ", t_srobs);
+  }
+  setverdict(pass);
+}
+
+/* * * * hexstring * * * */
+template RoHS t_RoHS := { '100'H, 'ABC'H };
+const RoHS c_RoHS := { '19A6'H, '999D'H, '1337'H };
+
+template WordString t_wordstr := ('A000'H, 'FFFF'H, all from c_RoHS, '0000'H);
+template WordString t_wordstr_exp := ('A000'H, 'FFFF'H, '19A6'H, '999D'H, '1337'H, '0000'H);
+
+template ShortRoHS t_srohs := { permutation (all from t_RoHS, '180DD'H) };
+template ShortRoHS t_srohs_exp := { permutation ('100'H, 'ABC'H, '180DD'H) };
+
+testcase tc_all_from_subtype_hexstring() runs on A
+{
+  if (log2str(t_wordstr) != log2str(t_wordstr_exp)) {
+    setverdict(fail, "Expected: ", t_wordstr_exp, ", got: ", t_wordstr);
+  }
+  if (log2str(t_srohs) != log2str(t_srohs_exp)) {
+    setverdict(fail, "Expected: ", t_srohs_exp, ", got: ", t_srohs);
+  }
+  setverdict(pass);
+}
+
+/* * * * octetstring * * * */
+template RoOS t_RoOS := { '00'O, 'FF'O };
+const RoOS c_RoOS := { 'E77FB41C'O, 'DEADBEEF'O, 'CDCDCDCD'O };
+
+template DWordString t_dwordstr := (all from c_RoOS, '0FFFFFFF'O);
+template DWordString t_dwordstr_exp := ('E77FB41C'O, 'DEADBEEF'O, 'CDCDCDCD'O, '0FFFFFFF'O);
+
+template ShortRoOS t_sroos := { permutation (?, all from t_RoOS) };
+template ShortRoOS t_sroos_exp := { permutation (?, '00'O, 'FF'O) };
+
+testcase tc_all_from_subtype_octetstring() runs on A
+{
+  if (log2str(t_dwordstr) != log2str(t_dwordstr_exp)) {
+    setverdict(fail, "Expected: ", t_dwordstr_exp, ", got: ", t_dwordstr);
+  }
+  if (log2str(t_sroos) != log2str(t_sroos_exp)) {
+    setverdict(fail, "Expected: ", t_sroos_exp, ", got: ", t_sroos);
+  }
+  setverdict(pass);
+}
+
+/* * * * charstring * * * */
+template RoCS t_RoCS := { ("a".."z"), ("0".."9"), ("A".."Z") };
+const RoCS c_RoCS := { "all_from.ttcn", "types.ttcn", "functions.ttcn", "sapc.ttcn" };
+
+template TtcnFileName t_ttcnfiles := (all from c_RoCS);
+template TtcnFileName t_ttcnfiles_exp := ("all_from.ttcn", "types.ttcn", "functions.ttcn", "sapc.ttcn");
+
+template ShortRoCS t_srocs := { permutation (all from t_RoCS) };
+template ShortRoCS t_srocs_exp := { permutation (("a".."z"), ("0".."9"), ("A".."Z")) };
+
+testcase tc_all_from_subtype_charstring() runs on A
+{
+  if (log2str(t_ttcnfiles) != log2str(t_ttcnfiles_exp)) {
+    setverdict(fail, "Expected: ", t_ttcnfiles_exp, ", got: ", t_ttcnfiles);
+  }
+  if (log2str(t_srocs) != log2str(t_srocs_exp)) {
+    setverdict(fail, "Expected: ", t_srocs_exp, ", got: ", t_srocs);
+  }
+  setverdict(pass);
+}
+
+/* * * * universal charstring * * * */
+template RoUCS t_RoUCS := { "abc", ?, "cba" };
+const RoUCS c_RoUCS := { "nothing", "special", "here" };
+
+template XsdString t_xsdstr := (pattern "<*>", all from c_RoUCS);
+template XsdString t_xsdstr_exp := (pattern "<*>", "nothing", "special", "here");
+
+template ShortRoUCS t_sroucs := { all from t_RoUCS };
+template ShortRoUCS t_sroucs_exp := { "abc", ?, "cba" };
+
+testcase tc_all_from_subtype_universal_charstring() runs on A
+{
+  if (log2str(t_xsdstr) != log2str(t_xsdstr_exp)) {
+    setverdict(fail, "Expected: ", t_xsdstr_exp, ", got: ", t_xsdstr);
+  }
+  if (log2str(t_sroucs) != log2str(t_sroucs_exp)) {
+    setverdict(fail, "Expected: ", t_sroucs_exp, ", got: ", t_sroucs);
+  }
+  setverdict(pass);
+}
+
+control {
+  execute(tc_all_from_subtype_integer());
+  execute(tc_all_from_subtype_float());
+  execute(tc_all_from_subtype_bitstring());
+  execute(tc_all_from_subtype_hexstring());
+  execute(tc_all_from_subtype_octetstring());
+  execute(tc_all_from_subtype_charstring());
+  execute(tc_all_from_subtype_universal_charstring());
+}
+
+}
index 134f2ecb7e95179105b92d49c2c00590cd5d4545..5aaa17a6e21a7852d9650553d72b00b144a32f4f 100644 (file)
@@ -11,7 +11,7 @@ module all_from_with_functions {
 
 external function f_ext(in template RoI r) return template RoI;
 
-type record of integer RoI;
+type record of integer RoI with { encode "JSON" };
 type set of integer SoI;
 
 type record Rec {
@@ -119,10 +119,52 @@ testcase tc_all_from_func_params() runs on CT_Empty {
   else { setverdict(fail, "Expected: ", c_res_log, ", got: ", vt_res); }
 }
 
+function f_non_templ(in RoI x) return RoI
+{
+  return x;
+}
+
+external function f_dec_roi(in octetstring os) return RoI
+  with { extension "prototype(convert) decode(JSON)" }
+
+// all from used on regular (non-template) functions
+testcase tc_all_from_with_functions2() runs on CT_Empty
+{
+  var template RoI vt_func_roi := { permutation ( all from f_non_templ( { 1, 4, 7, 10 } ) ) };
+  var template integer vt_func_int := ( 0, 1, all from f_non_templ( { 3, 6, 9 } ) );
+
+  var octetstring v_enc := char2oct("[ 4, 2, 10, 100 ]");
+  var template RoI vt_ext_func_roi := { permutation ( all from f_dec_roi(v_enc) ) };
+  var template integer vt_ext_func_int := ( 0, 1, all from f_dec_roi(v_enc) );
+
+  var charstring v_res_log := "{ permutation(1, 4, 7, 10) }";
+  if (log2str(vt_func_roi) != v_res_log) {
+    setverdict(fail, "Expected: ", v_res_log, ", got: ", vt_func_roi);
+  }
+
+  v_res_log := "(0, 1, 3, 6, 9)";
+  if (log2str(vt_func_int) != v_res_log) {
+    setverdict(fail, "Expected: ", v_res_log, ", got: ", vt_func_int);
+  }
+
+  v_res_log := "{ permutation(4, 2, 10, 100) }";
+  if (log2str(vt_ext_func_roi) != v_res_log) {
+    setverdict(fail, "Expected: ", v_res_log, ", got: ", vt_ext_func_roi);
+  }
+
+  v_res_log := "(0, 1, 4, 2, 10, 100)";
+  if (log2str(vt_ext_func_int) != v_res_log) {
+    setverdict(fail, "Expected: ", v_res_log, ", got: ", vt_ext_func_int);
+  }
+
+  setverdict(pass);
+}
+
 
 control {
   execute(tc_all_from_with_functions());
   execute(tc_all_from_func_params());
+  execute(tc_all_from_with_functions2());
 }
 
 }
index 862f3de7c5a32b53e164e823b5e9bd8082438168..cc8c2e8c0e8d9a3991d414f4f68bb0f6f50d0be7 100644 (file)
@@ -16,6 +16,7 @@ type component A {
 
 type record of integer RoI;
 type set    of integer SoI;
+type record of float RoF;
 type record of SoI RoSoI;
 type record of RoI RoRoI;
 type record of RoOS RoRoOS;
@@ -23,12 +24,18 @@ type record of SoOS RoSoOS;
 
 type set of integer MySetOfType (0 .. 10);
 
+type record of bitstring RoBS;
+
+type record of hexstring RoHS;
+
 type record of charstring RoCS;
 type set of charstring CoCS;
 
 type record of octetstring RoOS;
 type set of octetstring SoOS;
 
+type record of universal charstring RoUCS;
+
 type record MyRecord {
   integer i optional,
   RoI     roi optional,
@@ -80,4 +87,41 @@ type record CAI3gCommand {
 }
 */
 
+/* * * * Subtypes * * * */
+
+type integer PosInt (0..infinity);
+
+type float NegFloat (-infinity..0.0);
+
+type bitstring ByteString length (8);
+
+type hexstring WordString length (4);
+
+type octetstring DWordString length (4);
+
+type charstring TtcnFileName (pattern "*.ttcn");
+
+type universal charstring XsdString (
+  char(0,0,0,9)..char(0,0,0,9),
+  char(0,0,0,10)..char(0,0,0,10),
+  char(0,0,0,12)..char(0,0,0,12),
+  char(0,0,0,32)..char(0,0,215,255),
+  char(0,0,224,0)..char(0,0,255,253),
+  char(0,1,0,0)..char(0,16,255,253)
+);
+
+type record length (0..3) of integer ShortRoI;
+
+type record length (0..3) of float ShortRoF;
+
+type record length (0..3) of bitstring ShortRoBS;
+
+type record length (0..3) of hexstring ShortRoHS;
+
+type record length (0..3) of octetstring ShortRoOS;
+
+type record length (0..3) of charstring ShortRoCS;
+
+type record length (0..3) of universal charstring ShortRoUCS;
+
 }
index 602542acab8d2c6e523ab93d8988c68bd771ad11..dabf6b61bd8df9320df4138669b3cf5b7f8d7399 100644 (file)
@@ -303,6 +303,60 @@ testcase boolIsvalue() runs on boolOper_comptype{
   if ( isvalue(vt1) ) { setverdict(fail); } else { setverdict(pass); };
 }
 
+type union TestUnion {
+  integer t,
+  boolean b
+}
+
+type record TestRecord {
+  integer t,
+  boolean b optional
+}
+
+// for TR fix HT60781
+testcase boolShortCircuit() runs on boolOper_comptype {
+  // create a union variable, make sure the boolean field is not chosen
+  var TestUnion myUnion := { t := 1 };
+  
+  // reference the boolean field in the 2nd part of a condition using 'and' or 'or'
+  // only the first part of the condition should be evaluated, since
+  // evaluating the 2nd part would produce a DTE (because the field isn't chosen)
+  if (ischosen(myUnion.b) and myUnion.b) {
+    setverdict(fail, "Error in 'if' condition, field 'b' is not supposed to be chosen");
+  }
+  while (ischosen(myUnion.b) and myUnion.b) {
+    setverdict(fail, "Error in 'while' condition, field 'b' is not supposed to be chosen");
+  }
+  var integer i;
+  for (i := 0; ischosen(myUnion.b) and myUnion.b and i < 5; i := i + 1) {
+    setverdict(fail, "Error in 'for' condition, field 'b' is not supposed to be chosen");
+  }
+  var boolean res := not ischosen(myUnion.b) or myUnion.b;
+  if (not res) {
+    setverdict(fail, "Error in boolean assignment, field 'b' is not supposed to be chosen");
+  }
+
+  // create a record variable, make sure the boolean field is omitted
+  var TestRecord myRec := { t := 1, b := omit };
+  
+  // reference the boolean field in the 2nd part of a condition, same as with the union field
+  // (referencing the boolean field would cause a DTE again, because it is omitted)
+  if (ispresent(myRec.b) and myRec.b) {
+    setverdict(fail, "Error in 'if' condition, field 'b' is not supposed to be present");
+  }
+  while (ispresent(myRec.b) and myRec.b) {
+    setverdict(fail, "Error in 'if' condition, field 'b' is not supposed to be present");
+  }
+  for (i := 0; ispresent(myRec.b) and myRec.b and i < 5; i := i + 1) {
+    setverdict(fail, "Error in 'for' condition, field 'b' is not supposed to be present");
+  }
+  res := not ispresent(myRec.b) or myRec.b;
+  if (not res) {
+    setverdict(fail, "Error in boolean assignment, field 'b' is not supposed to be present");
+  }
+  setverdict(pass);
+}
+
 control {
   const boolean cl_1:=true;
   var boolean vl_1;
@@ -317,6 +371,7 @@ control {
   execute(boolXor());
   execute(boolSubtypes());
   execute(boolIsvalue());
+  execute(boolShortCircuit());
 }
 
 }
index cc52824c4018f7b713da01c2bc7fd2ac73181d5f..46e7995c824f294a84123dec7db62c01a018dc1c 100644 (file)
@@ -129,10 +129,10 @@ tsp_anytype_float := {float := 42.0}
 tsp_anytype_MyRec := {MyRec := {field1 := 1, field2 := 2}}
 
 // Component
-//tsp_component_null := null //modulepar cannot be of type component 
+tsp_component_null := null
 
 // Default
-//tsp_default := null //modulepar cannot be of type default
+tsp_default := null
 
 // Nested array, record of & set of
 tsp_nested.roi := { 4, 5 };
index 90e757fa9e9e6d1c776818378a817e832db77a20..69d68421d23e528f1d63a487a28563c7a7c681ff 100644 (file)
@@ -173,10 +173,10 @@ modulepar anytype tsp_anytype_float;
 modulepar anytype tsp_anytype_MyRec;
 
 // Component
-//modulepar MyComp_CT tsp_component_null; // modulepar cannot be of type component 
+modulepar MyComp_CT tsp_component_null;
 
 // Default
-//modulepar default tsp_default; // modulepar cannot be of type default 
+modulepar default tsp_default;
 
 // Nested array, record of & set of
 modulepar NestedRec tsp_nested := { { 1, 2, 3 }, { 1, 2, 3 } };
@@ -496,6 +496,16 @@ testcase tc_anytype() runs on MyComp_CT {
   else { setverdict(fail, "tsp_anytype_MyRec");}
 }
 
+testcase tc_component() runs on MyComp_CT {
+  if (tsp_component_null == null) { setverdict(pass); }
+  else { setverdict(fail, "tsp_component_null");}
+}
+
+testcase tc_default() runs on MyComp_CT {
+  if (tsp_default == null) { setverdict(pass); }
+  else { setverdict(fail, "tsp_default");}
+}
+
 testcase tc_nested() runs on MyComp_CT {
   if (tsp_nested == { { 4, 5, 9 }, { 6, 7, 8 } }) { setverdict(pass); }
   else { setverdict(fail, "tsp_nested = ", tsp_nested); }
@@ -558,6 +568,8 @@ control {
   execute(tc_set_of());
   execute(tc_anytype());
   execute(tc_array());
+  execute(tc_component());
+  execute(tc_default());
   execute(tc_nested());
   execute(tc_nested_templ());
 }
index f5f02fedf4d3f1d8b0d8e0e8e932055de5ab1aeb..580e20c7a897c1c7e759fc1b148d786f94e0be5b 100644 (file)
@@ -14,7 +14,7 @@ CODIRS := dynamicTemplate styleGuide topLevelPdu \
        centralstorage mfgen-tpd \
        openType optionalAssignCompare portConstructor \
        isbound namedActualParameters assignmentNotation \
-       attribQualif HT48786
+       attribQualif HT48786 selectCase
 
 all dep clean distclean:
        for dir in $(CODIRS); do $(MAKE) -C $$dir $@ || exit; done
diff --git a/regression_test/compileonly/selectCase/Makefile b/regression_test/compileonly/selectCase/Makefile
new file mode 100644 (file)
index 0000000..68eabbe
--- /dev/null
@@ -0,0 +1,41 @@
+###############################################################################
+# Copyright (c) 2000-2015 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
+###############################################################################
+TOPDIR := ../..
+include $(TOPDIR)/Makefile.regression
+
+.PHONY: all clean dep
+
+TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
+
+TTCN3_MODULES = selectCase.ttcn
+
+GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc)
+GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh)
+ifdef CODE_SPLIT
+GENERATED_SOURCES := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), .cc _seq.cc _set.cc  _seqof.cc _setof.cc _union.cc))
+endif
+
+OBJECTS = $(GENERATED_SOURCES:.cc=.o)
+
+TARGET = selectCase$(EXESUFFIX)
+
+all: $(TARGET)
+
+$(TARGET): $(GENERATED_SOURCES) $(USER_SOURCES)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) \
+       -L$(OPENSSL_DIR)/lib -lcrypto $($(PLATFORM)_LIBS)
+
+$(GENERATED_SOURCES) $(GENERATED_HEADERS): $(TTCN3_MODULES)
+       $(TTCN3_COMPILER) $(COMPILER_FLAGS) $^
+
+clean distclean:
+       $(RM) $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \
+       $(GENERATED_SOURCES) compile *.log
+
+dep: $(GENERATED_SOURCES)
+       makedepend $(CPPFLAGS) $(GENERATED_SOURCES)
diff --git a/regression_test/compileonly/selectCase/selectCase.ttcn b/regression_test/compileonly/selectCase/selectCase.ttcn
new file mode 100644 (file)
index 0000000..5d825ea
--- /dev/null
@@ -0,0 +1,76 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2000-2015 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
+///////////////////////////////////////////////////////////////////////////////
+
+module selectCase {
+
+type record of integer RoI;
+
+type record Rec {
+  RoI numz
+}
+
+type record EmptyRec { }
+
+type record Rec2 {
+  EmptyRec empty
+}
+
+function f_embeddedEmptyArray() {
+  var Rec r := { numz := { 1, 2 } };
+
+  select (r) {
+    // this condition used to crash the compiler during code generation (artf521346)
+    case ( { numz := { } } ) {
+      action("empty");
+    }
+    case else {
+      action("not empty");
+    }
+  }
+}
+
+function f_emptyArray() {
+  var RoI a := { 1, 2 };
+
+  select (a) {
+    case ( { } ) {
+      action("empty");
+    }
+    case else {
+      action("not empty");
+    }
+  }
+}
+
+function f_emptyRecord() {
+  var EmptyRec er := { };
+
+  select (er) {
+    case ( { } ) {
+      action("empty");
+    }
+    case else {
+      action("not empty");
+    }
+  }
+}
+
+function f_embeddedEmptyRecord() {
+  var Rec2 r2 := { empty := { } };
+
+  select (r2) {
+    case ( { empty := { } } ) {
+      action("empty");
+    }
+    case else {
+      action("not empty");
+    }
+  }
+}
+
+}
index aa0d37f5ed177aef15adcdebe7a7fbbab151e422..5a3b24a84d00acdaba27fb2b3151df9810a38ab6 100755 (executable)
@@ -25,7 +25,7 @@ CXXFLAGS += -Wall -Wextra -Wshadow -g
 CXXDEPFLAGS := -MM
 
 #COMPILER_FLAGS +=
-LDFLAGS += -rdynamic
+#LDFLAGS += -rdynamic
 
 TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
 
diff --git a/regression_test/profiler/Makefile b/regression_test/profiler/Makefile
new file mode 100755 (executable)
index 0000000..58a4580
--- /dev/null
@@ -0,0 +1,82 @@
+###############################################################################
+# Copyright (c) 2000-2015 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
+###############################################################################
+TOPDIR := ..
+include $(TOPDIR)/Makefile.regression
+
+.SUFFIXES: .ttcn .asn .hh .json
+.PHONY: all clean dep run
+
+TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
+
+# Tester modules
+TTCN3_MODULES = PIPEasp_PortType.ttcn PIPEasp_Types.ttcn PIPEasp_Templates.ttcn Shell.ttcn Testcases.ttcn
+
+GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) $(ASN1_MODULES:.asn=.cc)
+GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh)
+ifdef CODE_SPLIT
+GENERATED_SOURCES := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), .cc _seq.cc _set.cc  _seqof.cc _setof.cc _union.cc))
+endif
+
+USER_SOURCES = PIPEasp_PT.cc
+USER_HEADERS = $(USER_SOURCES:.cc=.hh)
+
+OBJECTS = $(GENERATED_SOURCES:.cc=.o) $(USER_SOURCES:.cc=.o)
+
+TARGET = profiler_test$(EXESUFFIX)
+
+# Tested modules (these are compiled with profiling enabled, and are executed by the tester modules)
+PROF_MODULES = prof1.ttcn prof2.ttcn prof3.ttcn
+
+PROF_COMPILER_FLAGS = $(COMPILER_FLAGS) -z prof_files.txt
+
+PROF_TTCN3_LIB = ttcn3$(RT2_SUFFIX)-parallel$(DYNAMIC_SUFFIX)
+
+PROF_GENERATED_SOURCES = $(PROF_MODULES:.ttcn=.cc)
+PROF_GENERATED_HEADERS = $(PROF_GENERATED_SOURCES:.cc=.hh)
+
+PROF_OBJECTS = $(PROF_GENERATED_SOURCES:.cc=.o)
+
+PROF_TARGET = prof.exe
+
+TEMP_FILES = $(PROF_GENERATED_SOURCES) $(PROF_GENERATED_HEADERS) $(PROF_OBJECTS) $(PROF_TARGET) data.json prof1.stats empty.stats
+
+# Rules for tester modules
+all: $(TARGET)
+
+$(TARGET): $(GENERATED_SOURCES) $(USER_SOURCES)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) -L$(OPENSSL_DIR)/lib -lcrypto $($(PLATFORM)_LIBS)
+
+$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile
+       @if [ ! -f $@ ]; then $(RM) compile; $(MAKE) compile; fi
+
+compile: $(TTCN3_MODULES)
+       $(filter-out -Nold -E, $(TTCN3_COMPILER)) $(COMPILER_FLAGS) $^ 
+       touch compile
+       
+clean distclean:
+       -rm -f $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \
+       $(GENERATED_SOURCES) *.log Makefile.bak $(TEMP_FILES)
+
+dep: $(GENERATED_SOURCES) $(PROF_GENERATED_SOURCES)
+       makedepend $(CPPFLAGS) $^
+
+run: $(TARGET)
+       ./$^
+
+.NOTPARALLEL:
+
+# Rules for tested modules
+$(PROF_TARGET): $(PROF_GENERATED_SOURCES)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ -L$(TTCN3_DIR)/lib -l$(PROF_TTCN3_LIB) -L$(OPENSSL_DIR)/lib -lcrypto $($(PLATFORM)_LIBS)
+
+$(PROF_GENERATED_SOURCES) $(PROF_GENERATED_HEADERS): prof_compile
+       @if [ ! -f $@ ]; then $(RM) prof_compile; $(MAKE) prof_compile; fi
+
+prof_compile: $(PROF_MODULES)
+       $(filter-out -Nold -E, $(TTCN3_COMPILER)) $(PROF_COMPILER_FLAGS) $^ 
+       touch compile
diff --git a/regression_test/profiler/PIPEasp_PT.cc b/regression_test/profiler/PIPEasp_PT.cc
new file mode 100644 (file)
index 0000000..2b57a16
--- /dev/null
@@ -0,0 +1,738 @@
+/*******************************************************************************
+* 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
+*
+* Contributors:
+*     Zoltan Janos Szabo (Ericsson) - initial architecture design and implementation
+*     Roland Gecse (Ericsson) - initial architecture design
+*     Akos Cserveni (Ericsson) - Basic AST in compiler, semantic checking
+*     Gabor Szalai (Ericsson) â€“ RAW and TEXT codecs
+*     Matyas Forstner (Ericsson) - ASN.1 extension of the compiler and BER/CER/DER codecs
+*     Kristof Szabados  (Ericsson) - Eclipse Designer, Executor, Titanium UIs
+*     Szabolcs Beres (Ericsson) - Eclipse LogViewer
+*     Ferenc Kovacs (Ericsson) â€“ log interfaces, big number support, subtype checking
+*     Csaba Raduly (Ericsson) â€“ ASN.1 additions, XML encoder/decoder
+*     Adam Delic (Ericsson) â€“ template restrictions, try&catch, support of pre-processor directives in Eclipse
+*     Krisztian Pandi (Ericsson) â€“ import of imports
+*     Peter Dimitrov (Ericsson)- maintenance
+*     Balazs Andor Zalanyi (Ericsson) â€“ code splitting
+*     Gabor Szalai (Ericsson) â€“ RAW encoding/decoding
+*     Jeno Attila Balasko (Ericsson) â€“ tests
+*     Csaba Feher (Ericsson) â€“ epoll support
+*     Tamas Buti (Ericsson)- maintenance
+*     Matyas Ormandi (Ericsson) - maintenance
+*     Botond Baranyi (Ericsson) - JSON encoder
+*     Arpad Lovassy (Ericsson) - Java Executor API
+*     Laszlo Baji (Ericsson) - maintenance
+*     Marton Godar (Ericsson) - xsd2ttcn converter
+*******************************************************************************/
+//
+//  File:               PIPEasp_PT.cc
+//  Description:        Source code of PIPE testport implementation
+//  Rev:                <RnXnn>
+//  Prodnr:             CNL 113 334
+//  Updated:            2008-06-03
+//  Contact:            http://ttcn.ericsson.se
+//
+
+
+#include "PIPEasp_PT.hh"
+#include <signal.h> //kill
+#include <unistd.h> //pipe
+#include <errno.h>  //errno
+#include <ctype.h>  //isspace
+#include <sys/select.h>  //FD_ZERO
+#include <stdio.h>      // sys_errlist
+#include <sys/types.h>  //wait
+#include <sys/wait.h>   //wait
+
+#ifndef PIPE_BUF_SIZE
+#define PIPE_BUF_SIZE 655536
+#endif
+
+namespace PIPEasp__PortType {
+
+PIPEasp__PT::PIPEasp__PT(const char *par_port_name)
+       : PIPEasp__PT_BASE(par_port_name)
+        , lineMode(true)
+        , processExecuting(false)
+        , binaryMode(false)
+        , disableSend(false)
+        , processPid(-1)     // pid of the process currently executing
+        , processStdin(-1)   // fd of stdin of the process
+        , processStdout(-1)  // fd of stdout of the process
+        , processStderr(-1)  // fd of stderr of the process
+        , processExitCode(0) // exit code of the process
+{
+  FD_ZERO(&readfds);
+  stdout_buffer.clear();
+  stderr_buffer.clear();
+}
+
+PIPEasp__PT::~PIPEasp__PT()
+{
+// nothing to do
+}
+
+void PIPEasp__PT::set_parameter(const char * /*parameter_name*/,
+       const char * /*parameter_value*/)
+{
+// no config parameters
+}
+
+void PIPEasp__PT::Event_Handler(const fd_set *read_fds,
+       const fd_set * /*write_fds*/, const fd_set * /*error_fds*/,
+       double /*time_since_last_call*/)
+{
+  log("PIPEasp__PT::Event_Handler called");
+  if (processStdout != -1 && FD_ISSET(processStdout, read_fds)) {
+    if (!processExecuting) {
+      TTCN_warning("Unexpected message from stdout, no command is executing");
+    } else {
+      log("Incoming stdout message received from process");
+    }
+
+    long nBytes;
+    int r;
+
+    nBytes = PIPE_BUF_SIZE;
+    unsigned char* buffer;
+    size_t end_len = nBytes;
+    stdout_buffer.get_end(buffer, end_len);
+    r = read(processStdout,buffer,(int)nBytes);
+    if (r <= 0) {
+       log("ttcn_pipe_port: read problem on stdout.\n");
+        // close the pipe and remove it from event handler
+        close(processStdout);
+        FD_CLR(processStdout, &readfds);
+        Install_Handler(&readfds, NULL, NULL, 0.0);
+        processStdout = -1;
+
+        // check if stderr is closed:
+        if (processStderr == -1) {
+          // child died
+          log("Child might have died.");
+          handle_childDeath();
+        }
+    }
+    else {
+      log("incoming stdout %ld bytes\n", r);
+      stdout_buffer.increase_length(r);
+      sendStdout();
+    }
+    return;
+  }
+  if (processStderr != -1 && FD_ISSET(processStderr, read_fds)) {
+    if (!processExecuting) {
+      TTCN_warning("Unexpected message from stderr, no command is executing");
+    } else {
+      log("Incoming stderr message received from process");
+    }
+
+    long nBytes;
+    int r;
+
+    nBytes = PIPE_BUF_SIZE;
+    unsigned char* buffer;
+    size_t end_len = nBytes;
+    stderr_buffer.get_end(buffer, end_len);
+    r = read(processStderr,buffer,(int)nBytes);
+    if (r <= 0) {
+       log("ttcn_pipe_port: read problem on stderr.\n");
+        // close the pipe and remove it from event handler
+        close(processStderr);
+        FD_CLR(processStderr, &readfds);
+        Install_Handler(&readfds, NULL, NULL, 0.0);
+        processStderr = -1;
+
+        // check if stdout is closed:
+        if (processStdout == -1) {
+          // child died
+          log("Child might have died.");
+          handle_childDeath();
+        }
+    }
+    else {
+      log("incoming stderr %ld bytes\n", r);
+      stderr_buffer.increase_length(r);
+      sendStderr();
+    }
+    return;
+  }
+}
+
+void PIPEasp__PT::user_map(const char * /*system_port*/)
+{
+// nothing to do
+}
+
+void PIPEasp__PT::user_unmap(const char * /*system_port*/)
+{
+// nothing to do
+}
+
+void PIPEasp__PT::user_start()
+{
+// nothing to do
+}
+
+void PIPEasp__PT::user_stop()
+{
+// nothing to do
+}
+
+/*************************************
+*  Specific outgoing_send functions
+*************************************/
+void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PExecute& send_par) {
+  log("PIPEasp__PT::outgoing_send_PExecute called");
+  // disable sendStdout, sendStderr until process exits
+  if (processExecuting) {
+    sendError("Pipe Test Port: Command already executing");
+    TTCN_Logger::begin_event(TTCN_DEBUG);
+    TTCN_Logger::log_event("PIPE test port (%s): Command already executing. Following ASP is ignored: ", get_name());
+    send_par.log();
+    TTCN_Logger::end_event();
+    return;
+  }
+  PIPEasp__Types::ASP__PExecuteBackground message_PExecuteBackground;
+  // starting command
+  message_PExecuteBackground.command() = send_par.command();
+  outgoing_send(message_PExecuteBackground);
+  // sending input
+  PIPEasp__Types::ASP__PStdin message_PStdin;
+  message_PStdin.stdin_() = send_par.stdin_();
+  outgoing_send(message_PStdin);
+  disableSend = true;
+
+  // closing stdin pipe:
+  outgoing_send(PIPEasp__Types::ASP__PEndOfInput());
+
+  log("PIPEasp__PT::outgoing_send_PExecute exited");
+}
+
+void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PExecuteBinary& send_par) {
+  log("PIPEasp__PT::outgoing_send_PExecuteBinary called");
+  // disable sendStdout, sendStderr until process exits
+  if (processExecuting) {
+    sendError("Pipe Test Port: Command already executing");
+    TTCN_Logger::begin_event(TTCN_DEBUG);
+    TTCN_Logger::log_event("PIPE test port (%s): Command already executing. Following ASP is ignored: ", get_name());
+    send_par.log();
+    TTCN_Logger::end_event();
+    return;
+  }
+  PIPEasp__Types::ASP__PExecuteBackground message_PExecuteBackground;
+  // starting command
+  message_PExecuteBackground.command() = send_par.command();
+  outgoing_send(message_PExecuteBackground);
+  // sending input
+  PIPEasp__Types::ASP__PStdinBinary message_PStdinBinary;
+  message_PStdinBinary.stdin_() = send_par.stdin_();
+  outgoing_send(message_PStdinBinary);
+  disableSend = true;
+
+  // closing stdin pipe:
+  outgoing_send(PIPEasp__Types::ASP__PEndOfInput());
+
+  log("PIPEasp__PT::outgoing_send_PExecuteBinary exited");
+}
+
+void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PExecuteBackground& send_par) {
+  log("PIPEasp__PT::outgoing_send_PExecuteBackground called");
+
+  if (processExecuting) {
+    log("Process already executing. Cannot start new process.");
+    sendError("Pipe Test Port: Command already executing");
+    TTCN_Logger::begin_event(TTCN_DEBUG);
+    TTCN_Logger::log_event("PIPE test port (%s): Command already executing. Following ASP is ignored: ", get_name());
+    send_par.log();
+    TTCN_Logger::end_event();
+    log("PIPEasp__PT::outgoing_send_PExecuteBackground exited");
+    return;
+  }
+
+  // creating pipes for process
+  int pipesStdin[2];
+  int pipesStdout[2];
+  int pipesStderr[2];
+
+  if (pipe(pipesStdin) != 0) {
+      sendError("Pipe Test Port: Cannot create stdin pipe");
+      log("PIPEasp__PT::outgoing_send_PExecuteBackground exited");
+      return;
+  }
+  if (pipe(pipesStdout) != 0) {
+      sendError("Pipe Test Port: Cannot create stdout pipe");
+      log("PIPEasp__PT::outgoing_send_PExecuteBackground exited");
+      return;
+  }
+  if (pipe(pipesStderr) != 0) {
+      sendError("Pipe Test Port: Cannot create stderr pipe");
+      log("PIPEasp__PT::outgoing_send_PExecuteBackground exited");
+      return;
+  }
+
+  processStdin = pipesStdin[1];
+  processStdout = pipesStdout[0];
+  processStderr = pipesStderr[0];
+
+  processPid = fork();
+  if (processPid < 0) {
+    //
+    // Error
+    //
+
+    // close the pipes
+    close(pipesStdin[0]);
+    close(pipesStdout[1]);
+    close(pipesStderr[1]);
+
+    close(processStdin);
+    close(processStdout);
+    close(processStderr);
+
+    sendError("Pipe Test Port: Cannot fork");
+  }
+  else if (processPid == 0) {
+
+      //
+      // Child process
+      //
+
+      // close the parent end of the pipes
+      close(processStdin);
+      close(processStdout);
+      close(processStderr);
+
+      /*// set these to the other end of the pipe
+      processStdin = pipesStdin[0];
+      processStdout = pipesStdout[1];
+      processStderr = pipesStderr[1];*/
+
+      int r;
+      // redirect pipeStdin to stdin
+      r = dup2(pipesStdin[0], 0);
+      if (r<0) {
+        TTCN_error("Cannot redirect stdin");
+        exit(errno);
+      }
+
+      // redirect pipeStdout to stdout
+      r = dup2(pipesStdout[1], 1);
+      if (r<0) {
+        TTCN_error("Cannot redirect stdout");
+        exit(errno);
+      }
+
+      // redirect pipeStderr to stderr
+      r = dup2(pipesStderr[1], 2);
+      if (r<0) {
+        TTCN_error("Cannot redirect stderr");
+        exit(errno);
+      }
+
+      processExitCode = execCommand((const char*)send_par.command());
+
+      // There is a problem executing the command
+      // Exiting...
+
+      fflush(stdout);
+      fflush(stderr);
+
+      //closing pipes:
+      close(pipesStdin[0]);
+      close(pipesStdout[1]);
+      close(pipesStderr[1]);
+
+      exit(processExitCode); // end of child process
+  }
+  else {
+
+    //
+    // Parent process
+    //
+
+    log("Process started with pid: %d", processPid);
+    // close child end of the pipes
+    close(pipesStdin[0]);
+    close(pipesStdout[1]);
+    close(pipesStderr[1]);
+
+
+    processExecuting = true;
+
+    // install handler for the process pipes:
+    //FD_SET(processStdin, &readfds);
+    FD_SET(processStdout, &readfds);
+    FD_SET(processStderr, &readfds);
+
+    Install_Handler(&readfds, NULL, NULL, 0.0);
+ }
+
+  log("PIPEasp__PT::outgoing_send_PExecuteBackground exited");
+}
+
+void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PStdin& send_par) {
+
+  log("PIPEasp__PT::outgoing_send_PStdin called");
+  binaryMode = false;
+  if (!processExecuting) {
+    sendError("Pipe Test Port: No command executing");
+    return;
+  }
+  if (disableSend) {  // process was started with PExecute(Binary)
+    sendError("Pipe Test Port: PStdin is not sent: current process is not started with PExecuteBackground!");
+    return;
+  }
+
+  log("will now write to stdin: '%s'",
+                (const char*)(send_par.stdin_()+((lineMode)?"\n":"")));
+  write(processStdin,
+       (const char*)(send_par.stdin_()+((lineMode)?"\n":"")),
+       send_par.stdin_().lengthof()+((lineMode)?1:0));
+
+  log("PIPEasp__PT::outgoing_send_PStdin exited");
+}
+
+void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PStdinBinary& send_par) {
+  log("PIPEasp__PT::outgoing_send_PStdinBinary called");
+  binaryMode = true;
+  if (!processExecuting) {
+    sendError("Pipe Test Port: No command executing");
+    return;
+  }
+  if (disableSend) {  // process was started with PExecute(Binary)
+    sendError("Pipe Test Port: PStdinBinary is not sent: current process is not started with PExecuteBackground!");
+    return;
+  }
+
+  TTCN_Logger::begin_event(TTCN_DEBUG);
+  TTCN_Logger::log_event("PIPE test port (%s): will now write binary data to stdin: ", get_name());
+  send_par.stdin_().log();
+  TTCN_Logger::end_event();
+
+  write(processStdin,
+       (const char*)(const unsigned char*)(send_par.stdin_()),
+       send_par.stdin_().lengthof());
+  log("PIPEasp__PT::outgoing_send_PStdinBinary exited");
+}
+
+void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PKill& send_par) {
+  log("PIPEasp__PT::outgoing_send_PKill called");
+  if (!processExecuting) {
+    // no process is running
+    log("No process executing.");
+    sendError("Pipe Test Port: No command executing");
+    log("PIPEasp__PT::outgoing_send_PKill exited");
+    return;
+  }
+
+  int signo = (int)send_par.signal();
+  if (signo<1 || signo>31) {
+    // signo out of range;
+    log("Signo out of range.");
+    sendError(
+      "Pipe Test port: Signal number should be "
+      "between 1 and 31");
+    log("PIPEasp__PT::outgoing_send_PKill exited");
+    return;
+  }
+  // killing process
+  log("Killing process %d, signo: %d", processPid, signo);
+  int r = kill(processPid, signo);
+  log("Kill process returned %d", r);
+  log("PIPEasp__PT::outgoing_send_PKill exited");
+}
+
+void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PLineMode& send_par) {
+  log("PIPEasp__PT::outgoing_send_PLineMode called");
+  lineMode = (bool)send_par.lineMode();
+  log("LineMode is set to %s", (lineMode)?"TRUE":"FALSE");
+  log("PIPEasp__PT::outgoing_send_PLineMode exited");
+}
+
+void PIPEasp__PT::outgoing_send(const PIPEasp__Types::ASP__PEndOfInput& /*send_par*/) {
+  log("PIPEasp__PT::outgoing_send_PEndOfInput called");
+  // close stdin pipe
+  close(processStdin);
+  processStdin = -1;
+  log("stdin closed");
+  log("PIPEasp__PT::outgoing_send_PEndOfInput exited");
+}
+
+/********************************
+* Execute the given command
+* returns the exitcode of the process
+*********************************/
+int PIPEasp__PT::execCommand(const char* command) {
+  log("PIPEasp__PT::execCommand called");
+  log("Executing command: %s", command);
+
+  // with this it is not possible to access the pid of the process
+  //return system(command);
+
+  int argc = 0;
+  char* argv[1024];
+
+  CHARSTRING temp(0, ""); // empty string
+  for (int i = 0; command[i] != 0; i++) {
+      if (isspace(command[i])) {
+         argv[argc++] = strdup(temp);
+          log("command argument added: %s", (const char*)temp);
+         while (command[i] != '0' && isspace(command[i])) i++;
+         i--;
+         temp = "";
+      } else {
+         temp = temp + CHARSTRING(1, command+i);
+      }
+  }
+
+  if (temp != "") {
+      argv[argc++] = strdup(temp);
+      log("command argument added: %s", (const char*)temp);
+  }
+
+  argv[argc++] = (char*)NULL;
+
+  log("execCommand(%s,%d)\n", argv[0], argc);
+  execvp(argv[0],argv);
+
+  fprintf(stderr,"Error executing command %s (%d): %s\n",
+    argv[0], errno, strerror(errno));
+  fflush(stderr);
+//  exit(errno);
+  return errno;
+}
+
+/***********************************
+* if the the child process died, gets
+* the exit code and sends it to TTCN
+* should be called when stdout/err are closed
+************************************/
+void PIPEasp__PT::handle_childDeath() {
+  log("Getting process status for pid %d...", processPid);
+  processExitCode = 0;  // reset the exitcode
+  int pid = wait(&processExitCode);
+  //waitpid(processPid,&processExitCode, 0);
+  if (pid!=processPid) {
+    log("other child died with pid: %d, exit code: %d", pid, processExitCode);
+    return;
+  }
+
+  log("Child process exit status is: %d", processExitCode);
+  // send code to TTCN:
+  sendExitCode();
+  // send result to TTCN
+  sendResult();
+
+  // removing fd-s installed for the process:
+  Uninstall_Handler(); // no handler is needed
+  FD_ZERO(&readfds);
+  /*
+  // equivalent with:
+  //FD_CLR(processStdin, &readfds);
+  FD_CLR(processStdout, &readfds);
+  FD_CLR(processStderr, &readfds);
+  Install_Handler(&readfds, NULL, NULL, 0.0);
+  */
+
+  // closing pipes:
+  close(processStdin);
+  //close(processStdout); // already closed
+  //close(processStderr); // already closed
+
+  processStdin = -1;
+  //processStdout = -1;
+  //processStderr = -1;
+
+  processExecuting = false;
+  disableSend = false;
+}
+
+/***************************
+* Send stdout msg to TTCN
+***************************/
+void PIPEasp__PT::sendStdout() {
+  if (disableSend) return;
+
+  PIPEasp__Types::ASP__PStdout message_PStdout;
+  PIPEasp__Types::ASP__PStdoutBinary message_PStdoutBinary;
+  if (lineMode && !binaryMode) {
+    // send complete lines from buffer
+    const unsigned char* pos = stdout_buffer.get_read_data();
+    for(unsigned int i=0; i<stdout_buffer.get_read_len(); i++) {
+      // not end of line:
+      if (pos[i] != '\n') {
+        continue;
+      }
+
+      // at end of line
+      // length of data is i (+1 is for \n and is not sent)
+      message_PStdout.stdout_() = CHARSTRING(i, (const char*)pos);
+
+      // send message
+      incoming_message(message_PStdout);
+
+      // remove the complete line from buffer,
+      // also set i and pos to the beginning of buffer
+      stdout_buffer.set_pos(i+1);
+      stdout_buffer.cut();
+      i = 0;
+      pos = stdout_buffer.get_read_data();
+    }
+  } else {
+    // lineMode false or binaryMode true
+    if (binaryMode) {
+      message_PStdoutBinary.stdout_() =
+        OCTETSTRING(stdout_buffer.get_read_len(), stdout_buffer.get_read_data());
+      stdout_buffer.clear();
+      incoming_message(message_PStdoutBinary);
+    }
+    else {
+      message_PStdout.stdout_() =
+        CHARSTRING(stdout_buffer.get_read_len(), (const char*)stdout_buffer.get_read_data());
+      stdout_buffer.clear();
+      incoming_message(message_PStdout);
+    }
+//    incoming_message(message);
+  }
+}
+
+
+/***************************
+* Send stderr msg to TTCN
+***************************/
+void PIPEasp__PT::sendStderr() {
+  if (disableSend) return;
+
+  PIPEasp__Types::ASP__PStderr message_PStderr;
+  PIPEasp__Types::ASP__PStderrBinary message_PStderrBinary;
+  if (lineMode && !binaryMode) {
+    // send complete lines from buffer
+    const unsigned char* pos = stderr_buffer.get_read_data();
+    for(unsigned int i=0; i<stderr_buffer.get_read_len(); i++) {
+      // not end of line:
+      if (pos[i] != '\n') {
+        continue;
+      }
+
+      // at end of line
+      // length of data is i (+1 is for \n and is not sent)
+      message_PStderr.stderr_() = CHARSTRING(i, (const char*)pos);
+
+      // send message
+      incoming_message(message_PStderr);
+
+      // remove the complete line from buffer,
+      // also set i and pos to the beginning of buffer
+      stderr_buffer.set_pos(i+1);
+      stderr_buffer.cut();
+      i = 0;
+      pos = stderr_buffer.get_read_data();
+    }
+  } else {
+    // lineMode false or binaryMode true
+    if (binaryMode) {
+      message_PStderrBinary.stderr_() =
+        OCTETSTRING(stderr_buffer.get_read_len(), stderr_buffer.get_read_data());
+      stderr_buffer.clear();
+      incoming_message(message_PStderrBinary);
+    }
+    else {
+      message_PStderr.stderr_() =
+        CHARSTRING(stderr_buffer.get_read_len(), (const char*)stderr_buffer.get_read_data());
+      stderr_buffer.clear();
+      incoming_message(message_PStderr);
+    }
+//    incoming_message(message);
+  }
+}
+
+
+/***************************
+* Send exitcode msg to TTCN
+***************************/
+void PIPEasp__PT::sendExitCode() {
+  if (disableSend) return;
+
+  log("Sending ExitCode to TTCN");
+  PIPEasp__Types::ASP__PExit message_PExit;
+  message_PExit.code() = processExitCode;
+  incoming_message(message_PExit);
+}
+
+
+/***************************
+* Send error msg to TTCN
+***************************/
+void PIPEasp__PT::sendError(const char* error_msg) {
+  PIPEasp__Types::ASP__PError message_PError;
+  message_PError.errorMessage() = error_msg;
+  incoming_message(message_PError);
+}
+
+
+/***************************
+* Send Result msg to TTCN
+***************************/
+void PIPEasp__PT::sendResult() {
+  if (!disableSend) return; // do not send result if process was started by PExecuteBackground
+
+  log("Sending result to TTCN...");
+  PIPEasp__Types::ASP__PResult message_PResult;
+  PIPEasp__Types::ASP__PResultBinary message_PResultBinary;
+  if (binaryMode) {
+    message_PResultBinary.stdout_() =
+     OCTETSTRING(stdout_buffer.get_read_len(), stdout_buffer.get_read_data());
+    message_PResultBinary.stderr_() =
+     OCTETSTRING(stderr_buffer.get_read_len(), stderr_buffer.get_read_data());
+    message_PResultBinary.code() = processExitCode;
+    incoming_message(message_PResultBinary);
+  } else {
+    int messageLen = stdout_buffer.get_read_len();
+    const char* messageData = (const char*)stdout_buffer.get_read_data();
+
+    if (lineMode && messageData[messageLen-1]=='\n') {
+      messageLen--; // remove newline from the end
+    }
+
+    message_PResult.stdout_() = CHARSTRING(messageLen, messageData);
+
+    messageLen = stderr_buffer.get_read_len();
+    messageData = (const char*)stderr_buffer.get_read_data();
+
+    if (lineMode && messageData[messageLen-1]=='\n') {
+      messageLen--; // remove newline from the end
+    }
+
+    message_PResult.stderr_() = CHARSTRING(messageLen, messageData);
+    message_PResult.code() = processExitCode;
+    incoming_message(message_PResult);
+  }
+
+  // clearing the buffers
+  stdout_buffer.clear();
+  stderr_buffer.clear();
+  //incoming_message(message);
+}
+
+
+////////////////
+// Log function
+////////////////
+void PIPEasp__PT::log(const char *fmt, ...)
+{
+  TTCN_Logger::begin_event(TTCN_DEBUG);
+  TTCN_Logger::log_event("PIPE test port (%s): ", get_name());
+  va_list ap;
+  va_start(ap, fmt);
+  TTCN_Logger::log_event_va_list(fmt, ap);
+  va_end(ap);
+  TTCN_Logger::end_event();
+}
+
+}//namespace
diff --git a/regression_test/profiler/PIPEasp_PT.hh b/regression_test/profiler/PIPEasp_PT.hh
new file mode 100644 (file)
index 0000000..df76240
--- /dev/null
@@ -0,0 +1,106 @@
+/*******************************************************************************
+* 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
+*
+* Contributors:
+*     Zoltan Janos Szabo (Ericsson) - initial architecture design and implementation
+*     Roland Gecse (Ericsson) - initial architecture design
+*     Akos Cserveni (Ericsson) - Basic AST in compiler, semantic checking
+*     Gabor Szalai (Ericsson) â€“ RAW and TEXT codecs
+*     Matyas Forstner (Ericsson) - ASN.1 extension of the compiler and BER/CER/DER codecs
+*     Kristof Szabados  (Ericsson) - Eclipse Designer, Executor, Titanium UIs
+*     Szabolcs Beres (Ericsson) - Eclipse LogViewer
+*     Ferenc Kovacs (Ericsson) â€“ log interfaces, big number support, subtype checking
+*     Csaba Raduly (Ericsson) â€“ ASN.1 additions, XML encoder/decoder
+*     Adam Delic (Ericsson) â€“ template restrictions, try&catch, support of pre-processor directives in Eclipse
+*     Krisztian Pandi (Ericsson) â€“ import of imports
+*     Peter Dimitrov (Ericsson)- maintenance
+*     Balazs Andor Zalanyi (Ericsson) â€“ code splitting
+*     Gabor Szalai (Ericsson) â€“ RAW encoding/decoding
+*     Jeno Attila Balasko (Ericsson) â€“ tests
+*     Csaba Feher (Ericsson) â€“ epoll support
+*     Tamas Buti (Ericsson)- maintenance
+*     Matyas Ormandi (Ericsson) - maintenance
+*     Botond Baranyi (Ericsson) - JSON encoder
+*     Arpad Lovassy (Ericsson) - Java Executor API
+*     Laszlo Baji (Ericsson) - maintenance
+*     Marton Godar (Ericsson) - xsd2ttcn converter
+*******************************************************************************/
+//
+//  File:               PIPEasp_PT.hh
+//  Description:        Header file of PIPE testport implementation
+//  Rev:                <RnXnn>
+//  Prodnr:             CNL 113 334
+//  Updated:            2008-06-03
+//  Contact:            http://ttcn.ericsson.se
+//
+
+
+#ifndef PIPEasp__PT_HH
+#define PIPEasp__PT_HH
+
+#include "PIPEasp_PortType.hh"
+
+namespace PIPEasp__PortType {
+
+class PIPEasp__PT : public PIPEasp__PT_BASE {
+public:
+       PIPEasp__PT(const char *par_port_name = NULL);
+       ~PIPEasp__PT();
+
+       void set_parameter(const char *parameter_name,
+               const char *parameter_value);
+
+       void Event_Handler(const fd_set *read_fds,
+               const fd_set *write_fds, const fd_set *error_fds,
+               double time_since_last_call);
+
+protected:
+       void user_map(const char *system_port);
+       void user_unmap(const char *system_port);
+
+       void user_start();
+       void user_stop();
+
+       void outgoing_send(const PIPEasp__Types::ASP__PExecute& send_par);
+       void outgoing_send(const PIPEasp__Types::ASP__PExecuteBinary& send_par);
+       void outgoing_send(const PIPEasp__Types::ASP__PExecuteBackground& send_par);
+       void outgoing_send(const PIPEasp__Types::ASP__PStdin& send_par);
+       void outgoing_send(const PIPEasp__Types::ASP__PStdinBinary& send_par);
+       void outgoing_send(const PIPEasp__Types::ASP__PKill& send_par);
+       void outgoing_send(const PIPEasp__Types::ASP__PLineMode& send_par);
+       void outgoing_send(const PIPEasp__Types::ASP__PEndOfInput& send_par);
+private:
+        int execCommand(const char* command);
+        void handle_childDeath();
+        void sendStdout();
+        void sendStderr();
+        void sendExitCode();
+        void sendResult();
+        void sendError(const char* error_msg);
+        void log(const char *fmt, ...);
+
+private:
+  bool lineMode; // true if lineMode is enabled
+  bool processExecuting; // true if process is executing: disable new processes
+  bool binaryMode; // true if result should be returned in as binary data
+  bool disableSend; // if true sendStdout/err is disabled
+
+  fd_set readfds;     // fd set for event handler
+  int processPid;     // pid of the process currently executing
+  int processStdin;   // fd of stdin of the process
+  int processStdout;  // fd of stdout of the process
+  int processStderr;  // fd of stderr of the process
+
+  TTCN_Buffer stdout_buffer; // data sent to stdout 
+  TTCN_Buffer stderr_buffer; // data sent to stderr
+  int processExitCode;       // exit code of the process
+
+};
+
+}//namespace
+
+#endif
diff --git a/regression_test/profiler/PIPEasp_PortType.ttcn b/regression_test/profiler/PIPEasp_PortType.ttcn
new file mode 100644 (file)
index 0000000..1d43b6f
--- /dev/null
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * 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
+ ******************************************************************************/
+//
+//  File:         PIPEasp_PortType.ttcn
+//  Reference:    Based on SCS PIPE Testport 
+//  Rev:          <RnXnn>
+//  Prodnr:       CNL 113 334
+//  Updated:      2008-06-03
+//  Contact:      http://ttcn.ericsson.se
+
+module PIPEasp_PortType
+{
+
+  import from PIPEasp_Types all;
+// *************************************************************************
+// *  PIPE port type definitions                                           *
+// *************************************************************************
+
+  // system PIPE port type
+  type port PIPEasp_PT message
+  {
+    out ASP_PExecute,
+        ASP_PExecuteBinary,
+        ASP_PExecuteBackground,
+        ASP_PStdin,
+        ASP_PStdinBinary,
+        ASP_PKill,
+        ASP_PLineMode,
+        ASP_PEndOfInput;
+
+    in  ASP_PResult,
+        ASP_PResultBinary,
+        ASP_PStdout,
+        ASP_PStderr,
+        ASP_PStdoutBinary,
+        ASP_PStderrBinary,
+        ASP_PExit,
+        ASP_PError;
+  }
+
+}//eof module
diff --git a/regression_test/profiler/PIPEasp_Templates.ttcn b/regression_test/profiler/PIPEasp_Templates.ttcn
new file mode 100644 (file)
index 0000000..988bd48
--- /dev/null
@@ -0,0 +1,93 @@
+/******************************************************************************
+ * 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
+ ******************************************************************************/
+module PIPEasp_Templates {
+
+import from PIPEasp_Types all;
+
+template ASP_PKill t_PKill(template integer signo)  := {
+  signal := signo
+}
+
+template ASP_PError t_PError(template charstring msg)  := {
+  errorMessage := msg
+}
+
+template ASP_PLineMode t_PLineMode(template boolean p_lineMode)  := {
+  lineMode := p_lineMode
+}
+
+template ASP_PResult t_PResult(
+    template charstring p_stdout,
+    template charstring p_stderr,
+    template integer    p_code)  := {
+    stdout := p_stdout,
+    stderr := p_stderr,
+    code   := p_code
+}
+
+template ASP_PResultBinary t_PResultBinary(
+    template octetstring p_stdout,
+    template octetstring p_stderr,
+    template integer    p_code)  := {
+    stdout := p_stdout,
+    stderr := p_stderr,
+    code   := p_code
+}
+
+template ASP_PStdin t_PStdin(
+    template charstring p_stdin)  := {
+  stdin := p_stdin
+}
+
+template ASP_PStdinBinary t_PStdinBinary(
+    template octetstring p_stdinBinary)  := {
+  stdin := p_stdinBinary
+}
+
+template ASP_PStdout t_PStdout(
+    template charstring p_stdout)  := {
+    stdout := p_stdout
+}
+
+template ASP_PStderr t_PStderr(
+    template charstring p_stderr)  := {
+    stderr := p_stderr
+}
+
+template ASP_PStdoutBinary t_PStdoutBinary(
+    template octetstring p_stdout)  := {
+    stdout := p_stdout
+}
+
+template ASP_PStderrBinary t_PStderrBinary(
+    template octetstring p_stderr)  := {
+    stderr := p_stderr
+}
+
+template ASP_PExecuteBackground t_PExecuteBackground(
+    template charstring p_command)  := {
+  command := p_command
+}
+
+template ASP_PExit t_PExit(template integer p_code)  := {
+  code := p_code
+}
+
+template ASP_PExecute t_PExecute(
+    template charstring p_command, template charstring p_stdin)  := {
+    command := p_command,
+    stdin := p_stdin
+}
+
+template ASP_PExecuteBinary t_PExecuteBinary(
+    template charstring p_command, template octetstring p_stdin)  := {
+    command := p_command,
+    stdin := p_stdin
+}
+
+} // end of module
diff --git a/regression_test/profiler/PIPEasp_Types.ttcn b/regression_test/profiler/PIPEasp_Types.ttcn
new file mode 100644 (file)
index 0000000..da8ea94
--- /dev/null
@@ -0,0 +1,180 @@
+/******************************************************************************
+ * 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
+ ******************************************************************************/
+//
+//  File:         PIPEasp_Types.ttcn
+//  Description:  PIPE (ASP) definitions
+//  Reference:    Based on SCS PIPE testport
+//  Rev:          <RnXnn>
+//  Prodnr:       CNL 113 334
+//  Updated:      2008-06-03
+//  Contact:      http://ttcn.ericsson.se
+//
+
+module PIPEasp_Types
+{//start of the module
+
+// *************************************************************************
+// *  Type Definitions Part                                                *
+// *************************************************************************
+
+// This ASP can be used to execute the given command with given standard input.
+// The PResult ASP is sent as an answer, unless there is already a process
+// executing which results in the ASP PError being sent.
+//
+// This ASP can only be sent from the test suite: $DIRECTION OUT
+  type record ASP_PExecute {
+    charstring command,
+    charstring stdin
+  };
+
+// This ASP is sent as an answer to the PExecute ASP. It provides
+// information about the standard output and error of the executed command,
+// as well as the exit code of the command.
+// 
+// This ASP can only be received by the test suite: $DIRECTION IN
+  type record ASP_PResult {
+    charstring stdout,
+    charstring stderr,
+    integer    code
+  };
+  
+// This ASP is similar to the PExecute ASP, except that binary data is
+// sent instead of a string as the contents of standard input. This means that
+// the data can be, for instance, the encode form of a PDU.
+// 
+// This ASP can only be sent from the test suite: $DIRECTION OUT
+  type record ASP_PExecuteBinary {
+    charstring  command,
+    octetstring stdin
+  };
+  
+// This ASP is similar to the PResult ASP, except that the outputs are
+// given as binary data.
+// 
+// This ASP can only be received by the test suite: $DIRECTION IN
+  type record ASP_PResultBinary {
+    octetstring stdout,
+    octetstring stderr,
+    integer     code
+  };
+  
+// This ASP can be used to start a background process with the command
+// given in the parameters. The PStdin, PStdinBinary, PStdout, PStdoutBinary,
+// PStderr, and PStderrBinary ASPs can then be used to send and receive input
+// and output to and from the process.
+// 
+// This ASP can only be sent by the test suite: $DIRECTION OUT
+  type record ASP_PExecuteBackground {
+    charstring command
+  };
+
+// This ASP sends input to the process started with PExecuteBackground.
+// After the usage of the PStdin ASP, all outputs are sent back to the
+// test suite by the PStdout and PStderr ASPs.
+// 
+// This ASP can only be sent by the test suite: $DIRECTION OUT
+  type record ASP_PStdin {
+    charstring stdin
+  };
+
+// This ASP is sent to the test suite when the background process started
+// by PExecuteBackground outputs something to its standard output.
+// 
+// This ASP can only be received by the test suite: $DIRECTION IN
+  type record ASP_PStdout {
+    charstring stdout
+  };
+  
+// This ASP is sent to the test suite when the background process started
+// by PExecuteBackground outputs something to its standard error.
+// 
+// This ASP can only be received by the test suite: $DIRECTION IN
+  type record ASP_PStderr {
+    charstring stderr
+  };
+
+// This ASP is similar to the PStdin ASP, except that the inputs are in
+// binary format. After sending this ASP, all the outputs produced by the
+// background process are sent back to the test suite in the PStdoutBinary
+// and PStderrBinary ASPs.
+// 
+// This ASP can only be sent by the test suite: $DIRECTION OUT
+  type record ASP_PStdinBinary {
+    octetstring stdin
+  };
+
+// This ASP is similar to PStdout, except that it carries binary data.
+// 
+// This ASP can only be received by the test suite: $DIRECTION IN
+  type record ASP_PStdoutBinary {
+    octetstring stdout
+  };
+
+// This ASP is similar to PStderr, except that it carries binary data.
+// 
+// This ASP can only be received by the test suite: $DIRECTION IN
+  type record ASP_PStderrBinary {
+    octetstring stderr
+  };
+
+// This ASP can be used to send a signal to the process started by
+// PExecuteBackground. The parameter value is the signal number.
+// 
+// This ASP can only be sent by the test suite: $DIRECTION OUT
+  type record ASP_PKill {
+    integer signal
+  };
+
+// This ASP informs the test suite about the death of the process started
+// by PExecuteBackground. The parameter value is the exit code of the process.
+// 
+// This ASP can only be received by the test suite: $DIRECTION IN
+  type record ASP_PExit {
+    integer code
+  };
+
+// This ASP determines the meaning of the strings representing the standard
+// input, output, and error in the ASPs PExecute, PResult, PStdin, PStdout,
+// and PStderr.  In the first two ASPs, it determines if a newline is added to
+// the end of the inputs and a newline is taken away from the end of the outputs.
+// TRUE determines that these changes take place, and FALSE that they do not.
+// 
+// In the three other ASPs, TRUE means that a newline is added to the end of
+// each input string, and that the outputs are sent in separate ASPs each
+// containing only one line of text (without the newline).
+// 
+// By default, the PIPE test port functions as if the PLineMode ASP would have
+// been sent with the parameter values TRUE.
+// 
+// This ASP can only be sent by the test suite: $DIRECTION OUT
+  type record ASP_PLineMode {
+    boolean lineMode
+  };
+
+// This ASP is sent to the test suite when the PIPE test port is used
+// in a wrong manner.
+// 
+// This ASP can only be received by the test suite: $DIRECTION IN
+  type record ASP_PError {
+    charstring errorMessage
+  };
+
+// This ASP can be used to notify the test port that the end of input
+// is reached. Makes sense for processes started by PExecuteBackground.
+// After this ASP is sent to the background process no more input can be sent
+// to its stdin using PStdin(Binary)
+// Note, that for processes started by PExecute(Binary) the input is
+// closed automatically.
+// 
+// This ASP can only be sent by the test suite: $DIRECTION OUT
+  type record ASP_PEndOfInput {
+  };
+
+}//end module
+
+
diff --git a/regression_test/profiler/Shell.ttcn b/regression_test/profiler/Shell.ttcn
new file mode 100644 (file)
index 0000000..0db58a1
--- /dev/null
@@ -0,0 +1,244 @@
+/******************************************************************************
+ * 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
+ ******************************************************************************/
+
+module Shell
+{
+
+import from PIPEasp_Types all;
+import from PIPEasp_PortType all;
+import from PIPEasp_Templates all;
+
+
+modulepar float tsp_shellCmdTimeout := 20.0;
+
+type component PIPE_CT {
+  port PIPEasp_PT PIPE_PCO;
+  var ASP_PExecute v_ASP_PExecute;
+  var ASP_PResult v_ASP_PResult;
+  var ASP_PExecuteBinary v_ASP_PExecuteBinary;
+  var ASP_PResultBinary v_ASP_PResultBinary;
+  var ASP_PExecuteBackground v_ASP_PExecuteBackground;
+  var ASP_PStdin v_ASP_PStdin;
+  var ASP_PStdout v_ASP_PStdout;
+  var ASP_PStderr v_ASP_PStderr;
+  var ASP_PStdinBinary v_ASP_PStdinBinary;
+  var ASP_PStdoutBinary v_ASP_PStdoutBinary;
+  var ASP_PStderrBinary v_ASP_PStderrBinary;
+  var ASP_PKill v_ASP_PKill;
+  var ASP_PExit v_ASP_PExit;
+  var ASP_PLineMode v_ASP_PLineMode;
+  var ASP_PError v_ASP_PError;
+}
+
+type component Shell_CT extends PIPE_CT {
+    var boolean v_initialized:=false;
+}
+
+type component mtc_CT {}
+
+//=========================================================================
+// Constants
+//=========================================================================
+
+const integer c_shell_successWithoutWarningAndError:=0;
+const integer c_shell_success := 0;
+const integer c_shell_successWithWarning:=1; //temp until licence is solved
+const integer c_shell_error:=256;
+const integer c_shell_error_noSuchFileOrDirectory:=512;
+
+//Expected and accepted diffs:
+// Line "Copyright Ericsson AB 2013"        - 4 diffs
+// Line "XSD to TTCN-3 Translator version:" - 4 diffs
+// Line "File"                              - 4 diffs
+// Line "Updated: "                         - 4 diffs
+// Line "module www_"                       - 4 diffs
+// Line "ETSI ES 201 873-9 V4.1.2"          - 2 diffs ???? << Fix it !
+// Line "variant \"namespace as"            - 4 diffs
+// Script counts the strings "\n" thus N different lines mean N-1 numOfDiff
+//Possible values: 19,21,23,25 but 21 and 25 should be eliminated!
+
+const integer c_numOfDiff_headerAndModuleName := 19;
+const integer c_numOfDiff_headerModNameAndNamespace := 23;
+const integer c_numOfDiff_headerModNameAndImport := 23;
+
+function f_countDelimiters(in charstring pl_string, in charstring pl_delimiter, inout integer pl_counter) {
+  pl_counter:=0;
+  var integer pos:=0;
+  var integer vl_size:=lengthof(pl_string);
+  var integer vl_delimsize:=lengthof(pl_delimiter);
+  while(pos<vl_size) {
+    if( substr(pl_string,pos,vl_delimsize)==pl_delimiter) { pl_counter:=pl_counter+1}
+    pos:=pos+1;
+  }
+}//f_
+
+//=========================================================================
+// f_compareFiles
+//=========================================================================
+//pl_diffLimit: upper limit of acceptable diff lines. 4 means one acceptable difference
+function f_compareFiles(in charstring pl_file1, in charstring pl_file2, in integer pl_diffLimit) runs on Shell_CT {
+  var integer vl_expectedResult:=0
+  if(pl_diffLimit>0) { vl_expectedResult:=256; }
+  var boolean vl_success:=false;
+  f_shell_command("diff -w " & pl_file1  & " " & pl_file2,"",vl_expectedResult,vl_success);
+
+  if(v_ASP_PResult.code==0)
+  {
+    setverdict(pass);
+  }
+  else if(v_ASP_PResult.code==256) {
+    var integer vl_counter:=0;
+    f_countDelimiters(v_ASP_PResult.stdout,"\n",vl_counter);
+    log("Counted lines: ",vl_counter, " diffLimit: ", pl_diffLimit)
+    if(vl_counter>pl_diffLimit) {
+      setverdict(fail);
+    }
+  } else { //e.g 512: No such file or directory
+    log("Wrong result code: ",v_ASP_PResult.code, " Expected result code: ", vl_expectedResult)
+    setverdict(fail);
+  }
+}//f_
+
+
+//********* SHELL Functions ***********************
+
+//=========================================================================
+// f_shell_init
+//=========================================================================
+function f_shell_init() runs on Shell_CT {
+  if(v_initialized) { return; }
+  map(self:PIPE_PCO, system:PIPE_PCO);
+  v_initialized:=true;
+}
+
+//=========================================================================
+// f_shell_cleanup
+//=========================================================================
+function f_shell_cleanup() runs on Shell_CT {
+  if(not v_initialized) { return; }
+  unmap(self:PIPE_PCO, system:PIPE_PCO);
+  v_initialized:=false;
+}
+//=========================================================================
+// f_setverdictfromBool
+//=========================================================================
+function f_setverdictfromBool(in boolean pl_result, in boolean pl_expected_result:=true) {
+  if(pl_result==pl_expected_result) {
+    setverdict(pass);
+  }else{
+    setverdict(fail);
+  }
+  return;
+}
+//=========================================================================
+//  f_shell_validateXml
+//  Compares pl_xmlFileContent (e.g encoding result) against pl_xsdFileName
+//=========================================================================
+function f_shell_validateXml(in octetstring pl_xmlFileContent, in charstring pl_xsdFileName, in integer pl_expected_result, inout boolean pl_success)
+runs on Shell_CT
+{
+  f_shell_command( "xmllint --noout --schema " & pl_xsdFileName & " - ",oct2char(pl_xmlFileContent), pl_expected_result, pl_success);
+}
+
+
+//=========================================================================
+//  f_shell_command
+//=========================================================================
+function f_shell_command(in charstring pl_command, in charstring pl_stdin, in integer pl_expected_result, inout boolean pl_success)
+runs on Shell_CT
+{
+  f_shell_init();
+
+  var integer vl_expectedCode:=-1;
+  if(pl_expected_result==c_shell_successWithoutWarningAndError or
+    pl_expected_result==c_shell_successWithWarning) {
+    vl_expectedCode:=0
+  } else {
+    vl_expectedCode:= pl_expected_result;
+  }
+
+  log("Running: ", pl_command);
+  PIPE_PCO.send(t_PExecute(pl_command,pl_stdin));
+
+  timer t:=tsp_shellCmdTimeout;
+  t.start;
+  pl_success:=false;
+
+  alt {
+
+    [] PIPE_PCO.receive(t_PResult(?, ?, ?)) -> value v_ASP_PResult {
+        log("PResult msg received: ", v_ASP_PResult);
+
+        if(v_ASP_PResult.code==vl_expectedCode ) {
+          var charstring vl_pattern:="";
+          select(pl_expected_result) {
+            case(c_shell_successWithWarning) {
+              vl_pattern:="*(Warning|WARNING|warning)*";
+              if(regexp(v_ASP_PResult.stderr,vl_pattern,0)!=""){
+                log("That is an expected Warning!")
+                pl_success:=true;
+              } else {
+                log("No Warning in the stderr string but expected");
+                pl_success:=false;
+              }
+            }
+            case(c_shell_successWithoutWarningAndError) {
+              vl_pattern:="*(Error|ERROR|error)*";
+              if(regexp(v_ASP_PResult.stderr,vl_pattern,0)!=""){
+                log("That is an unexpected Error!")
+                pl_success:=false;
+              } else {
+                log("No Error in the stderr string");
+                pl_success:=true;
+              }
+              vl_pattern:="*(Warning|WARNING)*";
+              if(regexp(v_ASP_PResult.stderr,vl_pattern,0)!=""){
+                log("That is an unexpected Warning!")
+                pl_success:=false;
+              } else {
+                log("No Warning in the stderr string");
+                pl_success:=true;
+              }
+            }//case
+            case(c_shell_error) {
+              log("Command returned with ERROR as expected");
+              pl_success:=true;
+            }
+            case(c_shell_error_noSuchFileOrDirectory) {
+              log("Command returned with No such file or directory as expected");
+              pl_success:=true;
+            }
+            case else {
+              log("Other case");
+              pl_success:=false;
+            }
+          }//select
+        } else {
+          log("The result code(", v_ASP_PResult.code, ") is not the expected(", vl_expectedCode, ")");
+          pl_success:=false;
+        }//if
+      }
+    [] t.timeout {
+        pl_success:=false;
+      }
+  }//alt
+
+  f_shell_cleanup();
+  return;
+}//f_shell_command
+//=========================================================================
+//  Name: f_shellCommandWithVerdict
+//  Description: sets verdict for pass, if the command execution returns with the expected value
+//=========================================================================
+function f_shellCommandWithVerdict(in charstring pl_command, in charstring pl_stdin, in integer pl_expected_result) runs on Shell_CT {
+  var boolean vl_success:=false;
+  f_shell_command(pl_command, pl_stdin, pl_expected_result, vl_success);
+  f_setverdictfromBool(vl_success)
+}
+
+}  // end of module
diff --git a/regression_test/profiler/Testcases.ttcn b/regression_test/profiler/Testcases.ttcn
new file mode 100644 (file)
index 0000000..67765a5
--- /dev/null
@@ -0,0 +1,74 @@
+/******************************************************************************
+ * Copyright (c) 2000-2015 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
+ ******************************************************************************/
+
+module Testcases {
+
+import from Shell all;
+
+type record of charstring CharstringList;
+
+function f_test_profiler(in charstring p_target_file, in charstring p_config_file,
+  in CharstringList p_output_files, in CharstringList p_exp_output_files) runs on Shell_CT
+{
+  // make the target (the makefile must have a rule for it)
+  f_shellCommandWithVerdict("make " & p_target_file, "", c_shell_successWithoutWarningAndError);
+
+  if (getverdict == pass) {
+    // run the executable with the specified configuration file
+    f_shellCommandWithVerdict("ttcn3_start " & p_target_file & " " & p_config_file, "",
+      c_shell_successWithoutWarningAndError);
+    
+    if (getverdict == pass) {
+      // compare the output files
+      var integer i;
+      for (i := 0; i < sizeof(p_output_files); i := i + 1) {
+        f_compareFiles(p_output_files[i], p_exp_output_files[i], 0);
+        if (getverdict != pass) {
+          action("Output file '" & p_output_files[i] & "' does not match the expected file '" &
+            p_exp_output_files[i] & "'");
+        }
+      }
+    }
+    else {
+      action("Failed to run target '", p_target_file, "', with configuration file '", p_config_file, "'");
+    }
+  }
+  else {
+    action("Failed to make target '", p_target_file, "'");
+  }
+}
+
+testcase tc_coverage() runs on Shell_CT
+{
+  // only code coverage is done in this case, since that is exact, and the results can be checked with
+  // a simple file comparison
+  f_test_profiler("prof.exe", "prof1.cfg", { "data.json", "prof1.stats" }, { "data_e.json", "prof1_e.stats" } );
+}
+
+testcase tc_profiling() runs on Shell_CT
+{
+  // only profiling is done in this case
+  // the results cannot be checked, since the call times will vary in each run
+  f_test_profiler("prof.exe", "prof2.cfg", { }, { } );
+}
+
+testcase tc_profiling_and_coverage() runs on Shell_CT
+{
+  // both profiling and code coverage is activated in this case
+  // although the call times cannot be checked, the statistics filter is set to generate an 
+  // empty statistics file, which can be cheked
+  f_test_profiler("prof.exe", "prof3.cfg", { "empty.stats" }, { "empty_e.stats" } );
+}
+
+control {
+  execute(tc_coverage());
+  execute(tc_profiling());
+  execute(tc_profiling_and_coverage());
+}
+
+}
diff --git a/regression_test/profiler/data_e.json b/regression_test/profiler/data_e.json
new file mode 100644 (file)
index 0000000..4a1737e
--- /dev/null
@@ -0,0 +1,226 @@
+[
+       {
+               "file" : "prof1.ttcn",
+               "functions" : [
+                       {
+                               "name" : "f1",
+                               "start line" : 15,
+                               "execution count" : 3,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "name" : "tc1",
+                               "start line" : 19,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       }
+               ],
+               "lines" : [
+                       {
+                               "number" : 13,
+                               "execution count" : 3,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 15,
+                               "execution count" : 3,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 16,
+                               "execution count" : 3,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 19,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 20,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 21,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 22,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 23,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       }
+               ]
+       },
+       {
+               "file" : "prof2.ttcn",
+               "functions" : [
+                       {
+                               "name" : "f2",
+                               "start line" : 13,
+                               "execution count" : 2,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "name" : "t1",
+                               "start line" : 22,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "name" : "tc2",
+                               "start line" : 24,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       }
+               ],
+               "lines" : [
+                       {
+                               "number" : 13,
+                               "execution count" : 2,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 14,
+                               "execution count" : 2,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 18,
+                               "execution count" : 2,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 22,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 24,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 25,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 26,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 27,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 28,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 29,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       }
+               ]
+       },
+       {
+               "file" : "prof3.ttcn",
+               "functions" : [
+                       {
+                               "name" : "f3",
+                               "start line" : 14,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "name" : "tc3",
+                               "start line" : 21,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "name" : "control",
+                               "start line" : 31,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       }
+               ],
+               "lines" : [
+                       {
+                               "number" : 14,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 16,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 17,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 18,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 21,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 23,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 24,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 25,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 26,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 27,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 28,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 31,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       },
+                       {
+                               "number" : 32,
+                               "execution count" : 1,
+                               "total time" : 0.000000
+                       }
+               ]
+       }
+]
diff --git a/regression_test/profiler/empty_e.stats b/regression_test/profiler/empty_e.stats
new file mode 100644 (file)
index 0000000..bab3ec0
--- /dev/null
@@ -0,0 +1,5 @@
+##################################################
+## TTCN-3 profiler and code coverage statistics ##
+##################################################
+
+
diff --git a/regression_test/profiler/prof1.cfg b/regression_test/profiler/prof1.cfg
new file mode 100644 (file)
index 0000000..9e2e50f
--- /dev/null
@@ -0,0 +1,22 @@
+###############################################################################
+# Copyright (c) 2000-2015 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
+###############################################################################
+[EXECUTE]
+prof1.tc1
+prof2.tc2
+prof3.control
+[PROFILER]
+DisableProfiler := true
+DisableCoverage := false
+DatabaseFile := "data.json"
+AggregateData := false
+StatisticsFile := "prof1.stats"
+DisableStatistics := false
+StatisticsFilter := NumberOfLines & AllRawData & UnusedData
+[LOGGING]
+SourceInfoFormat := Stack
+LogEntityName := Yes
diff --git a/regression_test/profiler/prof1.ttcn b/regression_test/profiler/prof1.ttcn
new file mode 100644 (file)
index 0000000..d37cc3e
--- /dev/null
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright (c) 2000-2015 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
+ ******************************************************************************/
+
+module prof1 {
+
+type component C {}
+
+const integer c1 := 7;
+
+function f1(inout integer x) runs on C {
+  x := x + c1;
+}
+
+testcase tc1() runs on C {
+  var integer x := 6;
+  f1(x);
+  log(x);
+  x := x + 1;
+}
+
+control {
+  execute(tc1());
+}
+
+}
diff --git a/regression_test/profiler/prof1_e.stats b/regression_test/profiler/prof1_e.stats
new file mode 100644 (file)
index 0000000..ef1d5b0
--- /dev/null
@@ -0,0 +1,84 @@
+##################################################
+######### TTCN-3 code coverage statistics ########
+##################################################
+
+
+--------------------------------------
+- Number of code lines and functions -
+--------------------------------------
+prof1.ttcn:    10 lines,       3 functions
+prof2.ttcn:    13 lines,       4 functions
+prof3.ttcn:    13 lines,       3 functions
+--------------------------------------
+Total: 36 lines,       10 functions
+
+-------------------------------------------------
+-------- Code line data (execution count) -------
+-------------------------------------------------
+3      prof1.ttcn:13
+3      prof1.ttcn:15 [f1]
+3      prof1.ttcn:16
+1      prof1.ttcn:19 [tc1]
+1      prof1.ttcn:20
+1      prof1.ttcn:21
+1      prof1.ttcn:22
+1      prof1.ttcn:23
+-------------------------------------------------
+2      prof2.ttcn:13 [f2]
+2      prof2.ttcn:14
+2      prof2.ttcn:18
+1      prof2.ttcn:22 [t1]
+1      prof2.ttcn:24 [tc2]
+1      prof2.ttcn:25
+1      prof2.ttcn:26
+1      prof2.ttcn:27
+1      prof2.ttcn:28
+1      prof2.ttcn:29
+-------------------------------------------------
+1      prof3.ttcn:14 [f3]
+1      prof3.ttcn:16
+1      prof3.ttcn:17
+1      prof3.ttcn:18
+1      prof3.ttcn:21 [tc3]
+1      prof3.ttcn:23
+1      prof3.ttcn:24
+1      prof3.ttcn:25
+1      prof3.ttcn:26
+1      prof3.ttcn:27
+1      prof3.ttcn:28
+1      prof3.ttcn:31 [control]
+1      prof3.ttcn:32
+
+------------------------------------------------
+-------- Function data (execution count) -------
+------------------------------------------------
+3      prof1.ttcn:15 [f1]
+1      prof1.ttcn:19 [tc1]
+------------------------------------------------
+2      prof2.ttcn:13 [f2]
+1      prof2.ttcn:22 [t1]
+1      prof2.ttcn:24 [tc2]
+------------------------------------------------
+1      prof3.ttcn:14 [f3]
+1      prof3.ttcn:21 [tc3]
+1      prof3.ttcn:31 [control]
+
+---------------------
+- Unused code lines -
+---------------------
+prof1.ttcn:26 [control]
+prof1.ttcn:27
+---------------------
+prof2.ttcn:15
+prof2.ttcn:32 [control]
+prof2.ttcn:33
+---------------------
+
+--------------------
+- Unused functions -
+--------------------
+prof1.ttcn:26 [control]
+--------------------
+prof2.ttcn:32 [control]
+--------------------
+
diff --git a/regression_test/profiler/prof2.cfg b/regression_test/profiler/prof2.cfg
new file mode 100644 (file)
index 0000000..f0c7c0c
--- /dev/null
@@ -0,0 +1,20 @@
+###############################################################################
+# Copyright (c) 2000-2015 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
+###############################################################################
+[EXECUTE]
+prof1.tc1
+prof2.tc2
+prof3.control
+[PROFILER]
+DisableProfiler := false
+DisableCoverage := true
+DatabaseFile := "data.json"
+AggregateData := true
+DisableStatistics := true
+[LOGGING]
+SourceInfoFormat := Stack
+LogEntityName := Yes
diff --git a/regression_test/profiler/prof2.ttcn b/regression_test/profiler/prof2.ttcn
new file mode 100644 (file)
index 0000000..78f77e8
--- /dev/null
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * Copyright (c) 2000-2015 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
+ ******************************************************************************/
+
+module prof2 {
+
+import from prof1 all;
+
+function f2(inout integer x) runs on C {
+  if (x < 0) {
+    x := x + 1;
+  }
+  else {
+    x := x - 1;
+  }
+}
+
+template integer t1(in integer x) := (0..x);
+
+testcase tc2() runs on C {
+  var integer x := 10;
+  f1(x);
+  f2(x);
+  log(x);
+  var template integer tx := t1(x);
+}
+
+control {
+  execute(tc2());
+}
+
+}
diff --git a/regression_test/profiler/prof3.cfg b/regression_test/profiler/prof3.cfg
new file mode 100644 (file)
index 0000000..20bab99
--- /dev/null
@@ -0,0 +1,22 @@
+###############################################################################
+# Copyright (c) 2000-2015 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
+###############################################################################
+[EXECUTE]
+prof1.tc1
+prof2.tc2
+prof3.control
+[PROFILER]
+DisableProfiler := false
+DisableCoverage := false
+DatabaseFile := "data.json"
+AggregateData := false
+StatisticsFile := "empty.stats"
+DisableStatistics := false
+StatisticsFilter := 0
+[LOGGING]
+SourceInfoFormat := Stack
+LogEntityName := Yes
diff --git a/regression_test/profiler/prof3.ttcn b/regression_test/profiler/prof3.ttcn
new file mode 100644 (file)
index 0000000..00fb287
--- /dev/null
@@ -0,0 +1,35 @@
+/******************************************************************************
+ * Copyright (c) 2000-2015 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
+ ******************************************************************************/
+
+module prof3 {
+
+import from prof1 all;
+import from prof2 all;
+
+function f3() runs on C
+{
+  var integer x := 3;
+  f1(x);
+  log(x);
+}
+
+testcase tc3() runs on C
+{
+  var C otha := C.create("otha");
+  otha.start(f3());
+  var integer y := 7;
+  f2(y);
+  log(y);
+  otha.done;
+}
+
+control {
+  execute(tc3());
+}
+
+}
diff --git a/regression_test/profiler/prof_files.txt b/regression_test/profiler/prof_files.txt
new file mode 100644 (file)
index 0000000..5609b9b
--- /dev/null
@@ -0,0 +1,3 @@
+prof1.ttcn
+prof2.ttcn
+prof3.ttcn
index e4b9c7a2255f4a937a271e3348780f09cf917a19..f4afb600b03aecdeecb74c696c0018b1f7d54877 100644 (file)
@@ -13,7 +13,7 @@ include $(TOPDIR)/Makefile.regression
 
 TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
 
-TTCN3_MODULES = TrecofOper.ttcn
+TTCN3_MODULES = TrecofOper.ttcn TrecofCompat.ttcn
 ifdef RT2
 TTCN3_MODULES += TrecofParamRef.ttcn
 ASN1_MODULES = BerType.asn
diff --git a/regression_test/recofOper/TrecofCompat.ttcn b/regression_test/recofOper/TrecofCompat.ttcn
new file mode 100644 (file)
index 0000000..a3e1a81
--- /dev/null
@@ -0,0 +1,262 @@
+/******************************************************************************
+ * Copyright (c) 2000-2015 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
+ ******************************************************************************/
+
+// This module tests the compatibility between record-ofs and set-ofs of base
+// element types
+module TrecofCompat {
+
+type component CT_Empty {}
+
+// record of
+type record of integer RoI1;
+type record of integer RoI2;
+
+type record of boolean RoB1;
+type record of boolean RoB2;
+
+type record of float RoF1;
+type record of float RoF2;
+
+type record of bitstring RoBS1;
+type record of bitstring RoBS2;
+
+type record of hexstring RoHS1;
+type record of hexstring RoHS2;
+
+type record of octetstring RoOS1;
+type record of octetstring RoOS2;
+
+type record of charstring RoCS1;
+type record of charstring RoCS2;
+
+type record of universal charstring RoUS1;
+type record of universal charstring RoUS2;
+
+type record of integer RoI1_opt with { extension "optimize:memalloc" };
+type record of integer RoI2_opt with { extension "optimize:memalloc" };
+
+testcase tc_record_of_compat() runs on CT_Empty
+{
+  var RoI1 v_roi1 := { 1, 2 };
+  var RoI2 v_roi2 := v_roi1;
+  if (not match( { 1, 2 }, v_roi2) or v_roi1 != v_roi2) { setverdict(fail, "record of integer incompatibility"); }
+
+  var RoB1 v_rob1 := { true, false };
+  var RoB2 v_rob2 := v_rob1;
+  if (not match( { true, false }, v_rob2) or v_rob1 != v_rob2) { setverdict(fail, "record of boolean incompatibility"); }
+
+  var RoF1 v_rof1 := { 0.4, 9.6 };
+  var RoF2 v_rof2 := v_rof1;
+  if (not match( { 0.4, 9.6 }, v_rof2) or v_rof1 != v_rof2) { setverdict(fail, "record of float incompatibility"); }
+
+  var RoBS1 v_robs1 := { '1101'B, '10101'B };
+  var RoBS2 v_robs2 := v_robs1;
+  if (not match( { '1101'B, '10101'B }, v_robs2) or v_robs1 != v_robs2) { setverdict(fail, "record of bitstring incompatibility"); }
+
+  var RoHS1 v_rohs1 := { '1AF74'H, 'D000D'H };
+  var RoHS2 v_rohs2 := v_rohs1;
+  if (not match( { '1AF74'H, 'D000D'H }, v_rohs2) or v_rohs1 != v_rohs2) { setverdict(fail, "record of hexstring incompatibility"); }
+
+  var RoOS1 v_roos1 := { 'DEAD'O, '1BC5'O };
+  var RoOS2 v_roos2 := v_roos1;
+  if (not match( { 'DEAD'O, '1BC5'O }, v_roos2) or v_roos1 != v_roos2) { setverdict(fail, "record of octetstring incompatibility"); }
+
+  var RoCS1 v_rocs1 := { "red", "blue" };
+  var RoCS2 v_rocs2 := v_rocs1;
+  if (not match( { "red", "blue" }, v_rocs2) or v_rocs1 != v_rocs2) { setverdict(fail, "record of charstring incompatibility"); }
+
+  var RoUS1 v_rous1 := { "yellow", "green" };
+  var RoUS2 v_rous2 := v_rous1;
+  if (not match( { "yellow", "green" }, v_rous2) or v_rous1 != v_rous2) { setverdict(fail, "record of universal charstring incompatibility"); }
+
+  var RoI1_opt v_roi1_opt := { 1, 2 };
+  var RoI2_opt v_roi2_opt := v_roi1_opt;
+  if (not match( { 1, 2 }, v_roi2_opt) or v_roi1_opt != v_roi2_opt) { setverdict(fail, "record of integer (optimized) incompatibility"); }
+
+  setverdict(pass);
+}
+
+// record of template
+testcase tc_record_of_template_compat() runs on CT_Empty
+{
+  var template RoI1 vt_roi1 := { 1, 2 };
+  var template RoI2 vt_roi2 := vt_roi1;
+  if (not match( { 1, 2 }, vt_roi2) or not match(valueof(vt_roi1), vt_roi2)) 
+    { setverdict(fail, "record of integer template incompatibility"); }
+
+  var template RoB1 vt_rob1 := { true, false };
+  var template RoB2 vt_rob2 := vt_rob1;
+  if (not match( { true, false }, vt_rob2) or not match(valueof(vt_rob1), vt_rob2)) 
+    { setverdict(fail, "record of boolean template incompatibility"); }
+
+  var template RoF1 vt_rof1 := { 0.4, 9.6 };
+  var template RoF2 vt_rof2 := vt_rof1;
+  if (not match( { 0.4, 9.6 }, vt_rof2) or not match(valueof(vt_rof1), vt_rof2)) 
+    { setverdict(fail, "record of float template incompatibility"); }
+
+  var template RoBS1 vt_robs1 := { '1101'B, '10101'B };
+  var template RoBS2 vt_robs2 := vt_robs1;
+  if (not match( { '1101'B, '10101'B }, vt_robs2) or not match(valueof(vt_robs1), vt_robs2)) 
+    { setverdict(fail, "record of bitstring template incompatibility"); }
+
+  var template RoHS1 vt_rohs1 := { '1AF74'H, 'D000D'H };
+  var template RoHS2 vt_rohs2 := vt_rohs1;
+  if (not match( { '1AF74'H, 'D000D'H }, vt_rohs2) or not match(valueof(vt_rohs1), vt_rohs2)) 
+    { setverdict(fail, "record of hexstring template incompatibility"); }
+
+  var template RoOS1 vt_roos1 := { 'DEAD'O, '1BC5'O };
+  var template RoOS2 vt_roos2 := vt_roos1;
+  if (not match( { 'DEAD'O, '1BC5'O }, vt_roos2) or not match(valueof(vt_roos1), vt_roos2)) 
+    { setverdict(fail, "record of octetstring template incompatibility"); }
+
+  var template RoCS1 vt_rocs1 := { "red", "blue" };
+  var template RoCS2 vt_rocs2 := vt_rocs1;
+  if (not match( { "red", "blue" }, vt_rocs2) or not match(valueof(vt_rocs1), vt_rocs2)) 
+    { setverdict(fail, "record of charstring template incompatibility"); }
+
+  var template RoUS1 vt_rous1 := { "yellow", "green" };
+  var template RoUS2 vt_rous2 := vt_rous1;
+  if (not match( { "yellow", "green" }, vt_rous2) or not match(valueof(vt_rous1), vt_rous2)) 
+    { setverdict(fail, "record of universal charstring template incompatibility"); }
+
+  var template RoI1_opt vt_roi1_opt := { 1, 2 };
+  var template RoI2_opt vt_roi2_opt := vt_roi1_opt;
+  if (not match( { 1, 2 }, vt_roi2_opt) or not match(valueof(vt_roi1_opt), vt_roi2_opt)) 
+    { setverdict(fail, "record of integer template (optimized) incompatibility"); }
+
+  setverdict(pass);
+}
+
+// set of
+type set of integer SoI1;
+type set of integer SoI2;
+
+type set of boolean SoB1;
+type set of boolean SoB2;
+
+type set of float SoF1;
+type set of float SoF2;
+
+type set of bitstring SoBS1;
+type set of bitstring SoBS2;
+
+type set of hexstring SoHS1;
+type set of hexstring SoHS2;
+
+type set of octetstring SoOS1;
+type set of octetstring SoOS2;
+
+type set of charstring SoCS1;
+type set of charstring SoCS2;
+
+type set of universal charstring SoUS1;
+type set of universal charstring SoUS2;
+
+type set of integer SoI1_opt with { extension "optimize:memalloc" };
+type set of integer SoI2_opt with { extension "optimize:memalloc" };
+
+testcase tc_set_of_compat() runs on CT_Empty
+{
+  var SoI1 v_soi1 := { 1, 2 };
+  var SoI2 v_soi2 := v_soi1;
+  if (not match( { 1, 2 }, v_soi2) or v_soi1 != v_soi2) { setverdict(fail, "set of integer incompatibility"); }
+
+  var SoB1 v_sob1 := { true, false };
+  var SoB2 v_sob2 := v_sob1;
+  if (not match( { true, false }, v_sob2) or v_sob1 != v_sob2) { setverdict(fail, "set of boolean incompatibility"); }
+
+  var SoF1 v_sof1 := { 0.4, 9.6 };
+  var SoF2 v_sof2 := v_sof1;
+  if (not match( { 0.4, 9.6 }, v_sof2) or v_sof1 != v_sof2) { setverdict(fail, "set of float incompatibility"); }
+
+  var SoBS1 v_sobs1 := { '1101'B, '10101'B };
+  var SoBS2 v_sobs2 := v_sobs1;
+  if (not match( { '1101'B, '10101'B }, v_sobs2) or v_sobs1 != v_sobs2) { setverdict(fail, "set of bitstring incompatibility"); }
+
+  var SoHS1 v_sohs1 := { '1AF74'H, 'D000D'H };
+  var SoHS2 v_sohs2 := v_sohs1;
+  if (not match( { '1AF74'H, 'D000D'H }, v_sohs2) or v_sohs1 != v_sohs2) { setverdict(fail, "set of hexstring incompatibility"); }
+
+  var SoOS1 v_soos1 := { 'DEAD'O, '1BC5'O };
+  var SoOS2 v_soos2 := v_soos1;
+  if (not match( { 'DEAD'O, '1BC5'O }, v_soos2) or v_soos1 != v_soos2) { setverdict(fail, "set of octetstring incompatibility"); }
+
+  var SoCS1 v_socs1 := { "red", "blue" };
+  var SoCS2 v_socs2 := v_socs1;
+  if (not match( { "red", "blue" }, v_socs2) or v_socs1 != v_socs2) { setverdict(fail, "set of charstring incompatibility"); }
+
+  var SoUS1 v_sous1 := { "yellow", "green" };
+  var SoUS2 v_sous2 := v_sous1;
+  if (not match( { "yellow", "green" }, v_sous2) or v_sous1 != v_sous2) { setverdict(fail, "set of universal charstring incompatibility"); }
+
+  var SoI1_opt v_soi1_opt := { 1, 2 };
+  var SoI2_opt v_soi2_opt := v_soi1_opt;
+  if (not match( { 1, 2 }, v_soi2_opt) or v_soi1_opt != v_soi2_opt) { setverdict(fail, "set of integer (optimized) incompatibility"); }
+
+  setverdict(pass);
+}
+
+// set of template
+testcase tc_set_of_template_compat() runs on CT_Empty
+{
+  var template SoI1 vt_soi1 := { 1, 2 };
+  var template SoI2 vt_soi2 := vt_soi1;
+  if (not match( { 1, 2 }, vt_soi2) or not match(valueof(vt_soi1), vt_soi2)) 
+    { setverdict(fail, "set of integer template incompatibility"); }
+
+  var template SoB1 vt_sob1 := { true, false };
+  var template SoB2 vt_sob2 := vt_sob1;
+  if (not match( { true, false }, vt_sob2) or not match(valueof(vt_sob1), vt_sob2)) 
+    { setverdict(fail, "set of boolean template incompatibility"); }
+
+  var template SoF1 vt_sof1 := { 0.4, 9.6 };
+  var template SoF2 vt_sof2 := vt_sof1;
+  if (not match( { 0.4, 9.6 }, vt_sof2) or not match(valueof(vt_sof1), vt_sof2)) 
+    { setverdict(fail, "set of float template incompatibility"); }
+
+  var template SoBS1 vt_sobs1 := { '1101'B, '10101'B };
+  var template SoBS2 vt_sobs2 := vt_sobs1;
+  if (not match( { '1101'B, '10101'B }, vt_sobs2) or not match(valueof(vt_sobs1), vt_sobs2)) 
+    { setverdict(fail, "set of bitstring template incompatibility"); }
+
+  var template SoHS1 vt_sohs1 := { '1AF74'H, 'D000D'H };
+  var template SoHS2 vt_sohs2 := vt_sohs1;
+  if (not match( { '1AF74'H, 'D000D'H }, vt_sohs2) or not match(valueof(vt_sohs1), vt_sohs2)) 
+    { setverdict(fail, "set of hexstring template incompatibility"); }
+
+  var template SoOS1 vt_soos1 := { 'DEAD'O, '1BC5'O };
+  var template SoOS2 vt_soos2 := vt_soos1;
+  if (not match( { 'DEAD'O, '1BC5'O }, vt_soos2) or not match(valueof(vt_soos1), vt_soos2)) 
+    { setverdict(fail, "set of octetstring template incompatibility"); }
+
+  var template SoCS1 vt_socs1 := { "red", "blue" };
+  var template SoCS2 vt_socs2 := vt_socs1;
+  if (not match( { "red", "blue" }, vt_socs2) or not match(valueof(vt_socs1), vt_socs2)) 
+    { setverdict(fail, "set of charstring template incompatibility"); }
+
+  var template SoUS1 vt_sous1 := { "yellow", "green" };
+  var template SoUS2 vt_sous2 := vt_sous1;
+  if (not match( { "yellow", "green" }, vt_sous2) or not match(valueof(vt_sous1), vt_sous2)) 
+    { setverdict(fail, "set of universal charstring template incompatibility"); }
+
+  var template SoI1_opt vt_soi1_opt := { 1, 2 };
+  var template SoI2_opt vt_soi2_opt := vt_soi1_opt;
+  if (not match( { 1, 2 }, vt_soi2_opt) or not match(valueof(vt_soi1_opt), vt_soi2_opt)) 
+    { setverdict(fail, "set of integer template (optimized) incompatibility"); }
+
+  setverdict(pass);
+}
+
+control {
+  execute(tc_record_of_template_compat());
+  execute(tc_record_of_compat());
+  execute(tc_set_of_template_compat());
+  execute(tc_set_of_compat());
+}
+
+}
index 09f4c5aaf5339815a9847dd3db477584a29363a9..0485ee9a7b5a2e7fe6ebab182fe00dbde6e8a2cc 100644 (file)
@@ -660,6 +660,32 @@ testcase tc_param_ref_emb_lazy() runs on CT_Empty
   else { setverdict(fail, "@4 got: ", v_roi, ", expected: { 10, <unbound>, <unbound>, <unbound>, <unbound>, 20 }"); }
 }
 
+// 19. The function call is interrupted by a DTE, the reference to the element should be cleaned up (HT47424)
+function f_dte(in RoI p_roi, inout integer p_val) runs on CT_Empty
+{
+  var integer bad_index := -1;
+  if (p_val < p_roi[bad_index]) {
+    setverdict(fail, "expected DTE in if clause");
+  }
+}
+
+testcase tc_param_ref_dte() runs on CT_Empty
+{
+  var RoI v_roi := { 0, 1, 2, 3 };
+  @try {
+    f_dte(v_roi, v_roi[2]);
+    setverdict(fail, "expected DTE in function call");
+  }
+  @catch (dummy) {}
+  v_roi := { };
+  var RoI v_copy := v_roi;
+  var charstring log_exp := "{ }";
+  if (log2str(v_roi) == log_exp) { setverdict(pass); }
+  else { setverdict(fail, "@1 got: ", v_roi, ", expected: ", log_exp); }
+  if (log2str(v_copy) == log_exp) { setverdict(pass); }
+  else { setverdict(fail, "@2 got: ", v_copy, ", expected: ", log_exp); }
+}
+
 control {
   execute(tc_param_ref_assign());
   execute(tc_param_ref_concat());
@@ -684,6 +710,8 @@ control {
 
   execute(tc_param_ref_emb_recof_opt());
   execute(tc_param_ref_emb_lazy());
+
+  execute(tc_param_ref_dte());
 }
 
 } // end of module
index eb0d2a5a66fbfa89157ab37222a99639f68e1702..0cbecade13f71b2866eb4a3d1bf151385ebb1d81 100644 (file)
@@ -12,3 +12,4 @@ FileMask := LOG_ALL
 ConsoleMask := TTCN_WARNING | TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS
 [EXECUTE]
 TrecofOper
+TrecofCompat
index 8cd9abc95ed5c5b7abafe24edcc4e2eec5d54750..0c8ed98a251766ccf2b71d9973fa25a9686d04c3 100644 (file)
@@ -12,4 +12,5 @@ FileMask := LOG_ALL
 ConsoleMask := TTCN_WARNING | TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS
 [EXECUTE]
 TrecofOper
+TrecofCompat
 TrecofParamRef
index 49f71221ae9789d2ec7d112789eee91991185e85..c874dd8d7fb863b3f686f771a31049520a2ccc6b 100644 (file)
@@ -32,7 +32,7 @@ CXXDEPFLAGS = -MM
 CXXFLAGS += -g
 
 # Flags for the linker:
-LDFLAGS += -g -rdynamic
+#LDFLAGS += -g -rdynamic
 
 
 # Flags for the TTCN-3 and ASN.1 compiler:
index f93552cd59eb5d28aed41fb1cb322f4083f76c33..fdc797a0b3c12e06f194d17e5753b458f569180f 100644 (file)
@@ -367,6 +367,41 @@ testcase tc_unichar_utf8_template() runs on empty {
   else { setverdict(fail,   valueof(t_u1ch), "!=", valueof(t_u1)); }
 }
 
+// Fixed indexing errors when the string only contained ASCII characters (HT70680)
+function f_changeUnichar(in universal charstring pl_char)
+return universal charstring
+{
+  log("lengthof(pl_char): ", lengthof(pl_char))
+  log("pl_char: ", pl_char); // garbage here
+  return pl_char;
+}
+
+function f_modifyUnichar(in universal charstring pl_str)
+return universal charstring
+{
+  var integer vl_size := lengthof(pl_str);
+  var universal charstring vl_tmp;
+
+  for (var integer vl_i := 0; vl_i < vl_size; vl_i := vl_i + 1)
+  {
+    log("pl_str[vl_i]: ", pl_str[vl_i])
+    vl_tmp := f_changeUnichar(pl_str[vl_i]);
+    log("vl_tmp: ", vl_tmp); // garbage here
+    pl_str[vl_i] := vl_tmp; // segmentation fault here
+  }
+
+  return pl_str;
+}
+
+testcase tc_indexing_HT70680() runs on empty 
+{
+  // must contain only ASCII characters
+  var universal charstring v_str := "alma123";
+  var universal charstring v_res := f_modifyUnichar(v_str);
+  if (v_str == v_res) { setverdict(pass); }
+  else { setverdict(fail, "got: ", v_res, " expected: ", v_str); }
+}
+
 
 control {
   execute(tc_charstring_content());
@@ -378,6 +413,7 @@ control {
   //execute(tc_unichar_utf8_mp1());
   //execute(tc_unichar_utf8_mp2());
   execute(tc_unichar_utf8_template());
+  execute(tc_indexing_HT70680());
 }
 
 }
index 62c5615b969dfc39c458f69bc1d57249f37923e2..c3e04d620d7fd6852306e16aeb1d82d124435320 100755 (executable)
Binary files a/titan_executor_api/doc/Titan_Executor_API_User_Guide.doc and b/titan_executor_api/doc/Titan_Executor_API_User_Guide.doc differ
index b0e48bf0a226c2435a81cbb3459a2fb80adc7e5d..4a1a4d0701f99745b3f2fb721a8f1c8965b761d8 100644 (file)
Binary files a/usrguide/PRI.doc and b/usrguide/PRI.doc differ
index 6d9e0e61f2044c2b981cb6ec4afec09665d603e6..0d52c28e306b8280cf08f1bdb59e80c2cfd13305 100644 (file)
Binary files a/usrguide/apiguide.doc and b/usrguide/apiguide.doc differ
index d530d55c31271dabbe32808e08cdfc5737fad0cb..c554cf6f5874b559797f15fd698f372cf4dc6a38 100644 (file)
Binary files a/usrguide/installationguide.doc and b/usrguide/installationguide.doc differ
index 4bc7ce3308253a4c88c9c24b94c0ebee8361d7cd..9a9bf7e6f6ad68b8e2657249c7fad57c192a7a18 100644 (file)
Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ
index b9c5b49bcaf02c1f4c612b5cadf5d8d2506adab0..e100f7a651d4265693a911833f0ff970b1daf5cb 100644 (file)
Binary files a/usrguide/releasenotes.doc and b/usrguide/releasenotes.doc differ
index da7dd72a28d15a2719d0a32bc9680a8633b60cb2..7588f021d967fb79e5b08c9c0784c5ceeea05f95 100644 (file)
Binary files a/usrguide/userguide.doc and b/usrguide/userguide.doc differ
This page took 0.271191 seconds and 5 git commands to generate.