Table of Contents Previous Chapter 44 The Cmicro Generator

44 The Cmicro Generator

The Cmicro Generator translates your SDL system into a C program that you can compile together only with the Cmicro Library and the Cmicro Tester target library. The Cmicro Library and the Cmicro Tester target library is not available as a pre-linked library but is delivered as source to enable scaling of the kernel dependent upon the SDL system characteristics. This chapter is a reference manual for the Cmicro Generator.

Introduction

Application Area for the Cmicro Generator

The application area for the Cmicro Generator is:

In this part of the manual, the general behavior of the Cmicro Generator, as seen from users point of view, is discussed.

Highly Optimized Code for Target

The generated code in combination with the Cmicro Library is highly optimized, which is absolutely inevitable for micro controllers and real-time applications as well. Some optimizations have been possible only by introducing restrictions in the use of SDL. Other optimizations have been possible by generating more compact code. For the restrictions in the use of SDL please see "Restrictions and SDL-92 Supported Features" on page 2695. Details regarding the output of the Cmicro code generation can be received by viewing chapter 45, The Cmicro Library.

Target Debug

With the generated code it is possible to debug the application on the target using the Cmicro Library and the Cmicro Tester target library. The parts of the Cmicro code generation, which do reflect parts of the Cmicro Tester, are highly optimized, too. Please see chapter 46, The Cmicro Tester.

Overview of the Cmicro Generator

The SDT Analyzer contains an SDL parser, an SDL semantic checker, and - among other code generators - the Cmicro Generator.

A lot of error checks are performed before any code generation starts. That makes it possible to improve written SDL specifications before any runtime testing must be done. These error checks are performed by the analyzer, which you will find in chapter 31, The Analyzer.

The following subsections describe the way to use the Cmicro Generator.

Selecting and Using Cmicro Generator as Code Generator

The Cmicro Generator can be selected as an extension to Cbasic and Cadvanced in the SDT Organizers menu

"Generate-Make-Code generator", as Cmicro.

The following buttons are allowed for Cmicro but may not be used:

"Generate environment header file" should be selected.

The other buttons may be used in the normal way.

Creating a C Program

To obtain an executable program that behaves according to an SDL description, you enter the SDL description into the SDT Analyzer, which contains the Cmicro Generator. The Cmicro Generator can be selected as an alternative to Cbasic and Cadvanced in the SDT Organizer "Generate-Make-Code generator" menu, as Cmicro. If the SDL description is syntactically and semantically correct a C program is generated. You then compile this program using an ordinary C compiler together with the source files of the Cmicro Library.

Apart from creation of the C program which represents the SDL system some more files are produced reflecting the SDL characteristics of the system

--------------------------------------------------------------------
Caution!                                                              
Do not try to hold two or more SDL systems under the same direc       
tory.                                                                 
The following files are always given the same name, as they reflect   
the characteristics of one sdl system. To avoid inadvertently over    
writing these files, maintain one SDL system per working direc        
tory when working with the Cmicro Generator.                          
--------------------------------------------------------------------
The first file is called sdl_cfg.h. It is used to scale the Cmicro Kernel depending on what characteristics the SDL system has. For an explanation of this file see chapter 45, The Cmicro Library.

The next file is called <systemname>.ifc and is used to implement the SDL environment. This is described in chapter 45, The Cmicro Library as well.

Another file called <systemname>.sym is used to store symbolic information about the SDL system. This file is used for Cmicro Tester purposes only and is described within chapter 46, The Cmicro Tester.

As seen from another point of view, the Cmicro Generator contains two components:

Executing a C Program on the Target

The generated C program uses an internal data representation of the SDL objects in the system, for example process instances and signal instances. The process instances will execute transitions in a quasi-parallel manner. During a transition, SDL actions such as tasks, decisions and signal outputs are executed according to the semantics of SDL.

You interact, using SDL terminology, with the target through a command line interface on the test system, e.g. a workstation or a PC, which contains a number of commands to:

Contents of this Chapter

You can find more details on creating and executing a C program in the following sections:

If a specific detail is not considered here, then you should consult:

Generating a C Program

A C program, which was generated by the Cmicro Generator, can only be used in connection with the Cmicro Library and Cmicro Tester. It is not necessary to validate and simulate the SDL system with the C code generated by the Cmicro Generator as this code is only suitable for target applications. In order to view the process of generating C applications see the Organizer make dialog (see "Make" on page 1112 in chapter 22, The SDT Organizer)

The SDT Analyzer, which contains the Cmicro Generator can also be started as a stand-alone tool. For more information about this possibility please see "The Analyzer Command-Line UI" on page 1541 in chapter 31, The Analyzer.

Process of Generating a C Program

There are four steps that must be performed to start the execution of a Cmicro Application.

  1. The SDT Analyzer and its built-in Cmicro Generator create a program expressed in C source code and an sdl_cfg.h for kernel scaling.
  2. The generated C files of the SDL system and the Cmicro Library are compiled for the target system. (Note: the target compiler must be adapted for this purpose). If required the Cmicro Tester can also be integrated into the compilation.
  3. The files are linked together.
  4. The executable program can then be downloaded into the target.
For this process to work automatically the user must adapt the required compiler to the system. The subsection "Adaptation to Compilers" on page 2842 in chapter 45, The Cmicro Library outlines how this is achieved.

A C program can only be generated for a complete SDL system. The C code that constitutes the program can, however, be generated on multiple files. However the make facility for SDL modules, processes blocks etc., is not available for Cmicro Applications. I.e. a change anywhere in the system means complete re-analysis and C code generation for the whole system.

The separation of the C code for an SDL system can be decided by the user. The Edit Separation command from the Generate menu is used for that purpose, see chapter 22, The SDT Organizer, on page 1123. The effect on the generated file structure and some guidelines of how to use separation can be found in the section "Selecting File Structure for Generated Code - Directive #SEPARATE" on page 2661.

Executing a C Program

Generated applications have no further connection with SDT and are executed as any other application.

The SDL Unit for which Code is Generated

As the Cmicro Library is re-compiled depending on the SDL system features C code must be generated for the complete system i.e. as in SDT 2.3 it is only possible to generate code for the complete system.

Running the Cmicro Generator stand-alone

The SDT Analyzer, which contains the Cmicro Generator may be executed stand-alone, see "The Analyzer Command-Line UI" on page 1541 in chapter 31, The Analyzer. Via the command interface to the analyzer, it is possible to set up most of the options that normally are set in the Organizer. An exception is the selection of separate units, where #SEPARATE directive can be used instead, see "Selecting File Structure for Generated Code - Directive #SEPARATE" on page 2661. When the Analyzer is executed stand-alone (without having information from the Organizer), the Cmicro Generator can generate and execute an appropriate make file. This operation is normally performed by the Organizer.

----------------------------------------------------------
Note:                                                       
The Cmicro Generator can be started by giving the command   
Generate-Micro                                              
as an analyzer command.                                     
----------------------------------------------------------
The compilation and linking of a generated C program may also be started directly from UNIX by typing the command:

make -f name_of_makefile
where name_of_makefile should be replaced by the name of the generated make file. This file is named system_name.m if it is generated by the Cmicro Generator, and SDTmake.m if it is generated by the Organizer.

The execution of a generated C program can also be started from the operating system by typing the name of the executable program.

