/ 1

C/C++ to TTCN-3 Mapping

Change history:
Version / Date / Made by / Comments
0.1 / 24.9.2004 / Matti Kärki/VTT,
Pekka Pulkkinen/VTT, Andreas Nyberg/NOKIA / Outline of the C/C++ to TTCN-3 mapping
0.2 / 16.11.2004 / Pekka Pulkkinen/VTT
Matti Kärki/VTT
Andreas Nyberg/NOKIA / First complete version of consolidated C/C++ mapping
0.3 / 8.3.2005 / Matti Kärki/VTT
Andreas Nyberg/NOKIA / C/C++ mapping finalized by VTT and Nokia
1

Contents

Contents

List of Symbols

1. Introduction

2. Scope

3. Names and Scoping

4. Boolean Type

5. Character Type

6. Integer Types

7. Floating-point Types

8. Structure Types

9. Class Types

10. Union Types

11. Enumeration Types

12. Function Types

13. Pointer Types

14. Array Types

15. Reference Types

16. Inheritance

17. Template Specifications

18. Constant Values

19. extern Values

20. typedef Declaration

21. Access Specifiers

22. Preprocessor Directives

23. Lexical Conventions

24. References

List of Symbols

ASN.1 Abstract Syntax Notation One

APIApplication Programming Interface

TTCN-3Testing and Test Control Notation version 3

1.Introduction

TTCN is a standardized and an industry proven test implementation language for conformance testing in telecom area, while TTCN-3 is an emerging technology and tries to widen the scope of TTCN by relying on the same concepts and refined definitions of TTCN, and introducing some new features. Unlike earlier versions of TTCN, TTCN-3 should be applicable, not just for conformance testing, but in many areas of testing. Typical areas of application are protocol testing (including mobile and Internet protocols), service testing (including supplementary services), module testing, testing of CORBA based platforms, APIs etc. TTCN-3 can be used also for many other kinds of testing including interoperability, robustness, regression, system and integration testing.

TTCN-3 is a language especially designed for test case implementation at an abstract level by hiding the test system details. However, to directly access the required and provided interfaces of the C/C++ software modules under test, the TTCN-3 test system requires information of the interfaces via which the modules are tested. In order to represent the interface, TTCN-3 provides a mechanism to use types from other languages by importing types from other non-TTCN-3 modules such as ASN.1 definitions. This, implicit mapping, is done by using the import and languagekeywords. The other approach to represent the interface on the TTCN-3 language level is to define explicit mapping, in which constructs of other languages are translated into TTCN-3 language constructs. These translated language constructs, which are defined in header files of C/C++ programs, represents the required and provided interfaces of the C/C++ software modules. The mapping defined in this document follows the explicit mapping.

2.Scope

The C/C++ header files should only include the items defined in Table 1 below and other constructs are outside of this document.

NOTE 1: The items marked as *) appears only in C++.

Table 1. C/C++ header file elements

*) Named namespaces / namespace N { /* ... */ }
Type definitions / struct Point {int x, y;};
*) Template declarations / templateclass T> class Z;
*) Template definitions / templateclass T> class V { /*...*/ };
Function declarations / externint strlen(constchar*);
Inline function definitions / inlinechar get(char* p) {return *p++;}
Data declarations / externint a;
Constant definitions / constfloat pi = 3.141593;
Enumerations / enum Light {red, yellow, green};
Typedef declarations / typedefstruct MyStruct MyStruct_t;
Name declarations / class Matrix;
Include directives / #include <algorithm>
Macro definitions / #define VERSION 12
Function like macros / #define max(a, b) ((a) > (b) ? (a) : (b))
Conditional compilation directives / #ifdef __cplusplus
Comments / /* check for end of file */

NOTE 2: Value ranges of TTCN-3 types are not restricted, thus TTCN-3 basic types (i.e. integer, float) accept all possible values, from negative infinity to positive infinity. However, some aspects of C/C++ types are implementation-defined and, for example, the sizes of integer and floating-point types depend on the characteristic of the system used. In order to provide comprehensive type mapping, a bounded range of acceptable values must be indicated in the corresponding type definitions.

3.Names and Scoping

C specific

There are four kinds of scopes in C: function, file, block, and function prototype. The scopes that TTCN-3 provides are module definition part, module control part, component types, functions, altsteps, test cases and "blocks of statements and declarations" within compound statements. TTCN-3 requires uniqueness of identifiers, i.e. all identifiers in the same scope hierarchy shall be distinctive; in some cases, C accepts a name declaration to be hidden behind a declaration of that same name. Therefore, this kind of hidden declarations should be renamed in a TTCN-3 module.

