/* Version numbers */
#define TTCN3_MAJOR 5
-#define TTCN3_MINOR 2
+#define TTCN3_MINOR 3
#define TTCN3_PATCHLEVEL 0
//#define TTCN3_BUILDNUMBER 0
* 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)
#include "../common/version.h"
#include "CodeGenHelper.hh"
#include <limits.h>
+#include "ttcn3/profiler.h"
reffer::reffer(const char*) {}
}
// 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");
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 =
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 =
// 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
#include "Value.hh"
#include "Int.hh"
#include "main.hh"
+#include "ttcn3/profiler.h"
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;
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);
}
}
- 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:
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;
{
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) {
{
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();
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:
}
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
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
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
"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"
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_);
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) {
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
"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)
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;
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));
}
// 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 =
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);
case OPTYPE_TMR_RUNNING_ANY:
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
+ case OPTYPE_PROF_RUNNING:
break;
case OPTYPE_UNARYPLUS: // v1
case OPTYPE_UNARYMINUS:
case OPTYPE_TMR_RUNNING_ANY:
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
+ case OPTYPE_PROF_RUNNING:
break;
case OPTYPE_UNARYPLUS: // v1
case OPTYPE_UNARYMINUS:
case OPTYPE_TMR_RUNNING_ANY:
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
+ case OPTYPE_PROF_RUNNING:
break;
default:
FATAL_ERROR("Value::Value()");
case OPTYPE_TMR_RUNNING_ANY:
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
+ case OPTYPE_PROF_RUNNING:
break;
case OPTYPE_UNARYPLUS: // v1
case OPTYPE_UNARYMINUS:
case OPTYPE_TMR_RUNNING_ANY:
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
+ case OPTYPE_PROF_RUNNING:
break;
case OPTYPE_UNARYPLUS: // v1
case OPTYPE_UNARYMINUS:
case OPTYPE_TMR_RUNNING_ANY:
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
+ case OPTYPE_PROF_RUNNING:
break;
case OPTYPE_UNARYPLUS: // v1
case OPTYPE_UNARYMINUS:
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;
return "log2str()";
case OPTYPE_TTCN2STRING:
return "ttcn2string()";
+ case OPTYPE_PROF_RUNNING:
+ return "@profiler.running";
default:
FATAL_ERROR("Value::get_opname()");
} // switch
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:
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:
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
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
}
ret_val += ')';
return ret_val; }
+ case OPTYPE_PROF_RUNNING:
+ return string("@profiler.running");
default:
return string("<unsupported optype>");
} // switch u.expr.v_optype
}
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()");
}
case OPTYPE_TMR_RUNNING_ANY:
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
+ case OPTYPE_PROF_RUNNING:
return true;
case OPTYPE_ENCODE:
case OPTYPE_DECODE:
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;
}
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
};
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);
.IR " verb_level" " \|]"
.RB "[\| " \-K
.IR " file" " \|]"
+.RB "[\| " \-z
+.IR " file" " \|]"
.RB "[\| " \-o
.IR " dir" " \|]"
.RB "[\| " \-P
.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
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 */
#include "ttcn3/Ttcn2Json.hh"
+#include "ttcn3/profiler.h"
+
#ifdef LICENSE
#include "../common/license.h"
#endif
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;
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;
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) {
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;
}
}
}
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;
}
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"
" -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"
usage();
return EXIT_FAILURE;
}
-
+
bool
Aflag = false, Lflag = false, Yflag = false,
Pflag = false, Tflag = false, Vflag = false, bflag = false,
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;
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':
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': {
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 {
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;
}
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");
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;
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]);
#endif
#include "datatypes.h"
+#include "../common/memory.h"
typedef struct tcov_file_list
{
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;
" 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) {
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);
}
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");
" 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) {
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,
" 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"
" }\n"
" return encoded_length;\n"
"}\n"
- ,name,sdef->oftypedescrname
+ ,name
);
src = mputprintf(src,
"int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
" 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"
" }\n"
" }\n"
" }\n"
- ,name,type,type,sdef->oftypedescrname,type
+ ,name,type,type,type
);
src = mputstr(src,
" limit.remove_tokens(ml);\n"
" 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"
"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) {
" 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"
" }\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"
" 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"
" 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
);
}
"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. */
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,
" 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"
" 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, "
"%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)");
}
" }\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,
" 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"
" 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 */
" 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 */
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"
" }\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"
" 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"
" 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
" 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,
" 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"
" }\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"
" }\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"
" }\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"
" 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"
" }\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");
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,
/* 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);
" 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"
" }\n"
" return encoded_length;\n"
"}\n"
- ,name,sdef->oftypedescrname
+ ,name
);
src = mputprintf(src,
"int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
" 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"
" }\n"
" }\n"
" }\n"
- ,name,type,sdef->oftypedescrname
+ ,name,type
);
src = mputstr(src,
" limit.remove_tokens(ml);\n"
" 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"
" 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) {
" 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"
" }\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"*/
" 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,
" 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
);
}
"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. */
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,
" 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"
" 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, "
"%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)");
}
" }\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,
" 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"
" 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 */
" 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 */
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"
, 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"
" 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"
" 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
" 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,
" 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"
" }\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"
" }\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"
" }\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"
" 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"
" }\n\n"
" return dec_len;\n"
"}\n\n"
- , name, type, sdef->oftypedescrname);
+ , name, type);
}
/* end of class */
def = mputstr(def, "};\n\n");
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,
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) {
"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) {
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");
}
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){
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)
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;
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
}
}
/* 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);
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);
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());
}
}
}
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();
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;
}
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;
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) {
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 += ')';
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;
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");
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());
}
}
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");
}
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);
}
}
}
// 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);
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;
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();
}
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;
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);
}
}
}
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);
}
}
}
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]);
}
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);
}
}
}
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);
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;
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;
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);
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:
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);
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);
{
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;
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",
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()->
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);
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;
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;
// 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;
{
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;
}
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;
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;
}
{
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(),
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;
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;
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;
}
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());
}
}
}
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;
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());
}
}
}
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;
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());
}
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;
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;
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);
{
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;
}
}
}
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()");
// 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());
}
}
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);
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) {
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) {
// 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"
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);
}
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;
}
}
}
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();
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) {
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();
// 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");
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();
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;
}
// 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
, __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);
}
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);
}
// 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"
// 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
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");
// 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"
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);
}
// 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"
// 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"
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",
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()");
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);
}
}
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();
}
}
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
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
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 {
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 {
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;
}
}
}
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) {
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);
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) {
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);
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;
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()");
}
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();
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;
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());
}
}
}
// 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;
// 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
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->
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());
}
}
}
// 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;
}
// 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);
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 {
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:
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;
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)
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
// 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()) {
}
// 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);
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)
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:
ags=0;
case S_ERROR:
case S_STOP_EXEC:
+ case S_START_PROFILER:
+ case S_STOP_PROFILER:
break;
case S_BREAK:
case S_CONTINUE:
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 "";
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:
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:
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:
case S_STRING2TTCN:
chk_string2ttcn();
break;
+ case S_START_PROFILER:
+ case S_STOP_PROFILER:
+ // do nothing
+ break;
default:
FATAL_ERROR("Statement::chk()");
} // switch statementtype
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);
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
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()");
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,
(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);
/* 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 {
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);
// 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;
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; }
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; }
// 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;
#include "compiler.h"
#include "../main.hh"
#include "../error.h"
+#include "profiler.h"
#ifdef LICENSE
#include "../../common/license.h"
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);
"@try" RETURN(TitanSpecificTryKeyword);
"@catch" RETURN(TitanSpecificCatchKeyword);
"@lazy" RETURN(TitanSpecificLazyKeyword);
+"@profiler" RETURN(TitanSpecificProfilerKeyword);
/* Predefined function identifiers */
%token TitanSpecificTryKeyword
%token TitanSpecificCatchKeyword
%token TitanSpecificLazyKeyword
+%token TitanSpecificProfilerKeyword
/* Keywords combined with a leading dot */
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
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
PredefOrIdentifier
PredefinedOps
PredefinedValue
+ProfilerRunningOp
+ProfilerStatement
RaiseStatement
Range
ReadTimerOp
%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.
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.
*/
| SUTStatements {$$=$1;}
| StopExecutionStatement { $$ = $1; }
| StopTestcaseStatement { $$ = $1; }
+| ProfilerStatement { $$ = $1; }
;
FunctionInstance: /* refpard */ // 181
| BehaviourStatements { $$ = $1; }
| SUTStatements { $$ = $1; }
| StopExecutionStatement { $$ = $1; }
+| ProfilerStatement { $$ = $1; }
;
/* A.1.6.2.1 Variable instantiation */
}
;
+ /* 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
{
else $$ = new Value(Value::V_ERROR);
$$->set_location(infile, @$);
}
+| ProfilerRunningOp { $$ = $1; }
;
PredefinedOps:
--- /dev/null
+/******************************************************************************
+ * 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;
+ }
+}
--- /dev/null
+/******************************************************************************
+ * 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 */
+
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()
{
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 ********************/
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 */
*
* */
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];
}
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,
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];
}
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
};
////////////////////////////////////////////////////////////////////////////////
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:
/** 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>
}
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};
#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;
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
*
*/
// 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;
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*);
/** @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;
/** 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,
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");
}
}
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;
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();
}
}
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);
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:
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
# 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)
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
endif
mkdir -p $(INCDIR)/$(APIDIR)
cp $(APIDIR)/TitanLoggerApi*.hh $(INCDIR)/$(APIDIR)
+ cp $(APIDIR)/PreGenRecordOf.hh $(INCDIR)/$(APIDIR)
# # # # executables
single$(RT2_SUFFIX)$(EXESUFFIX): $(LIBRARY)
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
{
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()
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. */
* '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)
{
++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
// 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;
#include "Error.hh"
#include "Encdec.hh"
#include "TCov.hh"
+#ifdef LINUX
+#include <execinfo.h>
+#endif
#ifdef LICENSE
#include "../common/license.h"
//static const char segfault[] = " : Segmentation fault occurred\n";
-void signal_handler(int)
+void signal_handler(int signum)
{
int retval;
time_t now=time(0);
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
(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();
}
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]);
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// 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" };
+
+}
///////////////////////////////////////////////////////////////////////////////
#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 //////////
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");
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();
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;
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);
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);
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);
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);
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);
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
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);
}
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()) {
, 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
"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;
// 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;
+ }
}
}
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
{
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)
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()
{
--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)
{
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,
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);
+ }
+ }
+ }
+}
#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).
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;
};
/** 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 */
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();
/** 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 */
* @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 */
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 */
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
* 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 */
/** 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 */
/** 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 */
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;
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);*/
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// 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 */
+
#include "Charstring.hh"
#include "Fd_And_Timeout_User.hh"
#include <TitanLoggerApi.hh>
+#include "Profiler.hh"
namespace API = TitanLoggerApi;
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();
"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);
#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();
}
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]);
#include <fcntl.h>
#include <errno.h>
+#include <sys/select.h>
#include <sys/types.h>
#include <poll.h>
#ifdef USE_EPOLL
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 } };
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 */
#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"
#include "JSON.hh"
#include "Error.hh"
#include "XmlReader.hh"
+#include "Profiler.hh"
#endif
#ifdef TITAN_RUNTIME_2
#include "Struct_of.hh"
+#include "RefdIndex.hh"
struct TTCN_Typedescriptor_t;
struct Erroneous_descriptor_t;
#endif
#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,
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
#include "Logger.hh"
#include "Encdec.hh"
#include "Addfunc.hh" // for unichar2int
+#include "TEXT.hh"
#include <string>
#include <iostream>
#include <stdint.h>
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);
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);
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);
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
{
// 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;
{
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;
}
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)
#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;
* 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
/** 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;
/** 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 */
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) \
#include "../common/dbgnew.hh"
+#include "Profiler.hh"
+
extern string_map_t *config_defines;
#define yylval config_process_lval
. /* 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 */
<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;
%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
%type <module_param_length_restriction> LengthMatch
%type <str_val> PatternChunk PatternChunkList
%type <int_native> IndexItemIndex LengthBound
+%type <uint_val> ProfilerStatsFlags
%destructor { Free($$); }
ArrayRef
| AggregateDataSetting
| StatisticsFileSetting
| DisableStatisticsSetting
+| StatisticsFilterSetting
+| StartAutomaticallySetting
+| NetLineTimesSetting
+| NetFunctionTimesSetting
;
DisableProfilerSetting:
}
;
+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:
string_map_free(config_defines);
config_defines = NULL;
- ttcn3_prof.init_data_file();
-
return !error_flag;
}
}
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);
}
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;
}
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;
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();
}
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));
}
}
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;
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++) {
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
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;
}
}
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);
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");
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++]);
}
}
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,
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;
}
// 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);
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 ||=
}
}
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 &&
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);
}
* @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
{
} 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);
}
}
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;
}
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;
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);
* 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.
}
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;
}
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);
}
}
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
+++ /dev/null
-<?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 <build>
- or providing the location of a pre-built <executable>
- 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>
: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)
.* 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)
.* 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)
.* 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)
: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)
.* 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)
.* 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.
: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
.* 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
: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
.* 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)
: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
.* 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
.* 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
: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
.* 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
: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
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.
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.
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.
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.
.* 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)
.* 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
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.
.*---------------------------------------------------------------------*
.* 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
: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
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])
}
}
<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\)
<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
.*---------------------------------------------------------------------*
<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>
<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>
<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>
: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>
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>
<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>
: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)
}
-proc _executor {message coverage_args rt_2} {
+proc _executor {message coverage_args} {
global sh_id
if {![file exists Makefile]} {
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
}
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
: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
<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>
<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>
<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>
<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>
<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>
<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>
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
<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">
<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">
<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>
<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">
--- /dev/null
+<!--
+ 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. </p>
+<p>By default the profiler is automatically started for each component when the program starts. This can be changed in the configuration file. </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. 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. 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/>
+ var boolean stop_prof := not @profiler.running;<br/>
+ @profiler.start;<br/>
+ x := x + c1;<br/>
+ if (stop_prof) {<br/>
+ @profiler.stop;<br/>
+ }<br/>
+}<br>
+</font>
+<p>
+
+<p>This function is always profiled and returns the profiler to its original state.</p>
+
+</body>
+</html>
<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>
<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>
<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">
</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 timers</a></p>
+<h3>2. <a name="timer">Checking 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>
<p><i>timer_identifier</i> is the 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> <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>
<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; <br>
</font>
<p>The variable v_metropolitain is true if at least one parallel component is still running.</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>
<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:
<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">
</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">
<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%">
<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>
<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">
</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>
</li>
</ul>
<hr align="left" width="75%">
-<p>3. <a name="timer">Stopping timers</a></p>
+<h3>3. <a name="timer">Stopping 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>
<p><i>timer_identifier</i> is the 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">
<p><i>timer_identifier</i> is the 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>
</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%"> </td>
<td width="17%"> </td>
<td width="17%"> </td>
<td width="17%"> </td>
<td width="17%"> </td>
- <td width="17%"> </td>
</tr>
<tr>
<td width="17%"><a name="r"></a><a href="info/raise.html">raise</a></td>
<td width="17%"> </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%"> </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%"> </td>
<td width="17%"> </td>
</tr>
+ <tr>
+ <td width="17%"><a name="@"></a><a href="info/profiler.html">@profiler</a></td>
+ <td width="17%"> </td>
+ <td width="17%"> </td>
+ <td width="17%"> </td>
+ <td width="17%"> </td>
+ <td width="17%"> </td>
+ <td width="17%"> </td>
+ </tr>
</table>
</center>
</div>
<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>
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// 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<) escaped = mputstr(escaped, "<");
+ else escaped = mputc(escaped, c);
+ break;
+ case '>':
+ if (escape_chars>) escaped = mputstr(escaped, ">");
+ else escaped = mputc(escaped, c);
+ break;
+ case '"':
+ if (escape_chars") escaped = mputstr(escaped, """);
+ else escaped = mputc(escaped, c);
+ break;
+ case '\'':
+ if (escape_chars&APOS) escaped = mputstr(escaped, "'");
+ else escaped = mputc(escaped, c);
+ break;
+ case '&':
+ if (escape_chars&) escaped = mputstr(escaped, "&");
+ 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";
+ }
+}
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// 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
--- /dev/null
+###############################################################################
+# 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
# 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
#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>
/* SC_cstring */
+<SC_PROFILER>{HEX}+ {
+ /* numeric statistics filter (check this before checking NUMBERs) */
+ RETURN(ProfilerStatsFlag);
+}
+
+
/* Values */
{NUMBER} {
<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);
case SC_LOGGING:
case SC_TESTPORT_PARAMETERS:
case SC_EXTERNAL_COMMANDS:
+ case SC_PROFILER:
return TRUE;
default:
return FALSE;
%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
| AggregateDataSetting
| StatisticsFileSetting
| DisableStatisticsSetting
+| StatisticsFilterSetting
+| StartAutomaticallySetting
+| NetLineTimesSetting
+| NetFunctionTimesSetting
;
DisableProfilerSetting:
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:
{
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)
{
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)
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
}
} -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
}
}
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
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());
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());
}
}
CXXFLAGS += -g -W -Wformat=2
# Flags for the linker:
-LDFLAGS += -g -rdynamic
+#LDFLAGS += -g -rdynamic
WIN32_LIBS += -liconv
FREEBSD_LIBS += -liconv
# built-in modules for the logger
'TitanLoggerApi' => '',
'TitanLoggerControl' => '',
+'PreGenRecordOf' => '',
);
--- /dev/null
+/******************************************************************************
+ * 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());
+}
+
+}
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 {
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());
}
}
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;
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,
}
*/
+/* * * * 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;
+
}
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;
execute(boolXor());
execute(boolSubtypes());
execute(boolIsvalue());
+ execute(boolShortCircuit());
}
}
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 };
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 } };
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); }
execute(tc_set_of());
execute(tc_anytype());
execute(tc_array());
+ execute(tc_component());
+ execute(tc_default());
execute(tc_nested());
execute(tc_nested_templ());
}
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
--- /dev/null
+###############################################################################
+# 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)
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// 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");
+ }
+ }
+}
+
+}
CXXDEPFLAGS := -MM
#COMPILER_FLAGS +=
-LDFLAGS += -rdynamic
+#LDFLAGS += -rdynamic
TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+/*******************************************************************************
+* 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
--- /dev/null
+/*******************************************************************************
+* 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
--- /dev/null
+/******************************************************************************
+ * 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
--- /dev/null
+/******************************************************************************
+ * 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
--- /dev/null
+/******************************************************************************
+ * 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
+
+
--- /dev/null
+/******************************************************************************
+ * 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
--- /dev/null
+/******************************************************************************
+ * 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());
+}
+
+}
--- /dev/null
+[
+ {
+ "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
+ }
+ ]
+ }
+]
--- /dev/null
+##################################################
+## TTCN-3 profiler and code coverage statistics ##
+##################################################
+
+
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+/******************************************************************************
+ * 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());
+}
+
+}
--- /dev/null
+##################################################
+######### 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]
+--------------------
+
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+/******************************************************************************
+ * 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());
+}
+
+}
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+/******************************************************************************
+ * 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());
+}
+
+}
--- /dev/null
+prof1.ttcn
+prof2.ttcn
+prof3.ttcn
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
--- /dev/null
+/******************************************************************************
+ * 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());
+}
+
+}
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());
execute(tc_param_ref_emb_recof_opt());
execute(tc_param_ref_emb_lazy());
+
+ execute(tc_param_ref_dte());
}
} // end of module
ConsoleMask := TTCN_WARNING | TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS
[EXECUTE]
TrecofOper
+TrecofCompat
ConsoleMask := TTCN_WARNING | TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS
[EXECUTE]
TrecofOper
+TrecofCompat
TrecofParamRef
CXXFLAGS += -g
# Flags for the linker:
-LDFLAGS += -g -rdynamic
+#LDFLAGS += -g -rdynamic
# Flags for the TTCN-3 and ASN.1 compiler:
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());
//execute(tc_unichar_utf8_mp1());
//execute(tc_unichar_utf8_mp2());
execute(tc_unichar_utf8_template());
+ execute(tc_indexing_HT70680());
}
}