To compile, link and execute from the operating system, the environment variable sdtdir should be given an appropriate value. This variable is given the correct value in the initialization file sdt.sou, which is used to make SDT available. sdtdir is used to find include files and object files during compilation and linking, and to find the help file during execution. The make file also requires that the environment variable sctdir refers to the directory containing the makeoptions file and the object files for the runtime library (the directory selected by the popup menu Standard kernel in the Organizer's Make dialog). sctdir is usually a subdirectory to sdtdir.

Errors During Code Generation

Errors that may occur during code generation are internal errors. That is, errors arising as features of SDL have not yet been implemented, and errors related to problems with open or close operations of files.

An error message starts with the line:

** Internal Code Generation Error **
and is followed by a description of the error.

The error:

Feature of SDL not implemented: #1 
will also contain a trace showing where in the SDL source the feature was found.

All the error messages are listed below, together with a short explanation. Some messages contain a"#" followed by a number which is used to indicate where information, specific of the error situation, can be found.

Feature of SDL not implemented: #1
The translator cannot yet handle this SDL feature. See the list of restrictions in the section "Restrictions and SDL-92 Supported Features" on page 2695.

Cannot open outfile
A .c, .h, or .m file cannot be opened. Probably the user has no write permission in the target directory.

WARNING! Unique name generation failed.
The scope structure is too deep.

#1 must be a unique name.
#1 is replaced by the name of an SDL unit. During code generation the Cmicro Generator prefixes SDL names to make them unique. The prefixing algorithm and the limit for the length of the prefix might make it impossible to generate a prefix, in which case this warning is issued. It is still possible to execute the generated program if the name, without prefix, is unique.

Node = nil in #1
Incorrect node type in #1. Nodetype: #2
Internal error in the PathStructure
Line exceeded MaxLineLength
These four last errors are internal errors in the Cmicro Generator, which we would be pleased if you reported to us. The telephone and fax numbers to Telelogic Customer Support can be found on page 1001 of this manual.

Implementation

In this section some implementation details are presented, that can be useful for understanding how a generated Cmicro Application behaves. Abstract data types are treated in the next section.

Time

As the generated C program is meant for target applications, Time is implemented as real time.

Real Time

If real time is used, then there will be a connection between the clock in the executing program and the wall clock. For applications the user must provide the connection with the wall clock, normally the hardware timer.

-------------------------------------------------------------------
Note:                                                                
The C standard function time used as real time clock returns the     
time in seconds. The implementation of the clock can be changed by   
re-implementing the function xmk_NOW in mk_stim.c.                   
-------------------------------------------------------------------

Scheduling

The Cmicro Kernel doesn't use a process ready queue, it works on signals in the order of their appearance. To do this, there is a signal queue which stores the signals sent to any process (either internally or externally). There are different ways to influence the scheduling when using the Cmicro Generator:

Assigning priorities to processes - preemptive scheduling

It is possible to assign priorities to process types (using SDL'88 terminology). The processes' priorities are assigned when designing the SDL system. They are assigned using the #PRIO directive.

There are some things to be kept in mind when using process priorities:

The Cmicro Kernel handles process priority by collecting all signals sent to processes of the same priority in a separate queue. Thus, there is a queue for each priority level.

In the run of the SDL system the Kernel checks for signals in the queues with decreasing priority. This check takes place whenever an SDL output appears or a process performs an SDL nextstate operation. Because of the Kernel checking for signals whenever an output takes place, it is possible to have preemptive scheduling.

Assume, there are two process types lowprio and highprio. Let processtype lowprio have the priority one and process type highprio have the priority zero.

If an instance of processtype lowprio performs an output to processtype highprio there appears a signal in a queue of a higher priority level (zero is the highest priority level available, process lowprio has priority one) which leads to the kernel immediately working on the signal sent to process highprio. The transition of process lowprio won't end until process highprio has finished its transition invoked by the signal.

This way of scheduling is implemented using recursion.

------------------------------------------------------------------
Note:                                                               
Process priorities are available only when using a compiler which   
can handle recursion.                                               
------------------------------------------------------------------
There is basically no restriction of the number of priority levels, but the target and compiler in use will of course limit the depth of recursion.

As a general recommendation process priorities should not be assigned one per processtype, but the process types should be grouped according to their purposes and these groups should then be assigned a priority level.

For more details please refer to "Assigning Priorities Directive #PRIO" on page 2684.

Assigning Priorities to Signals

The signals in the queue(s) normally are ordered according to their appearance (FIFO-strategy). By assigning priorities to signals this ordering is user definable. The directive #PRIO is used to assign a priority to signals.

Priority increases with decreasing numbers, but there is no restriction to use consecutive numbering.

Whenever a signal is sent, it is inserted into the signal queue(s) according to its priority.

Assume, there is a process performing two signal outputs, first signal first_sig then signal second_sig. Using the standard FIFO-strategy signal first_sig would be worked on before signal second_sig. But with signal priorities and signal first_sig assigned priority fifty and signal second_sig assigned priority twenty, signal second_sig would be in front of signal first_sig in the queue and thus would be worked on before signal first_sig.

For more details please refer to "Assigning Priorities Directive #PRIO" on page 2684.

Combinations of Signal/Process Priority

Every combination of signal and process priorities may be used. In this way it is possible to adapt the scheduling to the users' needs.

-----------------------------------------------------------------------
Note:                                                                    
Without process priorities a transition once started will have to be     
finished before the next transition can be dealt with. This is valid re  
gardless of the time it will need to finish a transition.                
-----------------------------------------------------------------------

Enabling Conditions and Continuous Signals

As the SDL entities enabling condition and continuous signal are considered too much of a code overhead, they are not supported by the Cmicro Generator. The user must therefore refrain from using these symbols in SDL flow diagrams, when the Cmicro Generator is to be used.

Synonyms

General

The Cmicro Generator only allows SDL synonyms to be implemented as C macros. To be translated to a macro the expression defining the value of the synonym must be:

Synonyms that cannot be calculated at analyses time are not supported by the Cmicro Generator. That is to say synonyms that would normally be implemented as variables in the generated code are not supported by the Cmicro Generator.

External Synonyms

External synonyms can be used to parameterize an SDL system and thereby also a generated program. The values that should be used for the external synonyms can be included as macro definitions into the generated code, for instance by including another header file.

Using a Macro Definition

To use a macro definition in C to specify the value of an external synonym, perform the following steps:

  1. Write the actual macro definitions on a file.
Example 279 : Macro Definition  
#define synonym1 value1
#define synonym2 value2
  
The synonym names are the SDL names (without any prefixes).

  1. Introduce the following #CODE directive at the system level among the SDL definitions of, for example, synonyms, sorts, and signals but before any use of the synonyms.
Example 280 : #CODE Directive  
/*#CODE
#TYPE
#include "filename"
*/
  
If this structure is used, the value of an external synonym can be changed merely by changing the corresponding macro definition and recompiling the system.

---------------------------------------------------------------------
Note:                                                                  
When an application is created, macro definitions should be used for   
all external synonyms, as the function for reading synonym values      
stored on file is not available. (See below.)                          
---------------------------------------------------------------------

Reading Values at Program Start up

This method of reading external synonyms is not supported for applications and is therefore not supported by the Cmicro Generator.

Import - Export

The Import-Export concept is not supported by the Cmicro Generator.

Remote Procedure Calls

Remote procedure calls are not supported by the Cmicro Generator.

Procedure Calls and Operator Calls

In SDL-92 value returning procedures and operator calls are introduced. This means, that an SDL procedure can be called within an expression. As the Cmicro Generator cannot handle procedures with states, it is not necessary to map such calls to a different scheme.

Example 281 : Procedure Call  
TASK i := (call p(1)) + (call Q(i,k));
is translated to something like:
i = p(1) + Q(i,k);
  
-------------------------------------------------------------------
Note:                                                                
The value returning procedure calls are transformed to C functions   
returning values.                                                    
-------------------------------------------------------------------
Operators which are defined using operator diagrams, are according the models in the SDL recommendation, treated exactly as value returning procedure.

Any

Any should not be used in applications using the Cmicro Generator, because it leads to an error message.

Calculation of Receiver in Outputs

The Cmicro Generator is currently a code generator using the semantics of SDL-92 (without object-oriented concepts) and a few restrictions. The behavior is according to the rules described in the following:

Abstract Data Types

In this section we will discuss the following topics:

SDL Predefined Types

Mapping Table

Below is a table which summarizes the mapping rules between SDL and C, concerning the predefined types in SDL and their operators. Note that many of the operators are in C defined as macros, and expanded by the C preprocessor to simple operators in C.

-----------------------------------------------------------------------
SDL name/operator         C name/expression/operator                     
-----------------------------------------------------------------------
Boolean                   SDL_Boolean                                    
False, True               SDL_False, SDL_True                            
not                       xNot_SDL_Boolean                               
=, /=                     yEqF_SDL_Boolean,                              
                          yNEqF_SDL_Boolean                              
and                       xAnd_SDL_Boolean                               
or                        xOr_SDL_Boolean                                
xor                       xXor_SDL_Boolean                               
=>                     xImpl_SDL_Boolean                              
Character                 SDL_Character                                  
NUL                       SDL_NUL                                        
SOH                       SDL_SOH                                        
...                       ... (for all unprintable characters)           
'a'                       'a'                                            
'b'                       'b'                                            
...                       ... (for all printable characters except ')    
''''                      '\''                                           
=, /=                     xEqF_SDL_Character,                            
                          xNEqF_SDL_Character                            
<, <=, >, >=  xLT_SDL_Character,                             
                          xLE_SDL_Character,                             
                          xGT_SDL_Character,                             
                          xGE_SDL_Character,                             
chr                       xChr_SDL_Character,                            
num                       xNum_SDL_Character,                            
Charstring                SDL_Charstring                                 
'aa'                      SDL_CHARSTRING_LIT("Laa","aa")                 
=, /=                     yEqF_SDL_Charstring,                           
                          yNEqF_SDL_Charstring                           
MkString                  xMkString_SDL_Charstring                       
Length                    xLength_SDL_Charstring                         
First                     xFirst_SDL_Charstring                          
Last                      xLast_SDL_Charstring                           
//                        xConcat_SDL_Charstring                         
SubString                 xSubString_SDL_Charstring                      
Integer                   SDL_Integer                                    
0, 1 etc.                 SDL_INTEGER_LIT(0),                            
                          SDL_INTEGER_LIT(1) etc.                        
+                         xPlus_SDL_Integer                              
- (monadic, dyadic)       xMonMinus_SDL_Integer,                         
                          xMinus_SDL_Integer                             
*                         xMult_SDL_Integer                              
/                         xDiv_SDL_Integer                               
mod                       xMod_SDL_Integer                               
rem                       xRem_SDL_Integer                               
=, /=                     yEqF_SDL_Integer, yNEqF_SDL_Integer            
<, <=, >, >=  xLT_SDL_Integer, xLE_SDL_Integer,              
                          xGT_SDL_Integer, xGE_SDL_Integer,              
Float                     xFloat_SDL_Integer                             
Fix                       xFix_SDL_Integer                               
Natural                   SDL_Natural                                    
Real                      SDL_Real                                       
12.45,...                 SDL_REAL_LIT(12.45, 12, 450000000)             
- (monadic, dyadic)       xMonMinus_SDL_Real,                            
                          xMinus_SDL_Real                                
+                         xPlus_SDL_Real                                 
*                         xMult_SDL_Real                                 
/                         xDiv_SDL_Real                                  
=, /=                     yEqF_SDL_Real, yNEqF_SDL_Real                  
<, <=, >, >=  xLT_SDL_Real, xLE_SDL_Real,                    
                          xGT_SDL_Real, xGE_SDL_Real                     
PId                       SDL_PId                                        
NULL                      SDL_NULL                                       
=, /=                     yEqF_SDL_PId, yNEqF_SDL_PId                    
Duration                  SDL_Duration                                   
23.45                     SDL_DURATION_LIT(23.45, 23,                    
                          450000000)                                     
                          Note, that the Cmicro Library uses only the    
                          integer part in front of the dot, 23 in this   
                          example.                                       
+                         xPlus_SDL_Duration                             
- (monadic)               xMonMinus_SDL_Duration                         
- (dyadic)                xMinus_SDL_Duration                            
* (Duration * Real)       xMult_SDL_Duration,                            
* (Real * Duration)       xMultRD_SDL_Duration                           
/                         xDiv_SDL_Duration                              
=, /=                     yEqF_SDL_Duration,                             
                          yNEqF_SDL_Duration                             
<, <=, >, >=  xLT_SDL_Duration, xLE_SDL_Duration,            
                          xGT_SDL_Duration, xGE_SDL_Duration             
Time                      SDL_Time                                       
23.45                     SDL_TIME_LIT(23.45, 23, 450000000)             
                          Note, that the Cmicro Library uses only the    
                          integer part in front of the dot, 23 in this   
                          example.                                       
+ (Time + Duration)       xPlus_SDL_Time,                                
+ (Duration + Time)       xPlusDT_SDL_Time                               
- (result: Time)          xMinusT_SDL_Time                               
- (result: Duration)      xMinusD_SDL_Time                               
=, /=                     yEqF_SDL_Time,                                 
                          yNEqF_SDL_Time                                 
<, <=, >, >=  xLT_SDL_Time, xLE_SDL_Time,                    
                          xGT_SDL_Time, xGE_SDL_Time                     
-----------------------------------------------------------------------

C Definitions

Here we discuss the types and macros supplied by the runtime library in the Cmicro Generator for the predefined types in SDL. These macros and extern definitions for functions can be found in the file $sdtdir/MICROLIBRARY/kernel/ml_pred.h, except for the PId sort which is handled in the file $sdtdir/MICROLIBRARY/kernel/ml_typ.h.

-------------------------------------------------------------------
Note:                                                                
For more information about the Charstring sort, see the subsection   
"Handling of the Charstring Sort" on page 2644.                      
-------------------------------------------------------------------

Translation of Sorts

The following data types are handled by the Cmicro Generator. The data types marked with an asterisk (*) below are implemented in a restricted way.

The following data types cannot be handled:

Predefined Types

The predefined data types, Integer, Natural, Boolean, Character, Real, and PId are completely handled.

Charstrings can be used either in the usual way as in the Master Library, or they can be used in a restricted way. The decision is up to the user and is a question of configuration. This is discussed in subsection "Manual Scaling" on page 2817 in the Cmicro Library reference manual.

The predefined data types Time, Duration are implemented in a more or less restrictive way. It is possible to specify a real value for Time and Duration on SDL level, like 23.45. Note, that the Cmicro Library uses only the integer part in front of the dot, 23 in this example. The mapping of SDL units to units in implementation is - in any case - up to the user.

The name of these types in the generated C code will be SDL_Integer, SDL_Natural, SDL_Boolean, and so on. The translation rules for these types and their operators are discussed in more detail in the"SDL Predefined Types" on page 2622.

Enumeration Type

A sort which is not a struct and does not contain any inheritance or generator instantiation, but which contains a literal list, is translated to an enumeration type in C, as can be seen in the example below. As in all examples in this subsection, the prefixes, which are added to names when they are translated to C, are not shown. The prefixes are added to make sure that no name conflicts occur in the generated program. For more information about prefixes see "Names and Prefixes in Generated Code" on page 2678.

Example 282 : Enumeration Type        
NEWTYPE EnumType  
  LITERALS Lit1, Lit2, Lit3;
ENDNEWTYPE;
is translated to:

typedef enum {Lit1, Lit2, Lit3} EnumType;
  

Struct

An SDL struct is translated to a struct in C, as can be seen in the example below.

Example 283 : Struct            
NEWTYPE Str STRUCT
  a integer;
  b Boolean;
  c real;
ENDNEWTYPE;
is translated to:

typedef struct {
  SDL_Integer a;
  SDL_Boolean b;
  SDL_Real c;
} Str;
  
All the properties of a struct in SDL are preserved in the C code.

The predefined operators Extract! and Modify! are implemented as component selections in the struct in the same way as in SDL, that is, if S is a variable of type Str, then S!a in SDL is translated to S.a in C.

The predefined operator Make!, which is a constructor of a struct value, is implemented by generating a Make function in C. This means that the expression (. 12, true, 0.22 .) in SDL is translated to the C function call Make(12, true, 0.22). The Make function will, of course, be given a name that makes it unique.

The components of a struct may be of any sort that the Cmicro Generator can handle. A component may, however, not directly or indirectly refer to the struct sort itself. As an example the sort Str above may not have a component of sort Str. In such a case the translation to a C struct would not be valid any longer.

Union

Using the directive #UNION (see example below) it is possible to tell the C Code Generator to generate a union according to the following example:

Example 284 : Union            
NEWTYPE Str STRUCT /*#UNION*/
  tag integer;
  a integer;
  b Boolean;
  c real;
ENDNEWTYPE;
is translated to:

typedef struct {
  SDL_Integer tag;
  union {
    SDL_Integer a;
    SDL_Boolean b;
    SDL_Real c;
  } U;
} Str;
  
The first component in the struct is assumed to be a tag value indicating which of the union components that are active. The tag should either be integer or an enumeration type. Tag value 0 or first enumeration literal is used to indicate that the first of the remaining components are active, and so on. On the SDL level a #UNION struct should be handled just like any other struct. It is up to the C Code Generator to generate the correct code for operations on the struct, like assignment, test for equality, component selection, and so on.

-------------------------------------------------------------------
Note:                                                                
It is completely up to the user to make certain that only valid com  
ponents in a #UNION struct are accessed.                             
-------------------------------------------------------------------

Array

Only array's, which can be translated to an array in C, are supported by the Cmicro Generator, so that there is no need for the predefined generator array.

The following array's in SDL cannot be translated to array's in C:

The reason, why the above is not supported, is that it implies a good dynamic memory management within the target system, which normally is not applicable.

If the index sort is a discrete sort, with one closed interval of values, that is of the following sorts:

then the SDL array is translated to a struct containing an element which is an array in C. The reason for this translation strategy is that an array may not be the result type of a C function (only the address of an array may be the result type), which is necessary as SDL procedures and SDL operators may have arrays as result. By embedding the C array in a C struct this problem is avoided.

-----------------------------------------------------------------
Note:                                                              
The index sort for arrays must be discrete when using the Cmicro   
Generator.                                                         
-----------------------------------------------------------------
Example 285 : Array  
SYNTYPE Syn = integer
  CONSTANTS 0:10
ENDSYNTYPE;
NEWTYPE Arr ARRAY(Syn, real)
ENDNEWTYPE;
is translated to:

typedef SDL_Integer Syn;
typedef struct {
 SDL_Real A[11];
} Arr;
  
All the properties of an array in SDL are preserved in the C code.

The predefined operators Extract! and Modify! are implemented as component selection of the array in C in the same way as in SDL, so if AVar is a variable of type Arr, and Index is a valid index expression, then AVar(Index) in SDL is translated to AVar.A[Index] in C. In the case of a link list implementation of the array, component selection is made through function calls.

The predefined operator Make!, which is a constructor of an array value, is implemented by generating a Make function in C. This means that the expression (. 0.22 .) in SDL is translated to the C function call Make(0.22). The Make function will of course be given a name that makes it unique.

String

As this generator is not useful for target applications, it is not implemented.

Powerset

As this generator is not useful for target applications, it is not implemented.

Syntypes

Syntypes may be defined for any sort that the Cmicro Generator can handle, giving a new name for the sort and possibly a new default value for variables of the sort. Range conditions that restrict the allowed range of values are also allowed.

The syntype is translated to a type equal to the parent type using typedef. The check that a variable of a syntype is only assigned legal values is implemented in a test function that is generated together with the type definition. An attempt to assign an illegal value to such a variable will be reported as an SDL dynamic error (if conditionally compiled so). If the syntype is used as an index sort in an array and the generated type in C would become an array, there will also be a test function that can be used to check that an index value is within its range in an array component selection.

Example 286 : Syntypes   
SYNTYPE Syn = integer
  CONSTANTS 0:10
ENDSYNTYPE;
SYNTYPE Syn2 = integer
  CONSTANTS <0, =2, >=10
ENDSYNTYPE;
SYNTYPE Arr1 = Arr
  DEFAULT (. 2.0 .);
ENDSYNTYPE;
/* Arr defined above */
is translated to:

typedef SDL_Integer Syn;
typedef SDL_Integer Syn2;
typedef Arr Arr1;
  

Default Values

Default values are fully supported for all sorts that the Cmicro Generator can handle, both if a default value is given in a sort definition and if an initial value is given in a variable definition (DCL).

Default values will also be assigned to all variables and components which do not have a default value specified in SDL. The reason for this is to avoid handling of undefined variables in C, which might give serious problems and unexpected behavior of an executing program. The values selected by the Cmicro Generator in such a case can be found below.

---------------------------------------------------------------
Note:                                                            
This is a deviation from SDL92. It means that the generated pro  
gram does not handle the value undefined for any type.           
---------------------------------------------------------------
The following start values are used if no default value is given in the sort and no start value is given in the data definition (DCL):

----------------------------------------------------------------
Sort         Start Value                                          
----------------------------------------------------------------
Integer      0                                                    
Natural      0                                                    
Real         0.0                                                  
Time         0.0                                                  
Duration     0.0                                                  
Character    NUL                                                  
Charstring   '' (empty string) or                                 
             NULL pointer                                         
             (depending on configuration)                         
Boolean      false                                                
PId          null                                                 
Enumeration  First value in enumeration                           
Struct and   1.  Components initialized according to their de     
Array        faults                                               
             2.  Components initialized according to this table.  
String and   Empty string, empty powerset                         
Powerset                                                          
Syntypes     Default value of father type (newtype)               
             According to this table for father type.             
----------------------------------------------------------------

Operators

It is not possible to define ADT operators in SDL directly with the Cmicro Generator. That is a part of simulation, but not for targeting. Applications require that the operators are implemented in C.

No default operators should be generated. This is to be prevented by applying the appropriate SDT directives as discussed in the subsection "Implementation of User Defined Operators", below.

A user defined operator in an SDL sort definition is translated to a C function that asks the user for the result of the operation. At a call of an operator the user is supplied with information on what operator in what sort that is called, and with information about the parameter values. You are then requested to answer with the result value. If you press <Return> at the prompt for the result the default value of the actual result type is returned.

Example 287 : Operator  
Operator Op in sort S is called.
Parameter 1: true
Parameter 2: 10
Enter value (integer) : 12
  
assuming that newtype S contains an operator

Op: Boolean, Integer -> Integer;

Literals

In sorts that are translated to enumeration types in C, literals are obviously handled by the Cmicro Generator. In sorts that are not translated to enumeration types in C, literals are treated as operators without parameters and are handled exactly in the same way as user defined operators.

--------------------------------------------------------------
Note:                                                           
The Cmicro Generator does not permit naming of literals using   
name class literals or character strings.                       
--------------------------------------------------------------

Axioms and Literal Mappings

Axioms and literal mapping are allowed by the Cmicro Generator in sorts, but are completely ignored.

Implementation of User Defined Operators

Including Implementations of Operators

In the Cmicro Generator no default behavior regarding the generation of operators can be expected, as it is with the C code Generator. The C Code Generator is able - together with the Simulator - to simulate the implementation of an operator, by using Read- and Write functions. The Cmicro Generator is not able to perform such a simulation. The reason is, that the Cmicro Generator mainly is used to build target applications, and not simulations.

To cope with this problem and to make it possible to generate applications, the Cmicro Generator offers a possibility to include implementations written in C of the operator and literal functions.

Only one method to implement operators and literal functions is served:

If you use Q (question), as it is allowed with the C code Generator, that will lead to an compilation error.This is the default value and specifies that the Cmicro Generator should generate the interactive routines describe above.

----------------------------------------------------------------------
Note:                                                                   
The C functions are divided into a function heading (extern or static   
declaration) and a function body.                                       
----------------------------------------------------------------------
An example of a function heading (extern declaration) is:

Example 288 : Implementing an Operator  
extern SDL_Integer Max 
  (SDL_Integer Para1,
   SDL_Integer Para2);
while the corresponding function body is:

SDL_Integer Max 
  (SDL_Integer Para1,
   SDL_Integer Para2)
{
 if (Para1 > Para2)
   return Para1;
 return Para2;
}
  
---------------------------------------------------------------------
Note:                                                                  
In all examples of this manual, prototypes as defined in ANSI-C, are   
used. If the compiler does not support prototypes, the examples        
should be transformed to the old C-style for functions.                
---------------------------------------------------------------------
The main reason for this division of functions into heading and body is the separate compilation scheme used in C. If, for example, an abstract data type is defined in a system and used in a process in the system, and the process is generated on a separate file, then there has to be a module interface file (a .h file) for the system containing the external interface (types, extern declarations of functions and so on). The interface file should then be included in the file generated for the process.

Even if separate compilation is not used, the division of functions into heading and body is useful. By having static declarations of the functions, the order in which functions must be defined is relaxed. If static declarations were not used, a function could only call the functions that are defined textually before the actual function.

To select the way the Cmicro Generator should generate code for operators and literals, Cmicro Generator directives are used. A Cmicro Generator directive is an SDL comment with the first characters equal to #, followed by a sequence of letters identifying the directive. In this case the letters are ADT (for Abstract Data Type) and OP (for operator). An ADT directive and a OP directive should thus look like:

/*#ADT */ /*#OP */
The text is not case sensitive.

OP directives are recognized at two different positions in an abstract data type:

ADT directives are recognized immediately before the reserved word ENDNEWTYPE (or ENDSYNTYPE).

Example 289 : Implementing an Operator (#ADT)   
NEWTYPE Str STRUCT 
  a integer; 
  b Boolean;
  c real;
ADDING 
LITERALS 
  Lit1 /*#OP */,
  Lit2 /*#OP */;
OPERATORS
  Op1 :Str,integer -> Str; /*#OP */
  Op2 :Str,Boolean -> Str; /*#OP */
/*#ADT */
ENDNEWTYPE;
  
At each of the positions after a literal name or operator definition, the user must specify a B (body). An OP or ADT directive specifying a generation technique should have the following structure:

/*#OP (B) */ /*#ADT (B) */
The letter between the parentheses should be B (body), and may not be Q. The interpretation of Q and B was explained on page 2635. As B is the only method to define operators, the C code for these functions must be supplied by the user. This code should be placed in the #BODY section in the ADT directive, according to the following example:

Example 290 : Implementing an Operator (#ADT)   
/*#ADT (B)
#BODY
C code, representing bodies of functions
*/
  
The section name, i.e #BODY, must be given on a line of its own and must have the # character in the first position of the line. Uppercase and lower case letters are as usual considered to be equal. If the section is empty, the section name can also be removed.

---------------------------------------------------------------------
Note:                                                                  
that the Cmicro Generator will not check the consistency between       
the specification of implementation techniques and the actual code     
included in the body section. This check is, together with checking    
the C code for syntactic and semantic errors, left to the C compiler.  
---------------------------------------------------------------------
Unfortunately it is not possible to have C comments within the code that is included in a #ADT directive, as SDL and C use the same symbols for start and end of comments. If a C comment is included, the SDT Analyzer will consider the end of the C comment as the end of the SDL comment. Instead a C macro called COMMENT can be used according to the examples below.

Example 291 : Comment in ADT  
COMMENT(This is a comment)
COMMENT(These comments may not contain commas \
        and should have a backslash at each \
        line break)
COMMENT((By having double parenthesis, any text
         can be entered into the comments. Some
         compilers might not allow everything.))
  
The function headings representing literals and operators are determined by their corresponding definition in SDL. The number of parameters, their types, the result type of the function and function name are all defined in SDL. In the example above, where the struct Str is defined, there are two literals (Lit1 and Lit2) and two operators
(Op1: Str, integer --> Str; and Op2: Str, Boolean --> Str;). The function heading of the corresponding C functions should be:

Example 292 : Implementing an Operator  
extern Str Lit1 (void);
extern Str Lit2 (void);
extern Str Op1 (Str, SDL_Integer);
extern Str Op2 (Str, SDL_Boolean);
  
The function bodies, which should be supplied by the user if B is specified in the OP or ADT directive, are ordinary C functions.

Example 293 : Implementing an Operator  
Str Lit1 (void)
{
 Str Temp;
 Temp.a = 2;
 Temp.b = false;
 Temp.c = 10.0;
 return Temp;
}
Str Op1 (Str yParam1, SDL_Integer yParam2),
{
  yParam1.a = yParam1.a + yParam2;
  return yParam1;
}
  
Before it is possible to give a complete example of an abstract data type with implementation of its operators supplied as C functions, it is necessary to look at the requirements to names. When a name of some object in SDL is translated to C, a suitable sequence of characters, a prefix, is added to the SDL name, to make the name unique in the C program, see also "Names and Prefixes in Generated Code" on page 2678. This strategy is selected in the Cmicro Generator to avoid name conflicts in the generated code, but it makes it also impossible to predict the actual name of, for example, a type or a function, in the generated program. To handle this problem the user can tell the Cmicro Generator to translate a name in the C code in the same way as SDL names are otherwise translated. This is specified by enclosing the SDL name between #( and ) in the C code. The two functions in the previous example and their headings would then become:

Example 294 : Including SDL name in C Code  
extern #(Str) #(Lit1) (void);
extern #(Str) #(Op1) (#(Str), SDL_Integer);
#(Str) #(Lit1) (void)
{
  #(Str) Temp;
  Temp.a = 2;
  Temp.b = false;
  Temp.c = 10.0;
  return Temp;
}
#(Str) #(Op1) 
  (#(Str) yParam1, SDL_Integer yParam2)
{
  yParam1.a = yParam1.a + yParam2;
  return yParam1;
}
  
This facility to access an SDL name in C code is described in more detail in the section "Accessing SDL Names in C Code - Directive #SDL" on page 2670. A few observations concerning the example above might be appropriate:

  1. The standard sorts in SDL, integer, natural, Boolean, real, character, charstring, time, duration, and pid, have the names SDL_Integer, SDL_Natural, SDL_Boolean, and so on in the generated code. These types should not be enclosed between #( and ).
  2. The component names of a struct are unchanged in the struct implementation in C, which means that struct components should not be enclosed between #( and ) neither.

Two Examples of ADTs

We now give two complete examples of abstract data types.

Example 295 : ADT Example  
NEWTYPE Str STRUCT
  a integer;
  b Boolean;
  c real;
  ADDING LITERALS
    Lit;
  OPERATORS
    Op1 : Str, integer -> Str;
    Op2 : Str, Boolean -> Str;
/*#ADT (B)
#BODY
#(Str) #(Lit1) (void)
{
  return yMake_#(Str) (2,false,10.0);
}
#(Str) #(Op1) 
  (#(Str) yParam1, SDL_Integer yParam2)
{
  yParam1.a = yParam1.a + yParam2;
  return yParam1;
}
#(Str) #(Op2) 
  (#(Str) yParam1, SDL_Boolean yParam2)
{
  if (yParam2)
    return yParam1;
  return #(Lit1)();
}
*/
ENDNEWTYPE;
  
The only thing in this example which has not been discussed earlier is the use of the make function in the function for literal Lit1. Each struct in SDL has an implicit operator Make!, which is a constructor for struct values from the struct components. The Cmicro Generator generates a function that corresponds to this operator with the name yMake_ followed by the sort name with prefix. The function has one parameter for each struct component and returns a value of the struct sort. The returned value is the struct value that is obtained when each component is assigned the value of the corresponding parameter. This make function is often very useful when literal functions in struct sorts are to be implemented. In C code the name of the make function is easiest to obtain by writing yMake_#(SortName), substituting the name of the actual struct sort for SortName.

Example 296 : ADT Example  
SYNTYPE Index CONSTANTS 1:10
ENDSYNTYPE,
NEWTYPE A Array(Index, integer)
  ADDING LITERALS
    Zero /*#OP (B) */;
  OPERATORS
    Add : A, A -> A; /*#OP (B) */
    Sum : A -> integer;
/*#ADT()
#BODY
#(A) #(Zero) (void)
{
  return yMake_#(A) (0);
}
#(A) #(Add) (#(A) yParam1, #(A) yParam2)
{
  #(Index) I;
  #(A) Result;
  for (I = 1; I<=10; I++)
    Result.A[I] = yParam1.A[I] + yParam2.A[I];
  return Result;
}
*/
ENDNEWTYPE;
  
Note that no body is supplied for the operator Sum. That will lead to a compilation error with missing identifiers, as no default implementation of operators is possible with the Cmicro code generation.

For more information about the functions and types (supplied by the runtime library in the Cmicro Generator and contained in generated code) that can be useful when implementing operators in C, see"SDL Predefined Types" on page 2622, and last in"More about Abstract Data Types" on page 2648.

Error Situations in Operators

In the C function used to implement operators (and literals) it is possible to define error situations and handle them as ordinary SDL run-time errors. The C library function ErrorHandler, with the following prototype

extern void ErrorHandler( xmk_OPT_INT errnum )
can be used for this purpose. xmk_OPT_INT is defined in ml_typ.h, normally as an ordinary C int. errnum may be one of the free values of error numbers. Please inspect ml_err.h in order to get a list of reserved values.

Example 297 : Error Handler in Operator  
  if ( strlen(C) <= 1 ) {
#ifdef XMK_USE_ERR_CHECK
    ErrorHandler (ERR_N_InvalidStringLength);
#endif
    return SDL_NUL;
  } else
    return C[1];
  
This is a simplified version of the test in the function for the operator First in the sort Charstring. Here the error situation is when we try to access the first character in a charstring of length 0. In this case the C function ErrorHandler is called and a default value is returned (NULL). By including the call to ErrorHandler between #ifdef XMK_USE_ERR_CHECK - #endif the function is only called to report the error, if error checks are turned on. The one parameter to the C function ErrorHandler should identify the error. The number must be given by the user.

Another possibility to route error messages to the host system is to use the C function xmk_PrintString of the Cmicro Tester, e.g.:

extern void xmk_PrintString( char * )
and

Example 298 : Error Handler in Operator  
  if ( strlen(C) <= 1 ) {
#ifdef XMK_ADD_MICRO_TESTER
    xmk_PrintString ("ERR:Invalid Stringlength");
#endif
    return SDL_NUL;
  } else
    return C[1];
  

Handling of the Charstring Sort

The SDL sort Charstring is - per default - implemented as char * in C.

--------------------------------------------------------------------------
Note:                                                                       
This means that the value NUL (ASCII character 0) cannot be part            
of a Charstring, as this value is used as string terminator in C (this is   
checked by the library functions for Charstring).                           
--------------------------------------------------------------------------
The Cmicro Generator and the library functions for the Charstring operators use the first character (index 0) in the C string to indicate the status of the string. If the first character is:

All the library functions for Charstrings handle memory in an appropriate way. A user only has to take the extra character into account, when Charstrings are handled in C. Any Charstring function parameters having a 'T' as first character must be handled according to the discussion above. A function that returns a Charstring and that creates new temporary memory to store the result, should assign the value 'T' to the first character in the Charstring.

As pointers and dynamic memory are used to implement Charstrings, it is necessary to be careful when Charstrings are handled in C code, which we show in two examples.

Example 299 : Equal Test on Charstring Sort  
If the C operator == is used to check if two charstrings are equal, then the actual test that is performed is to see if the two pointer values to the data areas representing the characters in the string are equal.

To check if the characters in the charstrings are equal the equal function should be used:

 yEqF_SDL_Charstring
  
Example 300 : Assignment on Charstring Sort    
If the C assignment operator =, is used to assign the value of one charstring variable (C1) to another charstring variable (C2), then two things will go wrong:

  1. The memory used to represent the old value of C1 is lost and can never be reused.
  2. C1 and C2 now refer to the same memory area, which means that if one of the variables is changed the other will also be changed. This leads to unpredictable behavior of the program.
The correct way to handle assignment of charstrings is to use the routine:

yAssF_SDL_Charstring
  
The problems mentioned above can of course also occur if a struct or array containing charstring components (or subcomponents) is handled carelessly. It is, for example, necessary to use the generated equal and assign routines to perform equal test and assignment (see subsection "Help Functions" on page 2657).

To avoid problems one should be aware that Charstring is implemented as char * in C and take the consequences thereof. There are a number of help functions (that implement the operators for the Charstring sort) supplied in the runtime library that might be helpful when handling Charstrings. See "SDL Predefined Types" on page 2622).

It is usually necessary to allocate dynamic memory when an operator returning a charstring value is implemented. There are two help functions that should be used in connection with allocation and de-allocation of dynamic memory:

  1. SDL_Charstring xAlloc_SDL_Charstring (xptrint Size)
    The function xAllocSDL_Charstring takes a requested size in bytes and returns a pointer to a data area of this size. The new area will contain 0 in all bytes.
  2. void xFree_SDL_Charstring (void * * C)
    The function xFree_SDL_Charstring should be given an address to a pointer and will return this data area to the pool of available memory. It will also give the pointer the value 0 (NULL).
These functions are, of course, implemented using the C standard functions for allocation and de-allocation of memory, and are described in detail in chapter 36, The Master Library, section "Allocating Dynamic Memory" on page 2260

----------------------------------------------------------------------
Caution!                                                                
Do not use Charstring in SDL if you want to get a correct trace out     
put with the Cmicro Tester, or if you want to use the Cmicro Record     
er. In the last case, the use of charstring may lead to a fatal error   
when an SDL session is replayed.                                        
----------------------------------------------------------------------

External Properties

As an alternative to the #ADT directive, which is a comment, the external properties clause in a newtype can be used as container for this information. See the following example:

Example 301 : External Properties in a Newtype  
 NEWTYPE Str STRUCT
  a integer;
  b Boolean;
  c real;
  ADDING LITERALS
    Lit;
  OPERATORS
    Op1 : Str, integer -> Str;
    Op2 : Str, Boolean -> Str;
ALTERNATIVE C;
#ADT (B)
#BODY
 some appropriate C code
ENDALTERNATIVE;
ENDNEWTYPE;
  
The #ADT directive, without the /* */ can be placed between ALTERNATIVE C; and ENDALTERNATIVE.

--------------------------------------------------------------------
Note:                                                                 
According to the syntax of SDL, if you have an external properties    
clause (i.e. alternative - endalternative), you cannot, in the same   
newtype, have operator diagrams, axioms, or literal mappings.         
--------------------------------------------------------------------

More about Abstract Data Types

More about Operators

Previously under "Implementation of User Defined Operators" on page 2635, the possibility to include implementations of operators in abstract data types was described. Here we will first discuss some additional features concerning operators and then describe how to replace the generated type definition for an abstract data type with a user defined type definition.

For an operator in an abstract data type not only B (body) may be specified. The following choices are available:

Note again, that the Q operator may not be specified with Cmicro.

For each operator one of the letters B, H, S and one of the letters P, I should be supplied, either in a #OP directive, or in a #ADT directive, or as the default P; for literals P and I have no meaning.

The purpose of S is straight forward and easy to understand, but H might require some explanation. H means that the Cmicro Generator will not generate any code for the operator, which leaves the user with a number of possibilities:

Example 302 : Using S (Standard Function or Operator)  
"+" : integer, real -> real; /*#OP (SI) */
sin : real -> real; /*#OP (SP) */
An SDL expression using these operators:

sin(a + 7.0) will be translated to: sin(zh723a + 7.0)

  
These examples show how standard functions in the target language can be directly utilized in abstract data types.

Including Type Definitions

In the remaining part of this subsection the possibility to include a type definition in the target language for an abstract data type will be described. When this facility is used, it is also needed to specify how to perform assignment, test for equal, assign default values, and so on, as this is not possible to generate when the type definition is not known (not generated). All this information is given in the #ADT directive, which has the following structure:

Example 303 : #ADT directive  
/*#ADT 
  (T(x) A(x) E(x) D(x) F(x) K(x) X(x) W(x) R(x) 
   xy 'file name')
#TYPE
C code
#HEADING
C code
#BODY
C code
*/
  
where each x on the first line should be replaced by one of the characters B, H, Q, S or G. Replace y by P or I. The interpretation of these characters is similar to the their interpretation for operators.

-----------
B  Body      
H  Heading   
S  Standard  
G  Generate  
P  Prefix    
I  Infix     
-----------
The reason why G (generate) is not allowed for operators or literals is of course that it would mean to generate the implementation of the operators from the axioms, which is, at least in the general case, an impossible task. For an operator defined in an operator diagram, G is assumed independently of what the user specifies.

The specifications, given in ADT directives, of how to generate code for type definition, assignment, test for equal, default values, and free function should be interpreted according to the table below. More details about the functions can be found in the subsection "Help Functions" on page 2657.

Type Definition

First the actual type definition. The entry - should be interpreted as if no specification is given for T.

---------------------------------------------------------
Type  Interpretation                                       
---------------------------------------------------------
T(G)  Generate type definition from SDL sort               
T(B)  Do not generate type definition                      
T(H)  Generate type from SDL, but place it in a C comment  
T     Same as T(B)                                         
-     Same As T(G)                                         
---------------------------------------------------------

Assignment

It is possible to select how assignments should be performed for values of the type. Note that all generated assignments will be of the form:

yAssF_#(SortName)(....);
The yAssF_#(SortName) is a macro either implemented as assignment or as a call to the yAss_#(SortName) function (if such function is to be used), i.e as:

#define yAssF_#(S)(V,E,A) V = E
#define yAssF_#(S)(V,E,A) yAss_#(S)(&(V),E,A).
----------------------------------------------------------
Type  Interpretation                                        
----------------------------------------------------------
A(B)  Use and generate heading, but not body, of yAss_#(S)  
A(H)  Use, but generate no code for yAss_#(S)               
A(G)  ·  If the type definition is generated:               
      
  • Use = if possible.
  • Otherwise use and generate heading and body of the assign function yAss_#(SortName) · If type definition is not generated ( T, T(B) ):
  • Use = A(S) Use = A Same as A(B) - Same as A(G) ----------------------------------------------------------
  • Equal test

    It is possible to select how test for equality should be performed for values of the type. Note that all generated equal tests will be of the form:

    yEqF_#(SortName)(....);
    
    The yEqF_#(SortName) is a macro either implemented as C equal or as a call to the yEq_#(SortName) function (if such function is to be used), i.e as:

    #define yEqF_#(S)(E1,E2) E1 == E2
    #define yEqF_#(S)(E1,E2) yEq_#(S)(E1,E2)
    
    The /= operator is represented by the macro

    #define yNEqF_#(S)(E1,E2) (! yEqF_#(S)(E1,E2) ).
    
    ------------------------------------------------------------------
    Type  Method                                                        
    ------------------------------------------------------------------
    E(B)  Use and generate heading, but not body, of yEq_#(S)           
    E(H)  Use but generate no code for yEq_#(S)                         
    E(G)  ·  If the type definition is generated:                       
          
  • Use == if possible
  • Otherwise generate heading and body yEq_#(S). · If the type definition is not generated
  • Use == E(S) Use == E(Q) Use and generate an equal function that asks for the result of the test (same as Q for operators). E Same as E(B) - Same as E(G) ------------------------------------------------------------------
  • Initialization

    The default value that variables of the given type will be initialized to.

    -------------------------------------------------------------
    Type  Interpretation                                           
    -------------------------------------------------------------
    D(B)  Generate heading, but no body of default function 
    yDef_#(SortName). D(H) Generate neither heading nor body of default function. D(G) Generate both heading and body of default function, or use macro if adequate. D(S) Same as D(G) D Same as D(B) - Same as D(G) -------------------------------------------------------------

    Free of Dynamic Memory

    How dynamic memory (if used for the type) will be released for reuse when it is no longer needed.

    -------------------------------------------------------------
    Type  Interpretation                                           
    -------------------------------------------------------------
    F(B)  Generate heading, but no body of the free function       
          yFree_#(SortName).                                       
    F(H)  Generate neither heading nor body of the free function.  
    F(S)  Use the function xFree                                   
    F     Same as F(B)                                             
    -     Do not use free function.                                
    -------------------------------------------------------------
    

    Make!

    In the case of array or struct sorts there will be a make function to implement the constructor Make! defined in SDL.

    -------------------------------------------------------------
    Type  Interpretation                                           
    -------------------------------------------------------------
    K(B)  Generate heading, but no body of the make function       
          yMake_#(SortName).                                       
    K(H)  Generate neither heading nor body of the make function.  
    K(G)  Generate the make function                               
    K     Same as K(B)                                             
    -     Same as K(G)                                             
    -------------------------------------------------------------
    

    Extract! and Modify!

    This entry specifies how component selection (struct components, array components for example) should be performed. In SDL a component can be selected in two ways:

    Variable ! Component
    Variable (Index)
    
    An Extract operation can be generated in four ways:

    Variable . Component            used for struct
    Variable . U . Component        used for #UNION
    Variable . A (Index)            used for array
    yExtr_SortName(Variable, Expr)
    
    The last version, the Extract function, is used for all other cases.

    -----------------------------------------------------------
    Type      Interpretation                                     
    -----------------------------------------------------------
    X(B)      Use Extract function                               
    X(G)      Use component selection according to table above.  
    X         Same as X(B)                                       
    -         Same as X(G)                                       
    -----------------------------------------------------------
    
    A Modify operation can in the same way be generated in four ways:

    Variable . Component            used for struct
    Variable . U . Component        used for #UNION
    Variable . A (Index)            used for array
    (* yAddr_SortName((&Variable), Expr))
    
    The last version, the Addr function, is used for all other cases.

    -----------------------------------------------------------
    Type      Interpretation                                     
    -----------------------------------------------------------
    ?(B)      Use Addr function                                  
    ?(G)      Use component selection according to table above.  
    ?         Same as X(B)                                       
    -         Same as X(G)                                       
    -----------------------------------------------------------
    

    Write Function

    No write functions can be used with Cmicro. The alternative is to use the Cmicro Tester. You have to specify W(H), or else compilation errors will occur with undefined identifiers.

    The write function is used by the monitor system to write values of the type.

    -----------------------------------------------------------------
    Type  Interpretation                                               
    -----------------------------------------------------------------
    W(B)  Generate heading but not the body of a write function.       
    W(H)  Generate neither heading nor body of a write function, but   
          assume that the user has provided such a function.           
    W(S)  Values of this type are to be printed as a HEX string. No    
          write function is assumed to be present.                     
    W     Same as W(B)                                                 
    -     Same as W(S)                                                 
    -----------------------------------------------------------------
    

    Read Function

    No read functions can be used with the Cmicro Package. The alternative is to use the Cmicro Tester. You have to specify R(H), or else compilation errors will occur with undefined identifiers.

    The read function is used by the monitor system to read values of the type.

    -------------------------------------------------------------
    Type  Interpretation                                           
    -------------------------------------------------------------
    R(B)  Generate heading but not the body of a read function.    
    R(H)  Generate neither heading nor body of a read function,    
          but assume that the user has provided such a function.   
    R(S)  Values of this type are to be read as a HEX string. No   
          read function is assumed to be present.                  
    R     Same as R(B)                                             
    -     Same as R(S)                                             
    -------------------------------------------------------------
    

    Some more General Comments

    When generate is specified for a function, the Cmicro Generator might decide not to generate the heading of the function, as in some cases it is not needed.

    All code that is not generated is, of course, assumed to be included by the user in the #TYPE, #HEADING and #BODY sections in the #ADT directive.

    Another name for an assign function, equal function and so on may be used, by including the desired name within quotes together with the generation options in the #ADT directive.

    If for example the name of a certain assign function should be AssX, this can be obtained by specifying: A(B 'AssX') for the assign function. This name will then be used throughout the generated code, both in generated declaration and at the places where the function is called. Note that the name should be last in the specification for the actual function.

    An include statement may be generated together with or replacing the type definition by giving a file name within quotes last in the specification part of the #ADT directive, immediately before the first section with code.

    Example 304 : Including a File in ADT  
    
    If the directive

    /*#ADT (T(B) A(S) E(S) 'file name') */ 
    
    is used, the following include statement will be generated:

    #include "file name"
      
    
    -------------------------------------------------------------------
    Note:                                                                
    Turning off the generation of the objects contained in the include   
    file must be done by the user.                                       
    -------------------------------------------------------------------
    

    Help Functions

    Assign Function

    An assign function has the following heading:

    void yAss_#(SortName) 
      (#(SortName) *yVar,
       #(SortName)  yExpr,
       int          AssType)
    
    It should assign the value passed as second parameter to the variable passed as first parameter. The SDL predefined sort Charstring, has an assign functions xAss_SDL_Charstring, while all the other predefined types can use =. Sorts translated as enum types can always use =, while arrays (translated to arrays), powersets (translated to bit arrays), and struct sorts can use = if all components can use =. The remaining generators array (translated to linked list), powerset (translated to linked list), and string need assignment functions. A syntype in SDL uses = if its father type can use =, otherwise it uses the assign function of the father type.

    The extra third parameter in Assign functions should be given a value according to the ideas given below, preferably using the macros indicated.

    Equal Function

    An equal function has the following heading:

    SDL_Boolean yEq_#(SortName) 
      (#(SortName) yExpr1, #(SortName) yExpr2);
    
    It should return true or false depending on if the two values passed as parameters are equal or not. The SDL predefined sorts Charstring, Time, Duration and PId have equal functions:

    xEq_SDL_Charstring, 
    xEq_SDL_Time, 
    xEq_SDL_Duration, 
    xEq_SDL_PId, 
    
    while all the other predefined types can use ==. Sorts translated as enum types can always use ==, while arrays and struct sorts always have equal functions. A syntype in SDL uses == if its father type can use ==, otherwise it uses the equal function of the father type.

    Default Function

    All sorts defined in an SDL system, including the predefined sorts, will have a default function which is used to initialize variables of the actual sort. A default function has the following heading:

    void yDef_#(SortName) (#(SortName) *yVar)
    
    It should assign the default value to the variable passed as a parameter. The default function will in most cases be implemented using a macro (all predefined sorts, all sort with explicit default value, all sorts translated to enum type, all Syntypes). Only array and struct sorts without a default value will have a function as default function.

    -----------------------------------------------------------------------
    Note:                                                                    
    Memory can be spared, if the Cmicro Kernel initialization is used        
    (XMK_USE_KERNEL_INIT). The Cmicro Kernel then initializes each           
    predefined sort with 0. This may be incorrect, e.g.for charstrings. In   
    this case, users should provide a yDef_#(SortName) function for the      
    sort which is to be given an explicit defaultvalue.                      
    -----------------------------------------------------------------------
    

    Free Function

    For a sort which uses allocated memory and pointers, a user should specify how to return such memory to the pool of free memory, using a free function.

    void yFree_#(SortName) (#(SortName) **yVar)
    
    The function should take the address to a pointer, return the allocated memory to the pool of available memory and assign 0 to the pointer. The SDL predefined sort Charstring has an own free function:

    xFree_SDL_Charstring
    
    Each structured type (struct or array) which has a component that has a free function, will have a free function.

    Make Function

    For each array and struct sort (not Syntypes) there will be a generated make function, which is used as a constructor of array or struct values out of their respective components, according to the rules for the Make! operator in SDL.

    Example 305 : Make Function for Array / Struct   
    #(ArraySortName) yMake_#(ArraySortName)
    ( #(ComponentSortName) yExpr )
    #(StructSortName) yMake_#(StructSortName)
    ( #(ComponentSortName1) yComponenName1;
      #(ComponentSortName2) yComponentName2 )
      
    
    The number of parameters in a struct make function is the same as the number of components in the struct.

    Write Function

    Write functions are not applicable for the Cmicro Package.

    Read Function

    Read functions are not applicable for the Cmicro Package.

    Directives to the Cmicro Generator

    Syntax of Directives

    The Cmicro Generator recognizes a number of directives given mainly in SDL comments. The #ADT and #OP directives used in abstract data types are examples of such directives. The directives #ADT and #OP were described in the section "Implementation of User Defined Operators" on page 2635, in connection with abstract data types and are not further discussed here.

    The Cmicro Generator recognizes a number of directives given mainly in SDL comments. The #ADT, #OP, and #UNION directives used in abstract data types are examples of such directives. The directives #ADT and #OP were described in the section "Implementation of User Defined Operators" on page 2635, and #UNION at page 2629, in connection with abstract data types and are not further discussed here.

    A directive has the general structure:

    1. The start of comment character: /*
    2. A `#' character.
    3. The directive name.
    4. Possible directive parameters given in free syntax. That is, spaces and carriage returns are allowed here.
    5. The end of comment characters */.
    Upper and lower case letters are considered to be equal in directive names.

    Example 306 : #OP Directive  
    
    Take as an example the directive:

     /*#OP (B) */. 
    
    This comment will be recognized as a directive only if no other character is inserted in the sequence /*#OP. After this part, spaces and carriage returns may be inserted freely.

      
    

    Selecting File Structure for Generated Code - Directive #SEPARATE

    The purpose of the separate generation feature is to specify the file structure of the generated program. Both the division of the system into a number of files and the actual file names can be specified. There are two ways this information can be given.

    The Cmicro Generator can generate a separate file for:

    Example 307 : #SEPARATE Directive  
    system S; /*#SEPARATE 'filename' */ 
    block B; /*#SEPARATE */
    process type P1 inherits PType; /*#SEPARATE */
    process P2 (1, ); /*#SEPARATE */
    procedure Q; /*#SEPARATE */
      
    
    In the example above the two versions of separate directive, with or without file name, are shown. As can be seen a file name should be enclosed between quotes. The Cmicro Generator will append appropriate extensions to this name when it generates code.

    If no file name is given in the directive, the name of the system, block, process, or procedure will be used to obtain a file name. In such case the file name becomes the name of the unit with the appropriate extension (.c .h) depending on contents. The file name is stripped from characters that are not letters, digits or underscores.

    The possibility to set up full, user-defined, or no separation in the Organizer's Make dialog (see page 1112) and in the user-interface of a stand-alone Analyzer (see page 1541), can be used in a simple manner to select certain default separation schemes. This setting will be interpreted in the following way:

    Independently if No, User defined, or Full separation has been selected, the Cmicro Generator will use the file name specified in the Edit Separation dialog (see page 1123) or the #SEPARATE directive, for a file that is to be generated.

    An Example of The Usage of the Separate Feature

    In the following example a system structure and the #SEPARATE directives are given. The same information can easily be set up in the Organizer as well. This example is then used to show the generated file structure depending on selected generation option.

    Example 308 : #SEPARATE Directive  
    system S; /*#SEPARATE 'Sfile' */
      block B1; /*#SEPARATE */
        process P11; /*#SEPARATE 'P11file' */
        process P12;
      block B2;
        process P21;
        process P22; /*#SEPARATE */
      
    

    Applying Full Separate Generation

    If Full separate generation is selected then the following files will be generated:

    --------------------
    Sfile.c     Sfile.h   
    B1.c        B1.h      
    P11file.c             
    P12.c                 
    B2.c        B2.h      
    P21.c                 
    P22.c                 
    --------------------
    
    The .c files contain the C code for the corresponding SDL unit and the .h files contain the module interfaces.

    Applying Separate Generation

    If User defined separate generation is selected then the following files will be generated:

    ------------------------------------------------------
    Sfile.c    Sfile.h  Contains code for units S, B2, P21  
    B1.c       B1.h     Contains code for units B1, P12     
    P11file.c           Contains code for unit P11          
    P22.c               Contains code for unit P22          
    ------------------------------------------------------
    
    The user defined separate generation option thus makes it possible for a user to completely decide the file structure for the generated code. The comments on files and extensions given above are, of course, also valid in this case.

    Applying No Separate Generation

    If the separation option No is selected, only the following file will be generated:

    -------------------------------------
    Sfile.c   Contains code for all units   
    -------------------------------------
    
    The comments on files and extensions earlier are valid even here.

    Guidelines

    Generally a system should be divided into manageable pieces of code That is, for a large system full separate generation should be used, while for a small system no separate generation ought to be used. The possibility to regenerate and recompile only parts of a system usually compensate for the overhead in generating and compiling several files for a large system.

    ------------------------------------------------------------------
    Note:                                                               
    A file name has to be specified, in the Organizer Edit Separation   
    command, see page 1123 in chapter 22, The SDT Organizer or in the   
    #SEPARATE directive, if two units in the system have the same       
    name in SDL and should both be generated on separate files, other   
    wise the same file name will be used for both units.                
    ------------------------------------------------------------------
    

    Generating Several Programs from an SDL System - Directive #PART

    The purpose of the partitioning feature is to make it possible to generate several programs from an SDL system. This feature has two major application areas:

    1. Using one SDL system to implement a distributed application.
    2. Separate testing (simulation or validation) of one or a group of processes.
    The basic idea behind the partitioning feature is as follows. Use separate generation to obtain building blocks (C files). Then link an appropriate set of the files to form a program. In a program everything that is not part of the partitioning will be considered as being part of the environment. During the start-up, channels and signal routes leading to units not part of the partitioning will be redirected to the environment. Below a detailed description of the partition feature is given.

    The first step is to enable partitioning. This is performed in the Make dialog in the Organizer (see page 1112 in chapter 22, The SDT Organizer) or in SDL-PR by a #PART directive introduce according to the following example:

    SYSTEM Example; /*#PART*/
    
    Next, should be decided what possibility to have, when it comes to forming partitions. Use separate generation to obtain the appropriate C files. Note that processes generated on the same file must be part of the same partition.

    When the partitioning is enabled, each separate unit (except the system unit) will be represented by two c files:

    unitname.c and e_unitname.c
    where the file unitname.c is the ordinary file for the SDL object or objects. The file e_unitname.c is a file that should be used to indicate that this SDL object and all objects below it should not be part of this partition. The e_unitname.c file, which is an almost empty file, contains the appropriate code to redirect channels and signal route for this SDL object to the environment.

    The partitioning and the separate generation have now made it possible to obtain several partitions. Now it is up to the user to decide which partitions or programs that should be created. This information is not needed until the linking of the programs, so in should be entered by changing the link script in the generated make file.

    Example 309 : Partitioning a System  
    
    Below the demon game system will be used as example of how to handle partitions. The structure of this example is:

    SYSTEM demongame
      BLOCK DemonBlock
        PROCESS Demon
      BLOCK GameBlock
        PROCESS Main
        PROCESS Game
    
    The beginning of the generated make file for this example is given below, assuming that full modularity has been selected.

    # makefile for System: demongame
    include $(sctdir)/makeoptions
    default: demongame$(sctEXTENSION)
    demongame$(sctEXTENSION):demongame$(sctOEXTENSION) \
              DemonBlock$(sctOEXTENSION) \
              Demon$(sctOEXTENSION) \
              GameBlock$(sctOEXTENSION) \
              Main$(sctOEXTENSION) \
              Game$(sctOEXTENSION)
      $(sctLD) $(sctLDFLAGS) demongame$(sctOEXTENSION) \
                DemonBlock$(sctOEXTENSION) \
                    Demon$(sctOEXTENSION) \
                GameBlock$(sctOEXTENSION) \
                    Main$(sctOEXTENSION) \
                    Game$(sctOEXTENSION) \
              $(sctLINKKERNEL) \
              -o demongame$(sctEXTENSION)
      
    
    The part shown above contains the include of the makeoptions file, the default action, and the link script. Following this, there will be the compilation scripts for all the c files. The generated link script will link all units into the same program, that is, the default behavior of the make file is the same as before, making one program from an SDL system.

    To create a partition only containing the Main process (and not the Game and Demon processes), the link script becomes:

    Example 310 : Partitioning a System  
    default: mainproc$(sctEXTENSION)
    mainproc$(sctEXTENSION): demongame$(sctOEXTENSION) \
              e_DemonBlock$(sctOEXTENSION) \
              GameBlock$(sctOEXTENSION) \
              Main$(sctOEXTENSION) \
              e_Game$(sctOEXTENSION)
      $(sctLD) $(sctLDFLAGS) demongame$(sctOEXTENSION) \
                e_DemonBlock$(sctOEXTENSION) \
                GameBlock$(sctOEXTENSION) \
                    Main$(sctOEXTENSION) \
                    e_Game$(sctOEXTENSION) \
              $(sctLINKKERNEL) \
              -o mainproc$(sctEXTENSION)
      
    
    First the name of the executable program ought to be changed to indicate that it does not contain the complete system any longer. Here mainproc has been selected as a new name. Then, as nothing in the DemonBlock is to be part of the partition, DemonBlock.o is changed to e_DemonBlock.o in two places and all references to units defined in the DemonBlock (process Demon) are removed. The GameBlock.o file should still be used as some object in the block (process Main) is part of the partition. Main.o should, of course, also be used, but Game.o should be replaced by e_Game.o. Now, we have a complete make file that will generate a program called mainproc.sct, which is a simulation or application only containing the process Main. The same way of defining a partition can be used also when working with the SDT Validator, making it possible to validate the behavior of only a part of a system.

    Another example of a link script would be to generate two partitions, one containing the processes Main and Demon and the other partition containing the process Game:

    Example 311 : Link Script for Partition  
    default: maindemon$(sctEXTENSION) \
             game$(sctEXTENSION)
    maindemon$(sctEXTENSION):demongame$(sctOEXTENSION) \
              DemonBlock$(sctOEXTENSION) \
              Demon$(sctOEXTENSION) \
              GameBlock$(sctOEXTENSION) \
              Main$(sctOEXTENSION) \
              e_Game$(sctOEXTENSION)
      $(sctLD) $(sctLDFLAGS) demongame$(sctOEXTENSION) \
                DemonBlock$(sctOEXTENSION) \
                    Demon$(sctOEXTENSION) \
                GameBlock$(sctOEXTENSION) \
                    Main$(sctOEXTENSION) \
                    e_Game$(sctOEXTENSION) \
              $(sctLINKKERNEL) \
              -o maindemon$(sctEXTENSION)
    game$(sctEXTENSION): demongame$(sctOEXTENSION) \
              e_DemonBlock$(sctOEXTENSION) \
              GameBlock$(sctOEXTENSION) \
              e_Main$(sctOEXTENSION) \
              Game$(sctOEXTENSION)
      $(sctLD) $(sctLDFLAGS) demongame$(sctOEXTENSION) \
                e_DemonBlock$(sctOEXTENSION) \
                GameBlock$(sctOEXTENSION) \
                    e_Main$(sctOEXTENSION) \
                    Game$(sctOEXTENSION) \
              $(sctLINKKERNEL) \
              -o game$(sctEXTENSION)
      
    
    During the start up of an executable program formed from a partition, the channels and signal routes will be redirected in such a way that any path going to a unit that is not part of the partition will be redirected to the environment. This means also recomputing the signalset of all channels and signal routes. The consequence is that integration target testing can take place, where individual processes or blocks.

    Restrictions

    The following restrictions have to be considered when an SDL system is partitioned into several programs.

    When running the partition on the target the environment functions may have to take into account the redirected signals if so desired by the user.

    ----------------------------------------------------------------------
    Note:                                                                   
    Signals sent using OUTPUT without to and which should go to a           
    process not in the partition, will be sent to the environment, as the   
    channels and signal routes are redirected in that way.                  
    ----------------------------------------------------------------------
    

    Generating Partitioned Applications

    When it comes to generating applications using the possibility to partition an SDL system into several programs, we have to look at the .ifc files. The usage of such files are described in chapter 9, Building an Application, section "System Interface Header File" on page 453. The .ifc files contain the information that is relevant to build the interface between the system and its environment. When partitions are used, we have not only an interface between the system and its environment, but also between different partitions of the SDL system.

    To handle the system internal interfaces, .ifc files are generated not only for the system, but for also all units that have separate subunits. In this way, the relevant information is available for any partitioning that the user selects. A partition will have the same properties as the program for an SDL system described in chapter 9, Building an Application, except that the partition may have to include several .ifc files to obtain all the information necessary to implement the interface.

    Potential Problems with Macros

    A potential problem using the .ifc files is the macros of type:

    #define  SDL_Name  Name_Used_In_C
    
    Such macros are generated to simplify writing the interface code and they can be found for signals, channels, signal routes, synonyms, sorts, and literals for sorts translated to enum types in C. This means that if the same name is used for two of these objects in SDL, C macros are subject to cause problems (redefinition of macro).

    Accessing SDL Names in C Code
    - Directive #SDL

    When writing C code that is to be included in a generated program it is often necessary to refer to names of objects defined in SDL. The name of an SDL object is, however, transformed when it is translated to C. A prefix, which is a sequence of characters, is added to the SDL name to make the C name unique in the C program. Furthermore, all characters in SDL name which are not allowed in a C name are removed. The prefixes are calculated by looking at the structure of definitions in the actual scope and in all scopes above. This means that adding a declaration at the system level might change all prefixes in blocks and processes contained in the system. As a consequence it is almost impossible to know the prefix of an object in advance.

    To be able to write C code and use the name of SDL objects in that code, the Cmicro Generator provides the directive #SDL which is used in C code to translate an SDL name to the corresponding C name.

    The syntax of the #SDL directive is as follows:

    #SDL (SDL name)
    
    or

    #SDL (SDL name, entity class name)
    
    There is also a short form for the directive. No characters are allowed between the # character and the left parentheses in this form:

    #(SDL name) 
    
    or

    #(SDL name, entity class name)
    
    Replace SDL name with the name of an object in the SDL definition and entity class name by any of the following identifiers (upper and lower case letters are considered to be equal):

    -----------------------------------------
    block       operator     sort (= newtype)  
    blocksubst  predef       state             
    channel     procedure    synonym           
    connect     process      syntype           
    formalpar   processinst  system            
    generator   processtype  timer             
    label       signal       variable          
    literal     signallist                     
    newtype     signalroute                    
    -----------------------------------------
    
    This list contains all entity classes for Cmicro, which means that not all of the entries are relevant for practical use. When a #SDL directive is found in included C code, the Cmicro Generator first identifies what SDL object that is referred and then replaces the directive by the C name for that object. The search for the SDL object starts in the current scope (the scope where the C code is included), and follows the scope hierarchy outward to the system definition, until an appropriate SDL object is found. An appropriate SDL name is considered to be found if it has the specified name and is in the specified entity class. If no entity class name is given the search is performed for all entity classes.

    -------------------------------------------
    block         newtype      signal            
    blockinst     operator     signallist        
    blocksubst    package      signalroute       
    blocktype     predef       sort (= newtype)  
    channel       procedure    state             
    channelsubst  process      synonym           
    connect       processinst  syntype           
    formalpar     processtype  system            
    gate          remoteprd    systemtype        
    generator     remotevar    timer             
    imported      service      variable          
    label         serviceinst  view              
    literal       servicetype                    
    -------------------------------------------
    
    ------------------------------------------------------------------
    Note:                                                               
    #SDL should be used with care. A #SDL directive on some objects     
    might lead to overloading of names in C. Sensitive objects are pro  
    cesses, signal routes, channels.                                    
    ------------------------------------------------------------------
    
    ---------------------------------------------------------------------
    Note:                                                                  
    In types, especially in block types, #SDL should be used with care.    
    The reason is that some of the objects in a block type are generated   
    for each instantiation of the block. A #SDL directive on such an ob    
    ject might lead to overloading of names in C. Sensitive objects are    
    processes, process instantiations, signal routes, channels, remote     
    definitions.                                                           
    ---------------------------------------------------------------------
    
    The table in the subsection "SDL Predefined Types" gives the direct translation between an SDL name and the corresponding C name or expression (see page 2622). For these names the #SDL directive should not be used.

    Including C Code in Task - Directive #CODE

    The user's own C code may be included in tasks by using the #CODE directive. This directive has the following syntax:

    /*#CODE
    C code that should
    be included in
    generated code */
    
    Type the directive name on the first line and the C code on the following lines up to the end of comment symbol. Note that text on the same line as the #CODE directive is not handled.

    A #CODE directive can be placed:

    The C code in the directives is textually included in the generated code at the position of the directive. If, for example, a code directive is placed between two assignment statements, the code in the directive is inserted between the translated version of the assignment statements.

    ------------------------------------------------------------------
    Note:                                                               
    The Cmicro Generator handles the C code in directives as text and   
    performs no check that the code is valid C code.                    
    ------------------------------------------------------------------
    
    The code directive is included as a facility in the Cmicro Generator to provide experienced users an escape possibility to the target language C. This increases the application range of the Cmicro Generator.

    An example of a possible use of the code directive is: An algorithm for some computation, which in the SDL description is only indicated as a task with an informal text, could be implemented in C. In this case the directive #SDL described in the previous subsection will probably become useful to access variables and formal parameters defined in SDL.

    Some general hints on how to write C code that can be included into a simulation program, especially when charstrings or sorts containing charstrings as components are used, can be found in the last part of the section "Implementation of User Defined Operators" on page 2635.

    Unfortunately it is not possible to have C comments within the code that is included in any directive, as SDL and C use the same symbols for start and end of comments. See also Example 291 on page 2638 which illustrates the possibility to use the C macro COMMENT.

    Including C Declarations - Directive #CODE

    The #CODE directive can also be used to include C declarations; for example types, variables, functions, #define, and #include in the declaration parts of the C program. This version of the code directive has the following structure:

    /*#CODE
    #TYPE
    C code containing:
    Types and variables
    #HEADING
    C code containing:
    Extern or static declarations of functions
    #BODY
    C code containing:
    Bodies of functions
    */
    
    The separation of functions into HEADING and BODY sections serves the same purpose as in the #ADT directive, see "Implementation of User Defined Operators" on page 2635.

    Code directives to include C declarations may, generally speaking, be placed immediately after a semicolon that ends a declaration in SDL. More precisely it is allowed to place a #CODE directive after the semicolon that ends:

    In the following small PR example the allowed positions are marked with an * followed by a number.

    Example 312 : #CODE Directive  
    system s; *1
      signal s1, s2(integer); *2
      channel c1 from env to b1 
        with s1, s2; *3
      newtype n
        ...
      endnewtype n; *4
      block b1; *5
        signalroute sr1 from env to p1 
          with s1, s2; *6
        connect c1 with sr1; *7
        process p1 (1,1); *8
          signalset s1, s2; *9
          dcl a n; *10
          start;
            ...
          state ...;
            ...
        endprocess p1; *11
      endblock b1; *12
    endsystem s1;
        
    
    A code directive is considered to belong to the unit where it is defined and the declarations within the directive are thus placed among the other C declaration for that unit. In the example above, directives at positions 1, 2, 3, 4, 12 belong to system s, directives at positions 5,6,7,11 belong to block b1, while directives at positions 8, 9, 10 belong to process p1. Only one code directive may be placed at each available position.

    ------------------------------------------------------------------------
    Note:                                                                     
    A variable declared in a #CODE directive that belongs to a process        
    will be shared between the process instances of the process type.         
    Such a variable should only be used to represent some common              
    property of all the process instances. To have a variable that is local   
    to a process instance, the variable should be defined in SDL using        
    DCL.                                                                      
    ------------------------------------------------------------------------
    
    In the generated code the type sections are included in the order of appearance in SDL. However, the type sections are also sensitive with respect to the relative position within SDL sort definitions. This means that the order of the type definitions in the system in the example above will be as follows:

    1. Type sections in 1, 2, 3
    2. Type generated for newtype n
    3. Type sections in 4, 12.
    As the Cmicro Generator will generate the SDL sorts in the correct order, definition before usage, in C, the full algorithm is as follows.

    The heading sections are placed in the order of their appearance in SDL. This applies to the body sections as well. All body sections will be placed after the sequence of heading sections and the heading section will be placed after all the type definitions. The SDL declarations made in the corresponding unit are available in the code directives and can as usual be reached using the #SDL directive. All declarations made in code directives are of course available in code directives in tasks in the corresponding unit or in its subunits.

    The general hints on how to write C code that fits into a generated C program given in the section "Implementation of User Defined Operators" on page 2635 and in the section "Accessing SDL Names in C Code - Directive #SDL" on page 2670 are also applicable here.

    Including C Code in SDL Expressions - Operator #CODE

    For each sort defined in an SDL system, both predefined and user defined, the Cmicro Generator includes an operator #CODE with the following signature:

    #CODE : Charstring -> S;
    
    where S is replaced by the sort name. This operator or rather these operators make it possible to access variables and functions defined in C using the #CODE directive in SDL expressions and still have syntactically and semantically correct SDL expressions.

    During code generation, the Cmicro Generator will just copy the Charstring parameter at the place of the #CODE operator.

    Example 313 : #CODE Directive  
    
    Suppose that x and y are SDL variables, which are translated to z72_x and z73_y, that a and b are C variables, and f is a C function defined in #CODE directives.

    -----------------------------------------
    SDL expression         C expression        
    -----------------------------------------
    x + #CODE('a')         z72_x + a           
    x + #CODE('a*b')       z72_x + a*b         
    x*#CODE('(a+b)')*y     z72_x*(a+b)* z73_y  
    #CODE('f(a,#SDL(x))')  f(a, z72_x)         
    -----------------------------------------
    
      
    
    Within the Charstring parameter of a #CODE operator the #SDL directive is available in the same way as in other included C code. This is also shown in the last of the examples above.

    As there is one #CODE operator for each sort in the system, it is sometimes necessary to qualify the operator with a sort name to make it possible for the SDL Analyzer to resolve which operator that has been used. If, for example, the question and all answers in a decision are given as applications of #CODE operators, then it is not possible to determine the type for the decision. One of the #CODE operators should then be qualified with a sort name to resolve the conflict.

    Example 314 : Code Directive  
    DECISION #CODE('a');
        (#CODE('1')) : TASK ...;
        (#CODE('2')) : TASK ...;
    ENDDECISION; 
    
    In this case the sort of the decision cannot be resolved. To overcome this problem the question could be written as

    DECISION TYPE integer #CODE('a');
      
    

    Names and Prefixes in Generated Code

    When an SDL name is translated to an identifier in C, a prefix is normally added to the name given in SDL. This prefix is used to prevent name conflicts in the generated code, as SDL has other scope rules than C and also allows different objects defined in the same scope to have the same name, if the objects are of different entity classes. It is, for example, allowed in SDL to have a sort, a variable and a procedure with the same name defined in a process. So the purpose of the prefixes is to make each translated SDL name to a unique name in the C program.

    A generated name for an SDL object contains four parts in the following order:

    1. The character "z"
    2. A sequence of characters that make the name unique. If the object is part of a package, the package name will appear in this sequence.
      (packages are not supported when using the micro package)
    3. An underscore "_"
    4. The SDL name stripped from characters not allowed in C identifiers.

    Sequence of Characters

    A C identifier may contain letters, digits, and underscore "_" and must start with a letter.

    The sequence of characters that make the name unique is determined by the position of the declaration in structure of declarations in the system:

    The total sequence making a name unique is now constructed from the "declaration numbers" for the unit and its parents, that is the units in which it is defined, starting from the top.

    If, for example, a sort is defined as the 5th declaration in a block that in turn is the 12th declaration in the system, then the total sequence will be b4 (if not more than 36 declarations are present on any of the two levels).

    Example 315 : Generated Names in Code  
    
    Examples of generated names:

    -----------------------------------------------------------
    SDL   Position of the Declaration                Generated   
    Name                                             Name        
    -----------------------------------------------------------
    S1    10th declaration in the system             z9_S1       
    Var2  3rd declaration in the process, which is   ze42_Var2   
          the 5th declaration in the block,                      
          which is the 15th declaration is system                
    -----------------------------------------------------------
    
      
    
    There will also be other generated names using the prefixes. If, for example, a sort MySort is translated to za2c_MySort, then the equal function connected to this type (if it exists) will be called yEq_za2c_MySort.

    Prefixes

    This strategy for naming objects in the generated code should be used in all normal situations, as it guarantees that no name conflicts occur. The Cmicro Generator offers, however, possibilities to change this strategy. In the Make dialog in the Organizer (see chapter 22, The SDT Organizer, on page 1112) and in the user interface an Analyzer running stand-alone (see "Analyzer Command-Line UI" on page 1541 in chapter 31, The Analyzer), it is possible to select one of the following strategies: full prefix, entity class prefix, no prefix, or special prefix. Full prefix is default and is the strategy described above.

    Entity Class Prefix

    If entity class prefix is selected, then the prefix that is concatenated with the SDL name will be in accordance with the table below and depends only of the entity class of the object.

    ------------------------------------------------
    Entity class        Prefix  Entity class  Prefix  
    ------------------------------------------------
    Block               blo     Signal        sig     
    Block substructure  bls     Signal list   sil     
    Channel             cha     Signal route  sir     
    Connection          con     Sort          sor     
    Formal parameter    for     State         sta     
    Generator           gen     Syntype       syt     
    Label               lab     Synonym       syo     
    Literal             lit     System        sys     
    Operator            ope     Timer         tim     
    Procedure           prd     Variable      var     
    Process             prs                           
    ------------------------------------------------
    
    -------------------------------------------------------------
    Entity class          Prefix  Entity class             Prefix  
    -------------------------------------------------------------
    Block, block type,    blo     Process, Process type,   prs     
    block instance                Process instance                 
    Block substructure    bls     Remote procedure         rpc     
    Channel               cha     Remote variable          imp     
    Channel substructure  chs     Service, Service type,   ser     
                                  Service instance                 
    Connection            con     Signal                   sig     
    Formal parameter      for     Signal list              sil     
    Gate                  gat     Signal route             sir     
    Generator             gen     Sort                     sor     
    Import                imp     State                    sta     
    Label                 lab     Syntype                  syt     
    Literal               lit     Synonym                  syo     
    Operator              ope     System, System type      sys     
    Package               pac     Timer                    tim     
    Predef                pre     Variable                 var     
    Procedure             prd     View                     vie     
    -------------------------------------------------------------
    
    Using entity class prefix means that the user must guarantee that no name conflict occurs. It also means, however, that the generated names are predictable and thus simplifies writing C code where the SDL names are used. It is only needed to look for name conflicts within entity classes, for example not having two sorts with the same name. The entity class prefixes handle the case when two objects of different entity class have the same name. Note that the table above contains all entity classes. Not all of the items are actually used by the Cmicro Generator.

    No Prefix

    The second alternative, no prefix, means of course that no prefixes are added to the SDL name. The name in the C program will then be the SDL name, stripped from characters that are not allowed in C identifiers (everything except letters, digits, and underscore). In this case, the user must guarantee that no name conflict occurs and that the stripped name is allowed as a C identifier, that is, that it begins with a letter.

    Special Prefix

    In the third alternative, special prefix, full prefixes are used for all entity classes except variable, formal parameter, sort, and syntype. For these entity classes, no prefix is used.

    --------------------------------------------------------------------
    Note:                                                                 
    If the OO diagram types in SDL-92 are used (system type, block        
    type, process type), full prefix should always be used, as the OO     
    concepts in itself most likely mean the name conflicts will be intro  
    duced in C.                                                           
    --------------------------------------------------------------------
    

    Conclusion

    As was said in the beginning of this subsection, the user should have a good reason for selecting anything but the full prefix, as it could be very difficult to spot name conflicts. The C compiler will in some cases find a conflict, but may in other cases consider the program as legal and generate an executable program with a possibly unwanted behavior.

    The note above about the OO concepts is also a strong argument for full prefix.

    Case Sensitivity

    Another aspect concerning identifiers is, that SDL is case insensitive, while C is case sensitive. This might introduce problems.

    The following strategy for upper and lower case letters is used by the Analyzer and Cmicro Generator.

    During lexical analysis each unique SDL name is stored in a name table. Only one occurrence of a name, according to the rules of SDL, will be stored in the table. This means that the first found occurrence of a name will govern how that SDL name will be seen, when it comes to upper and lower case letters. The Cmicro Generator will use the names in the name table to generate C names.

    This strategy normally works very well, as each occurrence of a C name is generated in the same way and as uniqueness of the C identifiers are obtained using the prefixes. If you, however, are about to use the SDL name in included C code, in for example a #CODE directive, then you need to know how upper and lower case letters are used in the C name. This might be a problem if you have multiple occurrences of the name using different combinations of upper and lower case letters. As the #SDL directive handles this problem correctly, you will come across the problem mainly for struct components which do not have prefixes and for which the #SDL directive should not be used.

    As a solution for this and for other potential problems concerning upper and lower case letters in C names, the Cmicro Generator has an option to translate all SDL names to lower case. Such a translation scheme can be selected in the Make dialog in the Organizer (see "Make" on page 1112 in chapter 22, The SDT Organizer) or in the user interface of the Analyzer, when it is executed stand-alone (chapter 31, The Analyzer, on page 1541).

    Specifying Names in Generated Code - Directive #NAME

    If you wish to decide the name of an object in generated code yourself you can use the #NAME directive. Place the directive directly after the name in the declaration of the object. It should contain the desired name to be used in the generated code within quotes.

    Example 316 : #NAME Directive  
    NEWTYPE S /*#NAME 'S' */ STRUCT
      a integer;
      b Boolean;
      ADDING OPERATORS
        Op /*#NAME 'OtherName' */ :
          S, S -> Boolean;
    ENDNEWTYPE;
      
    
    The name defined in a #NAME directive will be used everywhere that the SDL name is used in the generated files, with the exception, that the names of the files for generated code are not affected by the usage of #NAME directives.

    There are however some restriction on where #NAME directives can be placed.

    Some objects in for example a block type are generated in each instantiation of the block type. If a name directive is placed at such an object, the name will probably be overloaded in C, resulting in a C compilation error. The sensitive objects are processes, process instantiations, signal routes, channels, remote variables, and remote procedures.

    Assigning Priorities Directive #PRIO

    #PRIO for Processes

    Priorities can be assigned to processes using the directive #PRIO. The process priorities will affect the scheduling of processes, see "Scheduling" on page 2615. A priority is a positive integer, where low value means high priority. #PRIO directives should be placed directly after the process heading in the definition of the actual process.

    Example 317 : #PRIO Directive  .
    Process P1; /*#PRIO 0 */ 
    Process P2(1,1); /*#PRIO 1 */ 
    Process P3 : P3Type; /*#PRIO 0 */ 
    Process P4(1,1) : P4Type; /*#PRIO 1 */ 
      
    
    Processes that do not contain any priority directive will have a user defined default priority with the name xDefaultPrioProcess.

    There are some things to be kept in mind using process priorities:

    #PRIO for Signals

    Priorities can be assigned to signals using the directive #PRIO. The signal priorities will also effect the scheduling of processes, see "Scheduling" on page 2615.

    Signal priorities can be specified either

    It is impossible to specify #PRIO in a SDL input. Cmicro will ignore any occurrence of #PRIO in SDL input.

    Signal priorities do affect the SDL output and the SDL create actions only.

    The following rules are to be considered here:

    The following example will give more explanations (note, that the values PA, PB are of sort pid):

    Example 318 : #PRIO Directive  .
    Signal
    S1, /*#PRIO 11 */ 
    S2, /*#PRIO 22 */ 
    S3,  
    S4; /*#PRIO 44 */ 
    ....
    output S1 to PA
    output S1 to PB; /*#PRIO 55*/
    ....
    output S3 to PC;
    output S3 to PD; /*#PRIO 66*/
      
    
    Assuming the following C definition:

    #define xDefaultPrioSignal 100
    
    the following priorities will then be generated:

    output S1 to PA  --->use of prio 11
    output S1 to PB--->use of prio 55
    ....
    output S3 to PC--->use of prio 100
    output S3 to PD--->use of prio 66
    

    Initialization - Directive #MAIN

    The #MAIN directive is used to include initialization code that should be executed before any process transitions are started. The directive should be placed in the system definition directly after the system heading.

    Example 319 : #MAIN Directive  
    System S;
    /*#MAIN 
    C code for initialization */
      
    
    The #MAIN directive has exactly the same structure as the #CODE directive for including code in tasks. The included code will, however, be placed in the C function main, after the initialization of the internal structure, but before any transitions are executed.

    Modifying Outputs - Directive #EXTSIG, #ALT, #TRANSFER

    The purpose of these directives is to modify the standard behavior of an SDL output. The #EXTSIG directive can be used to build applications with the SDT run-time library. The directives #ALT and #TRANSFER are only useful together with other real-time operating systems.

    The directive #EXTSIG is used to replace the code for an SDL output with any appropriate in-line C code. This is an optimization and an alternative to the xOutEnv function (see chapter 9, Building an Application). The #EXTSIG directive can be specified:

    In the first case the #EXTSIG is valid for the signal(s) sent in the output symbol, and in the second case for all outputs of the defined signal.

    Example 320 : #EXTSIG Directive  
    signal
      Signal1          /*#EXTSIG */,
      Signal2(integer) /*#EXTSIG */;
    output Signal3 To Sender /*#EXTSIG */;
      
    
    For each output of a signal with a #EXTSIG directive (in either way described above) the following code is generated:

    #ifndef EXT_SignalName
      "the normal implementation of an output"
    #else
      EXT_SignalName(
        SignalName, SignalNameWithPrefix,
        ToExpression, SignalParameters)
    #endif
    
    where SignalName is the name of the signal in SDL. The parameter ToExpression is a translated version of the SDL expression after to in the output. If a to expression is given in the output, this parameter will be either self, sender, parent, offspring, or a variable of sort pid. If no to expression is given in the output, then the process behind that output, found via signalroute and channel, is given (therefore, the signal must have only one possible receiver). The entry SignalParameters will be replaced by the list of signal parameter values given in the output.

    The intention of this code is to give the user a possibility to introduce a macro with the same name as the signal, where the implementation of the output is expanded to in-line code. By just having a compilation switch which governs if this macro is visible or not, the same generated code can be used both for simulation and for applications. An appropriate switch is probably XENV, which governs the normal way of connecting an SDL system to the environment.

    Example 321 : #CODE Directive  
    
    The following #CODE directive can be included in a text symbol in the system diagram (assuming a signal called SigName with one parameter).

    /*#CODE
    #TYPE
    #ifdef XENV
    #define EXT_SigName(Name, IdNode, ToExpr, Param1) \
       suitable macro code
    #endif
    */
      
    
    The other two directives, #ALT and #TRANSFER, can be used together with appropriate real-time operating systems, to have two different interpretations of an output (internal or external output for example) and to specify that a received signal should be immediately retransmitted (#TRANSFER). These kinds of features are not uncommon in real-time operating systems, and can be modeled and simulated by the Cmicro Generator using these directives.

    Both these directives should be placed last in the output symbol.

    Linking with Other Object Files - Directive #WITH.

    -------------------------------------------------------------------
    Note:                                                                
    This feature is only valid for SDL-PR as input, when the Analyzer    
    is executed stand-alone. Similar features are available in the Orga  
    nizer's Make dialog among the Generate makefile options, see page    
    1115 in chapter 22, The SDT Organizer.                               
    -------------------------------------------------------------------
    
    You can tell the Cmicro Generator that a number of user defined and precompiled units should be linked together with a generated simulation program. You do this in a #WITH directive that should be placed in the system definition directly after the system heading.

    Example 322 : #WITH Directive  
    System S; /*#WITH 'file1.o' 'file2.o' */
      
    
    Within the #WITH directive the object files that are to be part in the link operation should be given between quotes, as in the example above. These files will be included in the definition of the link operation in the generated .m file.

    The make file will, however, not include any definition of how to compile the corresponding source files, as it is impossible for the Cmicro Generator to know the compilation options or even what compiler the user wants. A user that knows how to interface routines in other languages in a C program, can with this knowledge and the #WITH directive link modules written in another language together with the generated program.

    --------------------------------------------------------------------
    Note:                                                                 
    The #WITH directive will only affect the generated make file. There   
    will be no change in the generated C code when a #WITH directive      
    is introduced.                                                        
    --------------------------------------------------------------------
    

    Naming Tasks in Trace Output - Directive #ID

    To simplify the identification of a TASK in a trace printout, the Cmicro Generator uses the variable on the left hand side of the first assignment statement or the first informal text in the task symbol.

    A user that is not satisfied with this can name the tasks using #ID directives. An ID directive should contain the character string that is to be used as identification in trace printouts as shown in the example below. The switch enabling the ID directive to be included after preprocessing is XTRACE, this would normally not be set for Cmicro applications, but set for Cmicro Tester.

    Example 323 : #ID Directive  
    /*#ID 'Identification of task' */
      
    
    The Cmicro Generator will use the first ID directive it finds in a TASK (if any). An ID directive may be placed:

    Using the Cmicro Generator to Generate C++

    ---------------------------------------------------------------------
    Note:                                                                  
    This section is only applicable if you have compiled versions of the   
    runtime library that can be linked together with the object files pro  
    duced by the C++ compiler. In most cases this means that you must      
    have the SDT Cmicro Library, i.e. have source code for the runtime     
    library.                                                               
    ---------------------------------------------------------------------
    

    General

    The C code in the Cmicro Library and the C code generated by the SDT Cmicro Generator is in the common subset of C and C++(FBI_C), and will thus compile both as a C program and as a C++ program. There is one special feature in the Cmicro Generator concerning C++ when it comes to abstract data types and the possibility to match a C++ class and an SDL data type. Otherwise all the features for including C code, directive #ADT, directive #CODE (see page 2622 and page 2670), and so on, are directly applicable for C++ as well. The #CODE directives make it possible to include class definitions as C++ code and the utilization of the classes as C++ code in SDL tasks.

    Example 324 : Using C++ Classes  
    
    CODE directive containing declarations (see page 2674) which should be placed among the SDL declarations:

    /*#CODE
    #HEADING
    class TEST {
    public:
      void putvar(int avar, int bvar)
        {a = avar; b = bvar;}
      int  geta()
        {return a;}
      int  getb()
        {return b;}
    private:
      int a,b;
    } TESTvar;
    */
    
    Example of usage of the class in a CODE directive in a TASK (see page 2673).

    TASK '' /*#CODE
              TESTvar.putvar(#(I), #(I)+10); */;
    
    Example of usage of the class in a CODE operators in expressions (see page 2677).

    OUTPUT Score(
      #CODE('TESTvar.geta()'),
      #CODE('TESTvar.getb()'),
      #CODE('#(TClass)->getVar()')
    );
      
    

    Connection between C++ Classes and SDL

    To obtain a close connection between a C++ class and SDL, an abstract data type in SDL can be used; see below.

    If you have a C++ class (from a class library or developed specifically for the project), then the following correspondence rules can be used to map the class on an abstract data type.

    -----------------------------------------------------
    C++                     SDL                            
    -----------------------------------------------------
    Class definition        Abstract data type definition  
    Class instance pointer  Process variable               
    Member functions        Operators                      
    new, delete             Operators                      
    -----------------------------------------------------
    
    Example 325 : SDL and C++ Class  
    
    Suppose we have a C++ class with the following interface (.h file):

    class TestClass {
    public :
      TestClass (int);
      TestClass ();
      ~TestClass ();
      int updateVar(int);
      int getVar();
    private :
      int v;
    };
    
    then the following abstract data type can be used to represent the class (in the example the NAME directive, see page 2683, is used to instruct the Cmicro Generator which name to use in C for particular SDL objects):

    NEWTYPE TestClass     /*#NAME 'TestClassPtr' */
      LITERALS
        newTestClass      /*#NAME 'new1TestClass' */
        ;
      OPERATORS
        newTestClass      /*#NAME 'new2TestClass' */
          : integer -> TestClass;
        deleteTestClass
                           /*#NAME 'deleteTestClass' */
          : TestClass -> TestClass;
        updateVar        /*#NAME 'updateVar' */
          : TestClass, integer -> integer;
                       /*#OP(HC) */
        getVar           /*#NAME 'getVar' */
          : TestClass -> integer;
                       /*#OP(HC) */
    /*#ADT(T A(S) E(S) D(H) H P)
    #TYPE
    #include "TestClass.h"
    typedef TestClass * TestClassPtr;
    COMMENT((NOTE! SDL data type TestClass is
            pointer to C++ class TestClass))
    #HEADING
    #define yDef_TestClassPtr(p)  *(p) = 0
    #define new1TestClass()   new TestClass()
    #define new2TestClass(P)  new TestClass(P)
    extern TestClassPtr deleteTestClass
      (TestClassPtr);
    #BODY
    extern TestClassPtr deleteTestClass
      (TestClassPtr P)
    {
      delete P;
      return (TestClassPtr)0;
    }
    */
    ENDNEWTYPE;
    
    Note that the #ADT specification means that no code will be generated for the abstract data type. The abstract data type can utilized in the following way:

    DCL
      TClass TestClass,
      I      Integer;
    TASK TClass := newTestClass;
    TASK TClass := newTestClass(2);
    TASK I := updateVar(TClass, I);
    TASK I := getVar(TClass);
    TASK TClass := deleteTestClass(TClass);
      
    
    The only feature that is not described before is the C option in the #OP directive. C (class) is an alternative to I (infix) and P (prefix), and specifies that the operator call should be translated to a member function call of a C++ member function. #OP(C) means that an operator call

    F(a, b, c)
    is translated to

    a->F(b, c)

    --------------------------------------------------------------
    Note:                                                           
    This means that each operator mapped on class member function   
    should have the class instance pointer as first parameter.      
    --------------------------------------------------------------
    

    Restrictions and SDL-92 Supported Features

    SDL Restrictions

    General

    The SDT Cmicro Generator handles SDL concepts according to the definition of SDL-92. The following constructs are not supported:

    Restrictions in Combination with Cmicro Tester

    Scope rules / Qualifiers

    If the Cmicro Tester is to be used, then the scope rules of SDL are handled in a restrictive fashion. No information is generated for the system, block, block substructure, channel and signalroute. After applying the Cmicro Generator, all the structuring information is lost.

    This means: It is impossible to address two different processes with the same name in different blocks. In order to avoid problems, give all processes, signals and timers in the system a different name.

    Predefined Sorts

    The predefined sort charstring cannot be handled, if the Cmicro Tester is to be used. In order to get a detailed description, please see "Restrictions of sdtmt" on page 3034 in chapter 46, The Cmicro Tester.

    SDL-92 Supported Features

    Timer

    The SDL-92 duration constant expression for timers is supported.

    Example 326 : Timer  
    dcl Timer T := 10;
    TASK
    Set (T)   /* Default  is 10 */
      
    

    Output

    The possibility to specify the name of a process when using "output-to" is implemented. This is an SDL-92 feature. The Cmicro Generator behaves in the same way as when using implicit addressing (output without to).

    Example 327 : output   
    output to processname
      
    
    where processname is the name of a process, which is to be declared in the same scope unit, e.g.the same block.

    Procedures and Operator Diagrams

    In SDL-92 the following has been introduced:

    These constructs can be handled with the following restrictions (as a common restriction for all C Code Generators):

    Analyzer Restrictions

    The restrictions in the SDT Analyzer, which of course also affects the Cmicro Generator, are summarized below. For more information see chapter 31, The Analyzer, page 1573.

    Common C Code and Cmicro Generator Restrictions

    The Cmicro Generator introduces more severe restrictions on the allowed set of SDL concepts than the Analyzer:

     
    Table of Contents Next Chapter