There is no global scope in TTCN-3 but all definitions are done inside modules. A module name for global declarations and definitions of C programs can be derived from the header file where the global declarations and definitions are given, for instance.

To avoid keyword clashes and to enhance readability, identifiers should always be pre- or postfixed according to its type. Subtypes derived from TTCN-3 basic types are prefixed with 'C while record types, and port types are postfixed with 'Type' and 'Port'. Record of types are prefixed with 'Arr'.

end C specific

C++ specific

Classes, structures, unions, namespaces, and global namespace (also called as global) define scopes in C++. There exists also function, function prototype scope and local scope in C++. The scopes that TTCN-3 provides are module definition part, module control part, component types, functions, altsteps, test cases and "blocks of statements and declarations" within compound statements. TTCN-3 requires uniqueness of identifiers, i.e. all identifiers in the same scope hierarchy shall be distinctive; in some cases, C++ accepts a name declaration to be hidden behind a declaration of that same name. Therefore, this kind of hidden declarations should be renamed in a TTCN-3 module.

A namespace provides a scope and grouping for definitions and declarations in C++. Similar language construct in TTCN-3 is a module. A namespace is mapped to a TTCN-3 module and a nested namespace is defined as a TTCN-3 module, which name is prefixed by the name of the enclosing module. This is also illustrated in Table 2 below.

Table 2. Mapping of named namespace

C++ / TTCN-3
namespace Namespace {
namespace NestedNamespace{ ... }
} / module Namespace { ... }
// mapping of nested namespace
module Namespace_NestedNamespace { ... }

Namespace composition and selection are mapped explicitly. That is, all the definitions and the declarations of the existing module are not imported to the composed TTCN-3 module, but instead, they are explicitly defined in the composed module. Table 3 below shows an example.

Table 3.Mapping of namespace composition

C++ / TTCN-3
namespace Namespace {
usingnamespace ExistingNamespace;
}
namespace ExistingNamespace { ... } / module NameSpace {
// all the declarations and
// defintions of ExistingNamespace
// are defined in here, as well
}
module ExistingNamespace { ... }

Class, structure, and union types provide a scope and grouping for definitions and declarations in C++ in a same way as namespaces do. Table 4 illustrates a mapping of a scope defined by a structure.

Table 4. Mapping of a structured type to a module

C++ / TTCN-3
struct Person { ... }; / module Person {
type record PersonType { ... }
}

There is no global scope in TTCN-3 but all definitions are done inside modules. A module name for global declarations and definitions of C++ programs can be derived from the header file where the global declarations and definitions are given, for instance.

To enhance readability, and to provide better distinction to TTCN-3 and C++ types, identifiers should always be pre- or postfixed according to its type. Subtypes derived from TTCN-3 basic types are prefixed with 'Cpp' while record types, and port types are postfixed with 'Type' and 'Port'. Record of types are prefixed with 'Arr'.

end C++ specific

4.Boolean Type

A boolean, denoted by the keyword bool, can have a true or a false value in C/C++. Boolean type is mapped to TTCN-3 boolean, as shown in Table 5 below.

NOTE: In C the original boolean type is _Bool, but the macro bool in the header <stdbool.h> expands to _Bool.

Table 5. Mapping of the boolean type

C/C++ / TTCN-3
bool / typeboolean CppBool;

5.Character Type

Since characters in C/C++ are actually integer types, they should be mapped to integers in TTCN-3 (see Table 6 below). If printable characters are used it has to be done by providing an integer value in decimal form defined by the corresponding character set or by using TTCN-3 predefined functions (e.g. char2int()) for conversion. In addition, C++ includes a type wchar_t[1], which is a distinct implementation-defined type and is large enough to hold the largest extended character set specified among the supported locales. wchar_t is mapped to integer as well.

Table 6. Mapping of the character types

C/C++ / TTCN-3
char
signed char
unsigned char
wchar_t / type integer CppChar (-128..127);
type CppChar CppSignedChar;
type integer CppUnsignedChar (0..255);
typeinteger CppWchar_t(0..65535);

6.Integer Types

There are four distinct signed integer types which are short (int), int and long (int) in C/C++. In addition, there exists a corresponding unsigned integer type for each signed version. Mapping of integer types is depicted in Table 7 below.

NOTE: C includes also long long type

Table 7. Mapping of the integer types

C/C++ / TTCN-3
short
signed short
short int
signed short int
unsigned short
unsigned short int
int
// etc...
long long int
unsigned long long int / type integer CppShort (-32768..32767);
type CppShort CppSignedShort;
type CppShort CppShortInt;
type CppShort CppSignedShortInt;
type integer CppUnsignedShort (0..65535);
type CppUnsignedShort CppUnsignedShortInt;
type integer CppInt (-2147483648..2147483647);
// etc...
typeinteger CLongLongInt (LLONG_MIN..LLONG_MAX) //[2]
typeinteger CUnsignedLongLongInt (0..ULLONG_MAX)

