[Previous] [Next] [Contents] [Index]


    Data Types in SDT

This chapter describes how data types are handled in SDT. An overview of all supported SDL data types is given, including examples and guidelines. It is also explained how to use C and ASN.1 in combination with SDT.

Table of Contents 

Introduction

An important and often difficult aspect of system design and implementation is how to handle data in the system.

SDT offers several ways to use data:

This chapter gives an overview of all available data types, together with some guidelines of how to use these different data types, illustrated with a number of examples.

Using SDL Data Types

In this section, an overview is given of the data types that are available in SDL. SDL contains a number of predefined data types. Based on these predefined types it is possible to define user-specific data types. Types, or according to SDL terminology, "sorts", are defined using the keywords newtype and endnewtype.


Example 1 : Newtype definition      

A newtype definition introduces a new distinct type, which is not compatible with any other type. So if we would have another newtype otherexample with exactly the same definition as example1 above, it would not be possible to assign a value of example1 to a variable of otherexample.

It is also possible to introduce types, syntypes, that are compatible with their base type, but contain restrictions on the allowed value set for the type. Syntypes are defined using the keywords syntype and endsyntype.


Example 2 : Syntype definition      

The syntype example2 is an integer type, but a variable of this type is only allowed to contain values in the specified range 0 to 10. Such a constant clause is called a range condition. The range check is performed when the SDL system is interpreted. Without a range condition a syntype definition just introduces a new name for the same sort.

For every sort or syntype defined in SDL, the following operators are always defined:

These operators are not mentioned among the available operators in the rest of this section. Operators are defined in SDL by a type of algebra according to the following example:

The double quotes around the + indicate that this is an infix operator. The above "+" takes two integer parameters and returns an integer value. The second operator, num, is a prefix operator taking one Character and returning an Integer value. The operators above can be called within expressions in, for example, task statements:

where it is assumed that i and n are integer variables. It is also allowed to call an infix operator as a prefix operator:

This means the same as i:= i+1.

Predefined Sorts

The predefined sorts in SDL are defined in an appendix to the SDL Recommendation Z100. Some more predefined sorts are introduced in the Recommendation Z105, where it is specified how ASN.1 is to be used in SDL. These types should not be used if the SDL system must conform to Z.100. SDT also offers Telelogic-specific operators for some types. These operators should not either be used if your SDL system must be Z.100 compliant. The rest of this chapter describes all predefined sorts. Unless stated otherwise, the sort is part of recommendation Z.100.

Bit

The predefined Bit can only take two values, 0 and 1. Bit is defined in Z.105 for the definition of bit strings, and is not part of Z.100. The operators that are available for Bit values are:

These operators are defined according to the following:

The Bit type has most of its properties in common with the Boolean type, which is discussed below. By replacing 0 with False and 1 with True the sorts are identical.

Bit and Boolean should be used to represent properties in a system that can only take two values, like on - off. In the choice between Bit and Boolean, Boolean is recommended except if the property to be represented is about bits and the literals 0 and 1 are more adequate than False and True.

Bit_String

The predefined sort Bit_String is used to represent a string or sequence of Bits. Bit_String is defined in Z.105 to support the ASN.1 BIT STRING type, and is not part of Z.100. There is no limit on the number of elements in the Bit_String.

The following operators are defined in Bit_String:

These operators are defined as follows:

It is also possible to access Bit elements in a Bit_String by indexing a Bit_String variable. Assume that B is a Bit_String variable. Then it is possible to write:

This would mean that Bit number 2 is assigned the value of Bit number 3 in the variable B. Is is an error to index a Bit_String outside of its length.

Note: 

The first Bit in a Bit_String has index 0, whereas most other string types in SDL start with index 1!

Boolean

The newtype Boolean can only take two values, False and True. The operators that are available for Boolean values are:

These operators are defined according to the following:

The Bit sort, discussed above, has most of its properties in common with the Boolean sort. By replacing 0 with False and 1 with True the sorts are identical. Normally it is recommended to use Boolean instead of Bit; for a more detailed discussion see Bit.

Character

The character sort is used to represent the ASCII characters. The printable characters have literals according to the following example:

Note that the character ` is written twice in the literal. For the non-printable characters, specific literal names have been included in the Character sort. The following:

correspond to the characters with number 0 to 31, while the literal

corresponds to the character number 127.

The operators available in the Character sort are:

The interpretation of these operators are:

Charstring

The Charstring sort is used to represent strings or sequences of characters. There is no limit for the length of a Charstring value. Charstring literals are written as a sequence of characters enclosed between two single quotes: `. If the Charstring should contain a quote (`) it must be written twice.

Note the somewhat strange rule in SDL that several consecutive spaces are treated as one space. This means that the two literals below are identical:

The following operators are available for Charstrings:

These operators are defined as follows:

It is also possible to access Character elements in a Charstring by indexing a Charstring variable. Assume that C is a Charstring variable. Then it is possible to write:

This would mean that Character number 2 is assigned the value of Character number 3 in the variable C.

Note: 

The first Character in a Charstring has index 1.

IA5String, NumericString, PrintableString, VisibleString

These Z.105 specific character string types are all syntypes of Charstring with restrictions on the allowed Characters that may be contained in a value. These sorts are mainly used as a counterpart of the ASN.1 types with the same names. The restrictions are:

It is recommended to use these types only in relation with ASN.1 or TTCN. In other cases use Charstring.

Duration, Time

The Time and Duration sorts have their major application area in connection with timers. The first parameter in a Set statement is the time when the timer should expire. This value should be of sort Time.

Both Time and Duration have literals with the same syntax as real values. Example:

The following operators are available in the Duration sort:

The following operators are available in the Time sort:

The interpretation of these operators are rather straightforward, as they correspond directly to the ordinary mathematical operators for real numbers. There is one "operator" in SDL that returns a Time value; Now which returns the current global system time.

Time should be used to denote `a point in time', while Duration should be used to denote a `time interval'. SDL does not specify what the unit of time is. In SDT, the time unit is usually 1 second.


Example 3 : Timers in SDL      

After the above statement, SDL timer MyTimer will expire after 2.5 time units (usually seconds) from now.


You should note that according to SDL, Time and Duration (and Real) possess the true mathematical properties of real numbers. In an implementation, however, there are of course limits on the range and precision of these values.

Integer, Natural

The Integer sort in SDL is used to represent the mathematical integers. Natural is a syntype of Integer, allowing only integers greater than or equal to zero.

Integer literals are defined using the ordinary integer syntax. Example:

Negative integers are obtained by using the unary - operator given below. The following operators are defined in the Integer sort:

The interpretation of these operators are given below:

Null

Null is a sort coming from ASN.1, defined in Z.105. Null does occur rather frequently in older protocols specified with ASN.1. ASN.1 has later been extended with better alternatives, so Null should normally not be used. The sort Null only contains one value, Null.

Object_Identifier

The Z.105-specific sort Object_Identifier also comes from ASN.1. Object identifiers usually identify some globally well-known definition, for example a protocol, or an encoding algorithm. Object identifiers are often used in open-ended applications, for example in a protocol where one party could say to the other `I support protocol version X'. `Protocol version X' could be identified by means of an object identifier.

An Object_Identifier value is a sequence of Natural values. This sort contains one literal, EmptyString, that is used to represent an Object_Identifier with length 0. The operators defined in this sort are:

These operators are defined as follows:

It is also possible to access the Natural elements in an Object_Identifier by indexing an Object_Identifier variable. Assume that C is a Object_Identifier variable. Then it is possible to write:

This would mean that the Natural at index 2 is assigned the value of the Natural at index 3 in the variable C. Note that the first Natural in an Object_Identifier has index 1. It is an error to index an Object_Identifier outside of its length.

Octet

The Z.105-specific sort Octet is used to represent eight-bit values, i.e. values between 0 and 255. In C this would correspond to unsigned char. There are no explicit literals for the Octet sort. Values can, however, easily be constructed using the conversion operators I2O and O2I discussed below.

The following operators are defined in Octet:

The interpretation of these operators is as follows:

It is also possible to access the individual bits in an Octet value by indexing an Octet variable. The index should be in the range 0 to 7.

Octet should be used to represent bytes. Octet replaces the SDT supplied Byte ADT.

Octet_String

The Z.105-specific sort Octet_String represents a sequence of Octet values. There is no limit on the length of the sequence. The operators defined in the Octet_String sort are:

These operators are defined as follows:

It is also possible to access the Octet elements in an Octet_String by indexing an Octet_String variable. Assume that C is an Octet_String variable. Then it is possible to write:

This would mean that the Octet at index 2 is assigned the value of Octet at index 3 in the variable C. It is an error to index an Octet_String outside of its length.

Note: 

The first Octet in an Octet_String has index 0, whereas most other string types in SDL start with index 1!

PId

The sort PId is used as a reference to process instances. PId has only one literal, Null. All other values are obtained from the SDL predefined variables Self, Sender, Parent, and Offspring.

Real

Real is used to represent the mathematical real values. In an implementation there are of course always restrictions in size and precision of such values. Examples of Real literals:

The operators defined in the Real sort are:

All these operators have their ordinary mathematical meaning.

User Defined Sorts

All the predefined sorts and syntypes discussed in the previous section can be directly used in, for example, variable declarations. In many circumstances it is however suitable to introduce new sorts and syntypes into a system to describe certain properties of the system. A user-defined sort or syntype can be used in the unit where it is defined, and also in all its subunits.

Syntypes

A syntype definition introduces a new type name which is fully compatible with the base type. This means that a variable of the syntype may be used in any position where a variable of the base type may be used. The only difference is the range check in the syntype.

Syntypes are useful for:


Example 4  : Syntype definition      

In this example smallint is the new type name, integer is the base type, and 0:10 is the range condition. Range conditions can be more complex than the one above. It may consist of a list of conditions, where each condition can be (assume X to be a suitable value):


Example 5 : Syntype definition      

In this example all values <-5, 0, 1, 2, 3, 5, 8, >=13 are allowed.

The range check introduced in a syntype is tested in the following cases (assuming that the variable, signal parameter, formal parameter involved is defined as a syntype):

Enumeration Sorts

An enumeration sort is a sort containing only the values enumerated in the sort. If some property of the system can take a relatively small number of distinct values and each value has a name, an enumeration sort is probably suitable to describe this property. Assume for example a key with three positions; off, stand-by, and service-mode. A suitable sort to describe this would be:


Example 6 : Enumeration sort      

A variable of sort KeyPosition can take any of the three values in the literal list, but no other.

Struct

The struct concept in SDL can be used to make an aggregate of data that belong together. Similar features can be found in most programming languages. In C, for example, it is also called struct, while in Pascal it is the record concept that has these properties. If, for example, we would like to describe a person and would like to give him a number of properties or attributes, such as name, address, and phone number, we can write:

A struct contains a number of components, each with a name and a type. If we now define variables of this struct type,

it is possible to work directly with complete struct values, like in assignments, or in tests for equality. Also individual components in the struct variable can be selected or changed.

The first task is an assignment on the struct level. The right hand side, i.e. the (. .) expression, is an application of the implicit Make operator, that is present in all structs. The Make operator takes a value of the first component sort, followed by a value of the second component sort, and so on, and returns a struct value where the components are given the corresponding values. In the example above, the component Name in variable p1 is given the value `Peter'. The second task shows a test for equality between two struct expressions. The third and fourth task shows how to access a component in a struct. A component is selected by writing:

Such component selection can be performed both in a expression (then usually called Extract) and in the left hand side of an assignment (then usually called Modify).

Bit Fields

A bit field defines the size in bits for a struct component. This feature is not part of the SDL Recommendation, but rather introduced by Telelogic to enable the generation of C bit fields from SDL. This means that the syntax and semantics of bit fields follow the C counterpart very much.


Example 7 : Bit fields      

The following rules apply to bit fields:

Bit fields should only be used when it is necessary to generate C bit fields from SDL. Bit fields should not be used as an alternative to syntypes with a constants clause; SDT does not check violations to the size of the bit fields.

Optional and Default values

To simplify the translation of ASN.1 types to SDL sorts, two new features have been introduced into structs. Struct components can be optional and they can have default values. Note that these features have their major application area in connection with ASN.1 data types and applying them in other situations is probably not a good idea, as they are not standard SDL-96.


Example 8 : Optional and default values      

The default values for component c and d, means that these components are initialized to the given values.

An optional component may or may not be present in a struct value. Initially an optional component is not present. It becomes present when it is assigned a value. It is an error to access a component that is not present. It is possible to test if an optional component is present or not by calling an implicit operator called

In the example above aPresent(v) and ePresent(v) can be used to test whether components a and e are present or not in the value stored in variable v.

Components with default values also have Present operators. They however always return True! This somewhat strange semantics is according to the definition in Z105.

Choice

The new concept choice is introduced into SDL as a means to represent the ASN.1 concept CHOICE. This concept can also be very useful while developing pure SDL data types. The choice in SDL can be seen as a C union with an implicit tag field.


Example 9 : Choice      

The example above shows a choice with three components. The interpretation is that a variable of a choice type can only contain one of the components at a time, so in the example above a value of C1 either contains an Integer value, a Charstring value, or a Boolean value.


Example 10 : Working with a choice type      

The above example shows how to modify and extract components of a choice type. In this respect, choice types are identical to struct types, except the a:5 notation to denote choice values, whereas struct values are described using (. ... .).

Extracting a component of a choice type that is not present results in a dynamic error. Therefore it is necessary to be able to determine which component is active in a particular value. For that purpose there are a number of implicit operators defined for a choice.

where v is a variable of a choice type, returns a value which is the name of the active component. This is made possible by introducing an implicit enumeration type with literals with the same names as the choice components. Note that this enumeration type is implicit and should not be inserted by you. Given the example above, it is allowed to test:

This is illustrated in Figure 26.

Figure 26 : Check which component of a choice is present

Extracted pic [15]

It is also possible to test if a certain component is active or not, by using the implicit boolean operators ComponentNamePresent. To check if component b in the example above is present it is thus possible to write:

The information about which component that is active can be accessed using the Present operators, but it is not possible to change it. This information is automatically updated when a component in a choice variable is assigned a value.

The purpose of choice is to save memory or bandwidth. As it is known that only one component at a time can contain a value, the compiler can use overlay techniques to reduce the total memory for the type. Also sending a choice value over a physical connection saves time, compared to sending a corresponding struct.

The choice construct is Telelogic-specific, and not part of recommendation Z.105, so if you want to write portable SDL, you should not use choice. Choice replaces the SDT #UNION code generator directive. It is recommended to replace #UNION directives by choice, as SDT has better tool support for the latter.

Inherits

It is possible to create a new sort by inheriting information from another sort. It is possible to specify which operators and literals that should be inherited and it is then possible to add new operators and literals in the new type.

Note that it is not really possible to change the type in itself by using inheritance. It is, for example, not possible to add a new component to a struct when the struct is inherited.

Our experience with inheritance so far has been that it is not as useful as it might seem in the beginning, and that sometimes the use of inheritance leads to the need of qualifiers in a lot of places, as many expressions are no longer semantically valid.


Example 11 : Inherits      

In the example above a new type NewInteger is introduced. This type is distinct from Integer, i.e. an Integer expression or variable is not allowed where a NewInteger is expected, and a NewInteger expression or variable is not allowed where an Integer is expected. Since in the example all literals and operators are inherited, all the integer literals 0, 1, 2, ..., are also available as NewInteger literals. For operators it means that all operators having Integer as parameter or result type are copied, with the Integer parameter replaced with a NewInteger parameter. This is true for all operators, not only those defined in the Integer sort, which may give unexpected effects, which will be illustrated below.


Example 12 : Inherited operators      

The following operators are some of the operators having Integer as parameter or result type:

The type NewInteger defined above will inherit these and all the others having integer as parameter or result type. Note that Length is defined in the Charstring sort.


With this NewInteger declaration, statements like

are no longer correct in the SDL system. It is no longer possible to determine the types in the expression above. It can either be the Length returning integer that is tested against an integer literal, or the Length returning a NewInteger value that is tested against a NewInteger literal.

It is possible to avoid this kind of problem by specifying explicitly the operators that should be inherited.


Example 13 : Inherits      

Now only the enumerated operators are inherited and the problem with Length that was discussed above will not occur.

Predefined Generators

Array

The predefined generator Array takes two generator parameters, an index sort and a component sort. There are no restrictions in SDL on the index and component sort.


Example 14 : Array instantiation      

The example above shows an instantiation of the Array generator with Character as index sort and Integer as component sort. This means that we now have created a data structure that contains one Integer value for each possible Character value. To obtain the component value connected to a certain index value it is possible to index the array.


Example 15 : Using an array type      

The example above shows how to work with arrays. First we have the expression (. 3 .). This is an application of the Make! operator defined in all array instantiations. The purpose is to return an array value with all components set to the value specified in Make. The first task above thus assigns the value 3 to all array components. Note that this is an assignment of a complete array value.

In the second task the value of the array component at index `a' is extracted and assigned to the integer variable Var_Integer. In the third task the value of the array component at index `x' is modified and given the new value 11. The second and third task shows applications of the operators Extract! and Modify! which are present in all array instantiations. Note that the operators Extract!, Modify!, and Make! can only be used in the way shown in the example above. It is not allowed to directly use the name of these operators.

In the last statement, the decision, an equal test for two array values is performed. Equal and not equal are, as well as assignment, defined for all sorts in SDL.

The typical usage of arrays is to define a fixed number of elements of the same sort. Often a syntype of Integer is used for the index sort, as in the following example, where an array of 11 PIds is defined with indices 0 to 10.


Example 16 : Typical array definition      

Unlike most ordinary programming languages, there are no restrictions on the index sort in SDL. In most programming languages the index type must define a finite range of values possible to enumerate. In C, for example, the size of an array is specified as an integer constant, and the indices in the array range from 0 to the (size-1). In SDL, however, there are no such limits.


Example 17 : Array with infinite number of elements.      

Having Real as index type means that there is an infinite number of elements in the array above. It has, however, the same properties as all other arrays discussed above. This kind of more advanced arrays sometimes can be a very powerful concept that can be used for implementing, for example, a mapping table between different entities.


Example 18 : Array to implement a mapping table      

The above type can be used to map a Charstring representing a name to a PId value representing the corresponding process instance.


String

The String generator takes two generator parameters, the component sort and the name of an empty string value. A value of a String type is a sequence of component sort values. There is no restriction on the length of the sequence. The predefined sort Charstring, for example, is defined as an application of the String generator.


Example 19 : String generator      

Above, a String with Integer components is defined. An empty string, i.e. a string with the length zero, is represented by the literal Empty.

The following operators are available in instantiations of String.

In this enumeration of operators, String should be replaced by the string newtype (S1 in the example above) and Itemsort should be replaced by the component sort parameter (Integer in the example above). The operators have the following behavior, with the examples based on type String (Integer, Empty):

It is also possible to access Itemsort elements in a String by indexing a String variable. Assume that C is a String instantiation variable. Then it is possible to write:

This would mean that Itemsort element number 2 is assigned the value of Itemsort element number 3 in the variable C. NOTE that the first element in a String has index 1. It is an error to index a String outside of its length.

The String generator can be used to build lists of items of the same type, although some typical list operations are computationally quite expensive, like inserting a new element in the middle of the list.

Powerset

The Powerset generator takes one generator parameter, the item sort, and implements a powerset over that sort. A Powerset value can be seen as: for each possible value of the item sort it indicates whether that value is member of the Powerset or not.

Powersets can often be used as an abstraction of other, more simple data types. A 32-bit word seen as a bit pattern can be modeled as a Powerset over a syntype of Integer with the range 0:31. If, for example, 7 is member of the powerset this means that bit number 7 is set.


Example 20 : Powerset generator      

The only literal for a powerset sort is Empty, which represents a powerset containing no elements. The following operators are available for a powerset sort (replace Powerset with the name of the newtype, P1 in the example above, and ItemSort with the ItemSort parameter, SmallInteger in the example):

These operators have the following interpretation (the examples are based on newtype P1 of the above example, and it is supposed that variable v0_1_2 of P1 contains elements 0, 1, and 2):

Figure 27 : Computing the sum of all elements in a Powerset

Extracted pic [14]

Powerset resembles the Bag operator, and normally it is better to use Powerset. See also the discussion in Bag.

Bag

The Z.105-specific generator Bag is almost the same as Powerset. The only difference is that a bag can contain the same value several times. In a Powerset a certain value is either member or not member of the set. A Bag instantiation contains the literal Empty and the same operators, with the same behavior, as a Powerset instantiation. For details please see Powerset.

A Bag contains one additional operator:

It is recommended to use Powerset instead of Bag, except in cases where the number of instances of a value is important. Powerset is defined in Z.100, and is therefore more portable. Bag is mainly part of the predefined data types in order to support the ASN.1 SET OF construct.

Literals

Literals, i.e. named values, can be included in newtypes.


Example 21 : Literals in struct newtype      

In this struct there are two named values (literals); Origo and One. The only way in SDL to specify the values these literals represent is to use axioms. Axioms can be given in a section in a newtype. This is not further discussed here. The SDT code generators provide other ways to insert the values of the literals. Please see the documentation in The Cadvanced/Cbasic Code Generator.

The literals can be used in SDL actions in the same way as expressions.


Example 22 : Use of literals      

Operators

Operators can be added to a newtype in the same way as literals.


Example 23 : Operators in struct newtype      

The behavior of operators can either be defined in axioms (as the literal values) or in operator diagrams. An operator diagram is almost identical to a value returning procedure (without states). In the SDT Code Generators there is also the possibility to include implementations in the target language.

Default Value

In a newtype or syntype it is possible to insert a default clause stating the default value to be given to all variables of this type.


Example 24 : Default value in struct newtype      

All variables of sort Coordinates will be given the initial value
(. 0, 0 .)
, except if an explicit default value is given for the variable in the variable declaration.


Example 25 : Explicit default value in variable declaration      

Here C1 has an explicit default value that is assigned at start-up. C2 will have the default value specified in the newtype.

Generators

It is possible in SDL to define generators with the same kind of properties as the pre-defined generators Array, String, Powerset, and Bag. As this is a difficult task and the support from the SDT Code Generators is limited (for C) or non-existing (in CHILL), it is not recommended for a non-specialist to try to define a generator.

The possibility to use user defined generators in the C Code Generator is described in more detail in Generators.

Using C in SDL

SDT offers support for integrating C code with SDL. This makes it possible to re-use existing software, written in C, in SDL, which enables a smoother transition from C to SDL.

The following mechanisms in SDT enable integration between SDL and C code:

Mapping C to SDL

This section describes how C data types and functions are represented in SDL. This is explained by means of tables that represent a mapping from C data types to SDL and back. The tables can be regarded as a two-way mapping:

C Types with a Direct SDL Counterpart

The table below lists the C types for which a direct equivalent in SDL is available, either as a predefined SDL sort, or as a sort in the SDL package ctypes (see C Specific Package ctypes).

C type SDL sort Defined in package
char
Character
Predefined
unsigned char
Octet
Predefined
int
Integer
Predefined
short int
ShortInt
ctypes
long int
LongInt
ctypes
unsigned int
UnsignedInt
ctypes
unsigned short int
UnsignedShortInt
ctypes
unsigned long int
UnsignedLongInt
ctypes
float
Float
ctypes
double
Real
Predefined
void *
VoidStar
ctypes
void **
VoidStarStar
ctypes
char *
CharStar
ctypes

The C types long long int and unsigned long long int are mapped to the SDL sorts LongLongInt and UnsignedLongLongInt respectively. However, these double-word integral types are extensions to the ANSI C standard and are therefore not supported by all C compilers. For this reason the corresponding SDL sorts are not present in the ctypes package. If you wish to use the long long types you may write these SDL sort definitions yourself (they are very similar to LongInt and UnsignedLongInt) or retrieve them from Telelogic Support.

C Types with No Direct SDL Equivalent

For other C types there is no directly corresponding SDL sort available, and a syntype or newtype must be constructed. The following table gives a basic mapping of how other C types can be mapped to SDL syntypes or newtypes. In the below table, Ref and CArray are generators that are defined in package ctypes, see C Specific Package ctypes for a description of these generators.

C type SDL sort
typedef x y;
syntype y = x endsyntype;
typedef x *y;
newtype y Ref(x) endnewtype;
typedef x y[20];
newtype y CArray(20, x)
endnewtype;
typedef enum
  { a, b } x;
or alternatively:
typedef int x;
#define a 0
#define b 1
newtype x literals a, b
endnewtype;
or alternatively:
syntype x = Integer endsyntype;
synonym a x = 0; 
synonym b x = 1;
typedef struct
 { int a; } x;
newtype x struct
  a Integer;
endnewtype;
typedef struct
 { int a:2;
   int b:6; } x;
newtype x struct
  a Integer:2;
  b Integer:6;
endnewtype;
typedef union
  { int a; 
    char b; } x;
newtype x /*#UNIONC*/ struct
  a Integer; b Character;
endnewtype;

Note: 

H2SDL by default maps enum types to enumerated SDL sorts (i.e. newtypes with literals). Optionally it can, however, map them to syntypes of Integer. The C Code Generator maps an enumerated SDL sort to an int type together with macro constants, not to an enum type.

C Functions

C function prototypes are mapped to external procedures in SDL. External procedures are a new feature in SDL-96. An external procedure is called in the same way as a normal procedure. The table below shows the basic mapping scheme of function prototypes to SDL.

C SDL
void func (par1 type1,
           par2 type2, ..);
procedure func;
fpar par1 type1,
     par2 type2, ...;
external;
type1 func (par1 type1, ..);
procedure func;
fpar par1 type1, ...;
returns type1;
external;
void func (par1 *type1);
procedure func;
fpar in/out par1 type1;
external;

Pointer parameters of functions can be handled in two different ways. As an example we take the char * parameter in the function declaration
void fn (char *par1); The two ways to translate this are:

  1. Use of an in/out parameter:

  2. procedure fn; fpar in/out par1 Character; external;
    
    
    The function is called with a non-pointer parameter.

    call fn (c); /* c variable of type Character */
    
    
  3. Use of an in-parameter of the corresponding pointer type:

  4. procedure fn; fpar par1 CharStar; external;
    
    
    The function is called with a pointer parameter.

    call fn (&c);  /* c variable of type Character */
    call fn (cst); /* cst variable of type CharStar */
    
    

In the above example, &c denotes the address of variable c. With in/out parameters, only variables are allowed as argument. Therefore, the second way is a bit more general. H2SDL uses the second alternative.

Constants

Constants in C are often expressed using macros. They can be mapped to `normal' synonyms or to external synonyms. As an example we consider:

In normal cases, this can be mapped to a normal synonym:

If the above C constant has been defined in C code that is included in the generated SDL code, it should be mapped to an external synonym:

The same mappings are valid for C constants defined with const. For example the C constant below is from an SDL point of view the same as the macro above:

H2SDL cannot handle macros, but it can handle const variables, and will map these to external synonyms. The C Code Generator maps synonyms to C macros, while no C code at all is generated for external synonyms.

Also note that it is possible to access C macro values from SDL using the implicit #CODE operator. See Constant Variable Declarations.

The #C Code Generator Directive

If we have a C header, and we mapped C types to corresponding SDL sorts according to the above mapping rules, how do we know that the C Code Generator will generate the right C code back? This can be accomplished by putting the SDL sorts in a package that is provided with code generator directive #C `filename.h'. The C code generator will handle such a package in the following way:


Example 26 : Package with #C directive      

With the mapping described in this section, we would get the following package:

The C code generated for this package will use the original definitions in myheader.h. By using package mypackage, an SDL system has access to s, MAX, and fn.


C Specific Package ctypes

Telelogic offers a special package ctypes that contains data types and generators that match C. It is described in detail in The ADT Library. The ctypes package should be used in the following cases:

The tables below list the data types and generators in ctypes and their C counterparts.

SDL Sort Corresponding C Type
ShortInt
short int
LongInt
long int
UnsignedShortInt
unsigned short int
UnsignedInt
unsigned int
UnsignedLongInt
unsigned long int
Float
float
CharStar
char *
VoidStar
void *
VoidStarStar
void **

SDL Generator Corresponding C Declarator
CArray
C array, i.e. []
Ref
C pointer, i.e. *

The rest of this section explains how these data types and generators can be used in SDL.

Different Int Types and Float

ShortInt, LongInt, UnsignedShortInt, UnsignedInt, UnsignedLongInt are all defined as syntypes of Integer, so from an SDL point of view, these data types are really the same, and the normal Integer operators can be used on these types. The only difference is that the code that is generated for these types is different. Float is defined as a syntype of Real.

CharStar, VoidStar, VoidStarStar

CharStar represents character strings (i.e. char *) in C. CharStar is not the same as the SDL predefined type Charstring! CharStar is useful when accessing C functions and data types that use char *. In other cases it is better to use Charstring instead (see also Charstring). Conversion operators between CharStar and Charstring are available (see below).

VoidStar corresponds to void * in C. This type should only be used when accessing C functions that have void * parameters, or that return void * (in which case it is advised to `cast' the result directly to another type).

VoidStarStar corresponds to void ** in C. This type is used in combination with the Free procedure described in Using Pointers in SDL. In rare cases this type is also needed to access C functions.

The following conversion operators in ctypes are useful:

These operators have the following behavior:

The CArray Generator

The generator CArray in package ctypes is useful to define arrays that have the same properties as C arrays. CArray takes two generator parameters; an integer value and a component sort.


Example 27 : CArray instantiation      

The defined type IntArr is an array of 10 integers with indices 0 to 9, corresponding to the C type


Two operators are available on instantiations of CArray; Modify! to change one element of the array, and Extract! to get the value of one element in the array. These operators are used in the same way as in normal SDL arrays, see Array. There is no (. ... .) notation provided for denoting values of whole CArrays.


Example 28 : Use of CArray in SDL      

If a C array is used as parameter of an operator, it will be passed by address, just as in C. This makes it possible to write operators that change the contents of the actual parameters. In standard SDL this would not be possible.

The Ref Generator

The generator Ref in package ctypes is used to define pointer types. The following example illustrates how to use this generator.


Example 29 : Defining a pointer type      

The sort ptr is a pointer to Integer.


Standard SDL has no pointer types. Pointers have properties that cannot be defined in normal SDL. Therefore they should be used very carefully. Before explaining how to use the Ref generator, it is worthwhile to list some of the dangers of using pointers in SDL.

Pointers Will Lead to Data Inconsistency

If more than one process can read/write to the same memory location by means of pointers, data inconsistency can and will occur! Some examples:

Even though tools such as the Simulator and Validator will be able to detect a number of errors regarding pointers, there are situations that cannot be detected with these tools! This is because the Validator and Simulator assume a scheduling atomicity of at best one SDL symbol at a time. This may not hold in target operating systems where one process can be interrupted at any time (pre-emptive scheduling). If pointers are used, data is totally unprotected, and data inconsistency may occur, even though the Validator did not discover any problems! All these problems can be avoided by using SDL constructs for accessing data, like remote procedures and signal exchange.

Caution! 

For the above stated reasons, NEVER PASS POINTERS TO ANOTHER PROCESS!!! Not in an output, not in a remote procedure call, not in a create, not by exported/revealed variables, never!

And if you do not obey this rule anyway: after passing a pointer, release immediately the `old' pointer to prevent having several pointers to the same data area. For example (for some pointer p):

Pointers Are Unpredictable

If you have an SDL system that always works except during demonstrations, then you have used pointers! Bugs with pointers may be very hard to discover, as a system may (accidentally) behave correctly for a long time, but then suddenly strange things may happen. Finding such bugs may take very long time; in rare cases you might not find them at all!

Caution! 

BUGS CAUSED BY POINTERS MAY BE HARD TO FIND!!!

Pointers Do Not Work in Real Distributed Systems

If an SDL system is `really' distributed, i.e. where processes have their own memory space, it makes no sense to send a pointer to another process, as the receiving process will not be able to do anything with it. Therefore, by communicating pointers to other processes, limitations are posed on the architecture of the target implementation.

Pointers Are Not Portable

The Ref generator and its operators are completely Telelogic-specific. It is highly unlikely that SDL systems using pointers will run on other SDL tools.

Using Pointers in SDL

If you still want to use pointers in SDL after all these warnings, this section explains how to do this. A pointer type created by the Ref generator always has a literal value null (corresponds to NULL in C), which is also the default value. The literal Alloc is used for the dynamic creation of new memory. Examples are given later.

Note: 

It is up to the user to keep track of all dynamically allocated data areas and to free them when they are no longer needed.

The following operators are available for Ref types:

Furthermore, the following procedure is defined:

These operators can be used in the following way:


Example 30 : Use of the Ref operators      

Using Linked Structures with Pointers

Pointers are useful when defining linked structures like lists or trees. In this section we give an example of a linked list containing integer values. Figure 28 shows an SDL fragment with data type definitions for a linked list, and part of a transition that actually builds a linked list. A list is represented by a pointer to an Item. Every Item contains a pointer next to the next item in the list. In the last item of the list, next = Null.

Figure 28 : Building a linked list

Extracted pic [6]

Figure 29 shows an SDL fragment where the sum of all elements in a list is computed. Note that this computation would never stop if there would be an element that points back in the list, just to illustrate how easy it is to make errors with pointers.

Figure 29  : Going through the list

Extracted pic [5]

Using C Headers in SDL

In SDT, it is possible to have C header files as diagrams in the Organizer. These headers can then be used in an SDL system as if they were packages, thus offering a smooth way to integrate SDL and C. This section describes how to organize C headers in SDT, how to use the C data types in SDL, and how to overcome some of the restrictions imposed by SDT.

For a good understanding of how to use C headers in SDL, you should have carefully studied the section Mapping C to SDL that deals with how C types are converted to SDL.

The use of C headers will be illustrated with an example based on the AccessControl system described in Object Oriented Design Using SDL. In this chapter we will assume that the information about cards used to enter a door is maintained by an external database. There are two C headers:

The two headers are listed below.

Organizing C Headers in SDT

We recommend that you create a chapter in the Organizer (for example called C Headers) that contains all C headers used by the SDL system. If there are many C headers in use (which normally should be avoided, see Problems with Type Conflicts), it is a good idea to group related C headers together in Organizer Modules.

In this chapter we could add new C header diagrams and connect them to access.h and valid.h respectively. A difficulty in our example case is that the function declarations in valid.h use data types defined in access.h. For example OpenCardDb in valid.h uses CardDbType, but this type is defined in access.h.

In C this will not cause conflicts if C modules include access.h before valid.h. We could try to imitate this by "using in" SDL package access before valid, but unfortunately, packages in SDL and C headers do not behave the same way in this respect, and we would get semantic errors when analyzing package valid.

We can solve this case by creating a new header file cardbase.h that only consists of #include's to access.h and valid.h in the right order.

This is the header that will be used by SDL. So we can add a new diagram `C Header' and connect it (using Edit/Connect/To an existing file) to cardbase.h.

In order to use the file in the SDL system, we can add the following use clauses to the package reference clause text symbol SDL system diagram:

This is also illustrated in Figure 30.

Figure 30  : Using cardbase.h in SDL

Extracted pic [3]

Package ctypes is a special package supplied with SDT that contains the SDL definitions of predefined C data types. ctypes is described in detail in C Specific Package ctypes. Every SDL system that uses C headers must also include this package. You do not have to worry where to find this package: when analyzing the system, the Organizer will automatically detect that ctypes is used, and connect it to the right file (if not already present). Package ctypes will then automatically pop up in the Organizer structure.

Note: 

It is very important that the correct version of the ctypes package is present in the Organizer. If you experience strange errors when compiling or linking the generated C code, the reason may be that an old version of ctypes was used. To minimize this risk, always remove the ctypes icon from systems loaded into a new version of SDT. The Organizer will then automatically locate the correct version of the package.

Figure 31 below shows the Organizer view after analyzing the system. The symbol below the AccessControl system symbol is a dependency link that indicates that the SDL system depends on an external C header. Dependency links for C headers that are used were previously required by the Analyzer, but now only serve as comments and are optional.

Figure 31 : Organizer View of AccessControl with C Headers

Extracted pic [4]

Using the C Types and Functions in SDL

Now that we have included C headers as part of the SDL system, we can use the data types and functions defined in these headers. Figure 32 below shows the graph of an SDL process that uses functions and data types from the Access Control example.

Figure 32  : Using C types and functions in SDL

Extracted pic [16]

How Does It Work?

In order to clearly understand the restrictions of using C headers with SDL, it is important to have some understanding of how this is implemented in SDT.

When an SDL system using C headers is analyzed, the C headers will be translated by the H2SDL tool. H2SDL will first call a C preprocessor to resolve all macros, #ifdefs, etc. This also means that macros are not translated to SDL! The section When the Built-in Translation Rules Fail describes some ways to circumvent this restriction.

The resulting C code is converted to an SDL package according to translation rules described in The H2SDL Utility. This package is then included in the final SDL-PR file that is the input to the Analyzer.

Problems with Type Conflicts

Special attention is needed for generated "in-line types". As an example, consider the following function declaration:

In SDL, there is no type that corresponds directly to int *, so H2SDL will generate a type with a dummy name that corresponds to int *. The generated SDL package will use this type for all int * occurrences in the same package. However, an int * in another C header diagram would translate to another dummy type with another name. Assume for example that another C header diagram contains the following declaration:

The return type of fn2 would then in SDL not be considered to be the same as the parameter type of fn1. The SDL task below would therefore cause a type conflict:

In order to prevent unexpected problems with type compatibility of in-line types, it is recommended to use only one C diagram per SDL system that includes all used C headers.

But even if this recommendation is followed, problems with type conflicts may arise in some cases, as shown in Example 31 below.


Example 31  : Type conflicts when using C headers with SDL      

Assume that an SDL system needs to use the definitions from two separate C headers H1.h and H2.h. Following the recommendation above we make a new C header wrapper.h which includes H1.h and H2.h in the correct order. But now suppose that one of these headers contains the following declaration:

H2SDL will translate this to an SDL struct with the name Duration. But a type with that name already exists in the predefined SDL package predef which is automatically included in all SDL systems. Although it is legal to have types with the same name in different packages, we would need to use qualifiers when referring to the different Duration types in the SDL system. However, by placing a #define in wrapper.h we can "rename" the Duration that comes from the C header. Thereby we can distinguish between the types without bothering about qualifiers. Thus the final wrapper.h should look something like:

Now, the C header type Duration can be referred to as CDuration while the predefined type Duration keeps its name.


When the Built-in Translation Rules Fail

The translation rules implemented in H2SDL may not always be the most suitable for a specific implementation. For example, the C type char is mapped to the SDL sort Character, but in some cases a mapping to the SDL sort Octet may be more appropriate. Another restriction is that H2SDL relies on a C preprocessor to resolve #ifdefs, #defines, etc. This means that C macros cannot be translated to C.

The following actions can be taken to overcome such restrictions:

Each of these possibilities is discussed in the sections below.

Using H2SDL Options

The best way to change the default behavior of H2SDL is to use its options. These options are described in Command-Line Options and in Setting Options for the Preprocessor and H2SDL. Unfortunately there are currently only a few options available for controlling the translation rules used by H2SDL.

Changing the C Header

The smoothest way to change the C header, is to edit the C header itself. This may, for example, be used to replace macro definitions for types or functions. For this purpose the macro __H2SDL__ can be used. This macro is only defined during C to SDL translation (so it is not defined when C code generated from SDL is compiled by the C compiler). This property of __H2SDL__ can be exploited by "cheating" the C Code Generator.

The following examples illustrate how __H2SDL__ can be exploited to change C headers to make macros and functions with a variable number of parameters available in SDL.


Example 32 : Macro `types' in C headers      

In the C fragment above, the macro BYTE is used as if it were a type. The preprocessor will resolve all BYTE occurrences, so BYTE is not available in SDL. This can be circumvented, changing this definition to the following:

Now BYTE is available as a type in SDL (because during C to SDL translation, __H2SDL__ will be defined), but in the generated C code, BYTE is a macro (because then, __H2SDL__ will be undefined).



Example 33 : Macro `functions' in C headers      

putchar is defined as a macro, that is used as if it were a function. The following change makes putchar available in SDL.

With the above definition, putchar will be regarded as an external procedure by the SDL system (because then, __H2SDL__ will be defined). When the C code generated from SDL is compiled, the C preprocessor will resolve the `function calls' to putchar (because then, __H2SDL__ will be undefined).



Example 34  : "Typeless" macro parameters in C headers      

max is used as a macro that could be used for any type for which > is defined. In SDL such a `typeless' definition would not be possible. However, we could introduce specific definitions for specific types. The following definition makes a floatmax available in SDL for float, and an intmax for int.



Example 35 : C functions with a variable number of parameters      

fprintf is a function with an unknown number of parameters. In the SDL translation, fprintf will be available as a procedure with two parameters (pointer to FILE and pointer to Character). Just as in Example 34, we have added specific functions in order to make specific parameter combinations available in SDL.


Adding Definitions in a Separate SDL Package

Constants defined in C headers as macros are not translated to SDL because the C preprocessor will filter them out. Such constants can be added as external synonyms in a separate package.


Example 36 : Constants defined as C macros      

Suppose the C header myheader.h contains the following definitions:

To make MAXLEN and VERSION available as synonyms in SDL, the following definitions can be put in a separate package:

This package should "use myheader;". The code generator will then use the definitions from myheader.h.

An alternative solution is to convert the macros to const definitions:

Such const definitions can be handled by H2SDL.


Changing the Generated SDL Package

Normally it is not recommended to edit SDL packages that have been generated from a C header. But if the header is very stable (for example for system header files) and the translation to SDL of larger parts of a C header is not suitable for some application, it is possible to convert the C header to an SDL package using the command-line interface of H2SDL. Then the generated package can be edited with a text editor and imported into SDL with the PR to GR converter described in Convert to GR (SDL).

Caution! 

When changing an SDL-PR package that has been generated with H2SDL, make sure that the package name is different from the name of the C header. This should be done before converting the package to SDL-GR. Otherwise the original C header may be overwritten by SDT since the C Code Generator will generate a header file for the package called <packagename>.h.

Example 37 illustrates how to change a generated SDL package.


Example 37  : Changing a generated package      

Suppose the C header stdio.h contains the following definitions:

As the preprocessor resolves these macros, they are "lost" in the C to SDL translation. We will change the generated PR file so that FILE, stdin, and stdout can be used in SDL. First we convert the C header to an SDL package by running H2SDL from the command-line:

This creates a file stdio_SDL.pr. Note that H2SDL has an option (-n) for setting the package name. See Command-Line Options for more information.

The package header is now:

We can start with FILE, which in C is used as a shorthand for the type struct _iobuf. In SDL terms, this would mean that we define FILE as a syntype of the type that was generated for struct _iobuf. In stdio_SDL.pr we see that this is the following.

Below this type, we add the following line:

stdin and stdout are shorthands for constants. This corresponds in SDL to synonyms. After some thinking, we can conclude that stdin and stdout must be of type struct _iobuf *. In the generated SDL, we can look up this type and add two definitions:

The next step is to convert the package to GR from the Organizer, using Generate/Convert to GR. We add a new package to the Organizer and connect it to the existing filestdio_SDL.sun (when connecting, deselect Expand substructure in the Connect dialog).

This package can now be used as any other SDL package.


Using SDL Sorts in C Functions

External procedures, implemented as C functions, can be used as an alternative to implementing operators in C using the #ADT code generator directive (see Implementation of User Defined Operators). Use of external procedures has the following advantages:

As an example, we consider an SDL sort Point:

We need an operation AddPoints to add two points and we want to implement this operation in C. The traditional way in SDT to implement this operation is by means of an SDL operator that has a code generator directive attached. The implementation could look something like:

An alternative is to define AddPoints as an external procedure, and implement it as a C function. In order to get this working, a number of small problems have to be solved.

The C Definition of the External Procedure

Let us start with the C implementation of AddPoints. For this purpose we create a new file points.c. The first problem is that AddPoints uses the SDL data type Point. How do we make this type visible in C? One alternative is to define Point in a package or in the system diagram and make use of environment header files (.ifc files). In this example we choose to make use of normal C headers that the C code generator produces for SDL diagrams for which full separation is specified. Full separation can be selected in the Organizer Generate/Make dialog.

Suppose that Point is defined in process P. When code for P is generated, a header p.h will be created that can be included in points.c. Since p.h makes use of SDL predefined types, we also include scttypes.h, which is normally located in the directory $sdtdir/INCLUDE (on UNIX), or %SDTDIR%\include (in Windows). Assuming that the target directory is target, and points.c is in the same directory as the SDL system, points.c can be implemented as:

Furthermore, we create a C header points.h that contains the declaration of AddPoints:

SDL Definitions for the External Procedure

The C function uses the name Point, without any prefix. To make this possible, we supply the data type Point with a #NAME directive (see Specifying Names in Generated Code -- Directive #NAME). So the changed SDL definition of Point is as follows:

An external procedure AddPoints must also be declared. A #CODE directive to include points.h accompanies the declaration, otherwise the C compiler will complain that C function AddPoints has not been declared.

Creating a Makefile Template

The last remaining problem is that the SDL system must be linked together with points.c. The recommended way to do this is to create a makefile template points.tpm (in Windows adopted to suit either the Borland or Microsoft compiler) that contains the following lines:

On UNIX:

In Windows, Borland (bcc32) Version:

In Windows, Microsoft (cl) Version:

This template is used if you select the radio button Generate makefile and use template in the Organizer Generate/Make dialog and select the file points.tpm.

Using ASN.1 in SDL

ASN.1 is a language for defining data types that is frequently used in the specification and implementation of telecommunication systems. ASN.1 is defined in ITU-T Recommendations X.680-X.683. Recommendation Z.105 defines how ASN.1 can be used together with SDL. A subset of Z.105 is implemented in SDT.

This chapter explains how ASN.1 data types can be used in SDL systems. The following items will be discussed:

Organizing ASN.1 Modules in SDT

SDT treats ASN.1 modules in a very similar way as C headers, see Organizing C Headers in SDT. It is recommended to have a special chapter for ASN.1 modules (for example called ASN.1 Modules). If many ASN.1 modules are used, they may be grouped into Organizer modules (which is not the same as ASN.1 modules!), see Module.

Figure 33 shows an example of the Organizer look of a chapter with two Organizer modules containing ASN.1 modules.

Figure 33 : Example of ASN.1 modules in the Organizer

Extracted pic [2]

We will show with an example how to use an ASN.1 module in an SDL system. Suppose we have an ASN.1 module MyModule in file mymodule.asn:

This module contains one type definition, Color, that has three values, red, yellow, and blue.

We first add a new diagram of type Text ASN.1 to the Organizer using Edit/Add New (without showing it in the Editor) and we connect it to the file mymodule.asn (using Edit/Connect). In order to use the ASN.1 module in SDL, we edit the system diagram and add `use MyModule;' in the package reference clause, as is illustrated in Figure 34 below.

Figure 34 : Using an ASN.1 Module in SDL

Extracted pic [7]

Figure 35 shows the resulting Organizer view. The symbol below the MySDLSys system symbol is a dependency link that indicates that the SDL system depends on an external ASN.1 module. Dependency links for ASN.1 modules that are used by an SDL system were previously required by the Analyzer, but now only serve as comments and are optional.

Figure 35  : Organizer View of SDL System Using ASN.1 Module

Extracted pic [8]

If ASN.1 modules use other ASN.1 modules, dependency links between the ASN.1 modules should be created.

Using ASN.1 Types in SDL

After the above preparations, the data types in MyModule can be used in SDL. As an example, we will make an SDL system that converts a character string to the corresponding color. This is done by two signals:

The system diagram including these signal definitions is shown in Figure 36 below.

Figure 36  : SDL system diagram

Extracted pic [10]

The MSC below illustrates how the system is intended to be used.

Figure 37  : MSC illustrating GetColor

Extracted pic [11]

In order to know which values and which operators can be used on ASN.1 types, it is necessary to look in Translation of ASN.1 to SDL.

For example, Color is defined as an ENUMERATED type. By looking at the mapping rules in Enumerated Types, we see the list of operators that can be used on Color. These are in this case Num, `<`, `<=', `>', `>=', Pred, Succ, First, Last, and also `=' and `/=', which are always available.

Figure 38  : Using the Color type in SDL

Extracted pic [9]

Figure 38 shows a fragment of an SDL process that uses Color. It contains a loop over all values of Color, and illustrates how to declare variables of Color, how to use Color in new SDL sort definitions, and how to use the operators First, Last, and Succ. Some notes on the fragment:

Using Predefined ASN.1 Types in SDL

The predefined simple ASN.1 types can be used directly in SDL. In most cases, the ASN.1 type has the same name in SDL, for example ASN.1's type NumericString is also called NumericString in SDL. However, some predefined ASN.1 types contain white-space, like BIT STRING. In SDL, the white-space is replaced with an underscore, so the corresponding SDL sort is called BIT_STRING.

The operators on these predefined ASN.1 types are described in detail in section Using SDL Data Types.

Using ASN.1 Encoding Rules with SDT

The ASN.1 Utilities do not yet support encoding rules. To use encoding rules in SDT (like, for example, the Basic Encoding Rules defined in X.690), it is recommended to use ASN.1 in combination with SDL exactly as described above.

The encoding and decoding between ASN.1 data types and bit streams is done in the environment functions. For doing the actual encoding/decoding you need some other ASN.1 tool that can generate C or C++ and that has support for the encoding rules that you need. The code generated by this other tool can then be used in the environment functions xInEnv and xOutEnv (which are explained in The Environment Functions).

A manual job is needed if the C data types that are generated by SDT are different from the C/C++ data types that are generated from the other ASN.1 tool, because such data types have to be converted from the one tool's format to the other and vice versa.

For example, suppose that we have a signal S that is sent from the SDL system to the environment. The signal has one parameter of ASN.1 type A that has to be encoded according to BER. We use some ASN.1 tool X to generate the encoding/decoding functions. Suppose X generates C type A_X and C function BEREncodeA to encode A to bytes. Suppose furthermore that SDT generates C type A_SDT from A.

In the environment function xOutEnv, where we do the encoding, we do the following: we get the signal parameter (which is of type A_SDT), we convert it to data type A_X, and we encode the parameter by calling BEREncodeA after which we finally can send the data. This is illustrated in the code sketch below.

Decoding is done in the environment function xInEnv, following the same principles, but now the order is the other way around; received bytes are decoded to A_X, converted by a help function to A_SDT, assigned to an SDL parameter of a signal, and finally sent as a signal into the SDL system.

Sharing Data between SDL and TTCN

One more advantage of ASN.1 is that TTCN is also based on this language. By specifying the parameters of signals to and from the environment of the SDL system with ASN.1 data types, this information can be re-used in ITEX for the specification of test cases for the system.

Figure 39 : Sharing ASN.1 definitions between SDL and TTCN

Extracted pic [1]

This has the big advantage of making it easier to keep the SDL specification consistent with the TTCN test specification.

The use of external ASN.1 in TTCN is covered in more detail in the ITEX manual. In this section we will briefly illustrate how to share data between SDL and TTCN using TTCN Link.

Supposing we have to write a test suite for the SDL system with the Colors example, we would add a new diagram -- a TTCN Test Suite, for example called ColorTest -- to the Organizer. In this test suite we want to use definitions from the ASN.1 module MyModule that contains the Colors data type. For this purpose we need to set a dependency link between the ASN.1 module and the test suite. We do this by selecting the ASN.1 module in the Organizer. By using Generate/Dependencies we connect it to the TTCN test suite ColorTest.

We can also use TTCN Link to generate declarations from SDL system MySDLSys. For this purpose, it is easiest to associate the SDL system with the TTCN test suite. This is done by selecting the SDL system diagram in the Organizer and associate it with the TTCN test suite using Edit/Associate. The Organizer View for the test suite now looks as in Figure 40 below:

Figure 40 : Organizer view of a test suite that uses ASN.1

Extracted pic [12]

We can generate a TTCN Link executable for the SDL system by selecting the SDL system in the Organizer and using Generate/Make select standard kernel TTCN Link. Now we can start ITEX by double-clicking on test suite ColorTest. By using TTCN Link/Generate Declarations, we can automatically generate the PCOs, ASP type definitions and ASN.1 type definitions. If we look at the result, we can see that Color is present as an ASN.1 Type Definition by Reference. This table is shown in below.

Figure 41 : Resulting table in ITEX

Extracted pic [13]

Now this data type can be used in creating test cases, in constraints, etc. If at some point in time the definition of Color would be changed (for example if we would add a new color), then, in order to update the test suite accordingly, we can select the TTCN table for Color. In the Analyzer dialog, we should select both Enable Forced Analysis and Retrieve ASN.1 Definitions. Now the TTCN test suite will be updated with the new definition for Color.


[Previous] [Next] [Contents] [Index]