7.Floating-point Types

There are three different floating-point types in C/C++, which are float, double and long double. In TTCN-3, a keyword floatdescribes floating-point types, which is also shown in Table 8.

Table 8. Mapping of the floating-point types

C/C++ / TTCN-3
float
double
long double / const float FLT_MIN := -3.402823466E38;
const float FLT_MAX := 3.402823466E38;
type float CppFloat (FLT_MIN..FLT_MAX);
// ...
type float CppDouble (DBL_MIN..DBL_MAX);
type float CppLongDouble (LDBL_MIN..LDBL_MAX);

8.Structure Types

The data definition that a structure defines can be mapped to TTCN-3 by using the TTCN-3 ordered structured type record (Table 9). Member data can be defined as constant. Constant members are be mapped as normal member data, i.e. within record. However, the representation of the constant members shall not be modified once instantiated.

Table 9. Mapping of a structure type

C/C++ / TTCN-3
struct Person {
int age;
constint gender;
}; / type record PersonType {
CppInt age,
CppInt gender
}

C++ specific

In C++ member fields can be defined as static, or staticconstant. Static data is accessed and modified by using TTCN-3 external functions or signatures and static constant members are mapped to external constants. This is also shown in Table 13 below. In addition, C++ structure may contain also member functions as well as access specifiers, which are described in chapters 12 and 21, respectively.

Table 13. Mapping of member data

C++ / TTCN-3
struct MyClass {
const int constInt;
staticint staticInt;
staticconstint staticConstInt;
}; / module MyClass {
type record MyClassType {
// mapping of constant member
CppInt constInt
}
// mapping of static member
external function Set_staticInt(
in CppInt staticInt);
external function Get_staticInt()
return CppInt;
// or
signature Set_staticInt(
in CppInt staticInt);
signature Get_staticInt() return CppInt;
// mapping of static constant member
external const CppInt staticConstInt;
}

end C++ specific

Compound types, i.e., class, struct and union, can have their members and fields defined with bit restrictions. These restrictions are reflected in the mapped type with a range of allowed values (Table 12). Fields defined to be of zero bits are not represented in a mapped type.

Table 12.Mapping of bit size fields in structured type

C/C++ / TTCN-3
struct BitSizeStc {
unsigned int f1 : 1;
unsigned int f2 : 3;
};
union BitSizeUnion {
int f1 : 3;
int f2 : 2;
};
class BitSizeClass{
public:
unsigned int m1 : 3;
unsigned : 0;
unsigned int m2 : 2;
}; / type record BitSizeStcType {
CUnsignedInt f1 ( 0 .. 1 ), // : 1
CUnsignedInt f2 ( 0 .. 7 ) // : 3
}
type union BitSizeUnionType {
CInt f1 ( -4 .. 3 ), // : 3
CChar f2 ( -2 .. 1 ) // : 3
}
module BitSizeClass {
type record BitSizeClassType {
CppUnsignedInt m1 ( 0 .. 7 ), // : 3
CppUnsignedInt m2 ( 0 .. 3 ) // : 2
}
}

Structures can be of anonymous type in C/C++. In TTCN-3, named structure is mapped to record type and mapping of anonymous structure follows this rule but is nested and unnamed (Table 10).

Table 10. Mapping of anonymous structure

C/C++ / TTCN-3
struct Person {
int age;
struct {
char* address;
int phone;
} addrAndPhone;
}; / type record PersonType {
CppInt age,
record {
CppCharPtr addr,
CppInt phone
} addrAndPhone
}

C++ specific

A function can be declared inside the anonymous type. In this case, the signature should be prefixed with the field name of the anonymous type. Table 11 illustrates this.

Table 11.Mapping of anonymous structure with a function

C++ / TTCN-3
struct Person {
int age;
struct {
char* address;
int phone;
void MyFunction();
} addrAndPhone;
void MyFunction();
}; / type record PersonType {
CppInt age,
record {
CppCharPtr addr,
CppInt phone
} addrAndPhone
}
signatureaddrAndPhone_MyFunction();
signature MyFunction();

end C++ specific

9.Class Types

C++ specific

Class type in C++ is basically the same as struct; the only difference is that all members in a struct are public by default, whereas in class they are private. Thus mapping of class types follows the mapping of structure types described in chapter 8 above. Mapping of the access specifiers (private, protected, public) are described more detail in chapter 21.

end C++ specific

10.Union Types

Union types are mapped to union type in TTCN-3 and rest of the mapping follows the mapping of structure types. An example of mapping union is shown in Table 14 below.

Table 14.Mapping of union

C/C++ / TTCN-3
union U {
int i;
char c;
}; / typeunion UType {
CppInt i,
CppChar c
}

11.Enumeration Types

Both C/C++ and TTCN-3 support enumerated types, but they differ considerably from each other. For instance, enumerators accept negatives values in C/C++ that is not allowed by TTCN-3. Furthermore, C/C++ accepts an enumeration value to be used as an integer value e.g., to a function call while TTCN-3 enumeration values are used with the corresponding enumeration type. Therefore, C/C++ enum should be mapped to constant integers in TTCN-3 and enumerator values are grouped using TTCN-3 group statement. Table 15 below gives an example.

NOTE: There are two cases, in which literals (e.g. oct, hex) are used in C/C++ header files; when constant values are defined, or with enum members. Constants are mapped to external const, in which case actual values are hidden (see chapter 18). In the case of enum, TTCN-3 predefined functions (e.g. hex2int()) can be taken advantage of.

Table 15. Mapping of enumeration

C/C++ / TTCN-3
enum Days {
Monday = 0x01,
Tuesday = 3,
Wednesday,
Sunday = -5
}; / group Days {
const CppInt Monday := hex2int('0001'H);
const CppInt Tuesday := 3;
const CppInt Wednesday := 4;
const CppInt Sunday := -5;
}

12.Function Types

C/C++ functions declare the operations of a C/C++ interface, and a function call is the means to request something to be done by the interface implementation. Alternatively, functions declare the required interfaces that services are used by the module under test. TTCN-3 provides procedure based communication mechanism in terms of signatures and ports. C/C++ function is mapped to signature and procedureport, whereport directions are defined according to provided and required interfaces. I.e., provided functions are mapped to out direction whereas required functions are mapped to in direction as shown in Table 16 below.

Table 16. Mapping of functions

C/C++ / TTCN-3
externvoid Foo(int i);
externint Bar(); / typeport Port procedure {
in Foo; // required interface
out Bar; // provided interface
}
signature Foo(in CppInt i);
signature Bar() return CppInt;

In C/C++ there exists also a means to define unspecified number of arguments for functions. For each argument combination a dedicated signature is defined in TTCN-3 (see example in Table 17 below).

Table 17.Mapping of a function with unspecified number of arguments

C/C++ / TTCN-3
void printf(constchar* string, ...); / signature printf_int(in CppCharPtr string,
in CppInt value1);
signature printf_char_charptr(
in CppCharPtr string,
in CppChar value1,
in CppCharPtr value2);

C++ specific

C++ includes mechanism to overload functions in which functions that conceptually perform same operation get same name whereas TTCN-3 does not support overloading of signatures. To map each overloaded functions to signatures, each overloaded function in C++ must have unique signature in TTCN-3. Table 18 gives an example of this.

Table 18.Mapping of overloaded functions

C++ / TTCN-3
void print(int value);
void print(constchar* string);
void print(constchar* string) const; / signature print_int(in CppInt value);
signature print_constcharptr(
in CppCharPtr string);
signature print_constcharptr_const(
in CppCharPtr string);

C++ function declarations can provide also default arguments. Each function with default arguments shall have different number of signature declarations in TTCN-3 (see Table 19 below).

Table 19.Mapping of a function with default argument

C++ / TTCN-3
void print(int value, int base = 10); / signature print(in CppInt value);
signature print_int(in CppInt value,
in CppInt base);

Functions within structure, class, and union types are called as member functions, which can be either static or non-static (i.e. must be called for an object of its type). In TTCN-3, the signature that represents the non-static member function must take an extra parameter that defines the object for which the member function is called. The extra parameter represents the C++ this pointer and it has type derived from octetstring. Opposite to non-static member functions, static member functions are mapped without the extra parameter.

Constructor and destructor are special kind of member functions which are used to create a new object and destroy previously allocated object by using the new and delete keywords, respectively. Thus, constructor is mapped to signature which returns pointer to allocated object. Destructor is defined as a signature that takes pointer as parameter and frees the previously allocated memory. Examples of member function mappings are shown in Table 20.

Table 20. Mapping of member functions

C++ / TTCN-3
class MyClass {
MyClass();
staticvoid StaticMemberFunction();
void MemberFunction();
virtual ~MyClass();
}; / signature CMyClass() return MyClassPtr;
signature StaticMemberFunction();
signature MemberFunction(in MyClassPtr this);
signature DMyClass(in MyClassPtr this);

Operators are mapped into signatures just as ordinary functions and shall follow the rules for overloading in the same way. The ordinary calling convention in C++ and TTCN-3 differs and an operator has to be called in the C++ alternative way (Table 21).