![]() |
![]() |
![]() |
![]() |
![]() |
Migration Guide for Generic Functions
General
This section provides help to migrate a system using old-style code generation for operators to the new Generic Function style.
Introduction
The basic idea of the generic function approach is to decrease the number of generated help functions and functions for operators in predefined generators. This is accomplished by generating generic functions that can be re-used by different types.
This means, for instance, that only one assignment function is created. This function, however, can be used by all types. In the old-style method, one assignment function was created for each type. For operators in predefined generators, there is now one single length function calculating the length of all string generator instantiations.
In order to implement the generic functions, the parameter passing mechanisms have been changed. In principle, a generic function cannot take a value as parameter, it must receive a pointer to the value. This approach has a positive effect on the performance. However, the generic function approach introduces incompatibility problems if your existing system calls generated functions from inline C-code. If this is the case, the function calls must be changed.
If you need to migrate an SDL system created with the old-style code generation, you must solve the incompatibility issue.
References to Information
Generic Functions
The major source of information regarding generic functions is Abstract Data Types, which contains a number of sections discussing different aspects of data types and operators:
- Translation of Sorts describes how different SDL types are translated to C.
- Parameter Passing to Operators discusses the general parameter passing principles for operators and literal functions. This section also lists which types that are passed as values and which types that are passed as addresses.
- Implementation of User Defined Operators describes how to include your own implementation in C for an operator.
- Generic Functions introduces you to the type info node concept and describes the general operators assign, equal, free, etc.
- Generic Function for Operators in Pre-defined Generators describes the operators in the predefined generators.
- More about Abstract Data Types comprises information on how to change the implementation of a data type.
SDL Data Types
Information on SDL data types and operators, seen from the SDL point of view, is available in Using SDL Data Types. Although this section does not discuss the use of generic functions, it provides the framework for SDL data types and operators. In some circumstances it might be better to rewrite a data type or operator in SDL, than to fix the problems in C. A number of extensions and improvements have been included in the support for data types.
Type Info Nodes
For more information on the contents of the type info nodes, please see Type Info Nodes. This section does not cover migration aspects, but provides implementation details for an interested reader.
Migrating Strategy
Overview
The common problems that might occur when migrating a system from the old-style operator implementation to the generic functions implementation can be divided into two groups:
- Some user-defined SDL operators have changed their prototypes in C. This means that user-provided implementations of the operators have to be changed and that calls to such operators directly from C have to be changed.
- Predefined operators like assignment, equal test, make, and so on, as well as operators in predefined generators might have changed their prototypes in C, which means that calls to such operators directly in C have to be changed. Also types where the implementation of assignment, equal and similar operators are changed by a #ADT directive, might have to be updated.
The first of these problems is fairly straight forward to fix, while the second might be more complex.
Step 1: Identifying Migration Problems
Before continuing with the migration instructions, check if your SDL systems are affected by any incompatibility problems.
- Find an SDL system that compiles without errors in a previous version of the SDL Suite (with the old-style operator implementations)
- Open it in the new version of SDL Suite.
- Compile it and see if you get any compilations errors.
If your compilation errors are similar to the errors in Example 419 you can assume that you have a migration problem.
Example 419 : Compilation Errors
The compilation error in this example originates from the GNU compiler, gcc. It gives a fairly good feeling of what kind of errors you can expect.
file.c:50825: conflicting types for `yAss_example'file.c:50844: conflicting types for `yEq_example'file.c:51496: conflicting types for `op1'file.c:211376: too many arguments to function `op1'file.c:211376: cannot convert to a pointer typefile.c:6042: incompatible type for argument 2 of `GenericAssignSort'file.c:6081: incompatible type for argument 2 of `op1'Step 2: Locating the Compatibility Problems
The Cadvanced, Cbasic, and Cmicro SDL to C compilers allows you to find the operators and literals that should be updated. By setting the environment variable SDT_COMP_WARN the code generators will produce a file called compatibility.warn in the target directory, while generating code for the system. In the first section of this file all operators and literals that might have to be changed are listed.
Example 420 : Contents of compatibility.warn
LITERAL NewDb C-name: z0V0_NewDb<<SYSTEM accesscontrolooa>>#SDTREF(TEXT,file.sdl,57,12)Literal function result passed as addressOPERATOR ValidateCard C-name: z0V1_ValidateCard<<SYSTEM accesscontrolooa/TYPE CardDbType>>#SDTREF(TEXT,file.sdl,59,5)Parameter 2 passed as addressUsed in DIRECTIVE at #SDTREF(TEXT,file.sdl,62)Used in DIRECTIVE at #SDTREF(TEXT,file.sdl,62)This example shows one literal and one operator that have to be updated:
- The first line contains the name of the operator/literal in SDL and in C.
- The second line contains an appropriate qualifier, that gives information on where in the system the item is defined.
- The third line is the SDT reference to the operator/literal. This can be used in the Organizer's Goto Source feature to show where the SDL source is located.
- The following lines indicate where changes are needed. Each line states that the result or a parameter is passed as an address. This means that previously this item was passed as a value, but now it should be passed as an address. A complete list of types that must be changed can be found in Mapping Table.
- Last, a number of cross references might be found. These show places where the operator is called from inline C using an #SDL directive. These calls might have to be updated.
Step 3: Updating Operators and Literals
For each operator or literal that is listed in the file compatibility.warn, perform the instructions presented in this section.
Updating the Headers
The headers of the corresponding C functions must be updated. If you have specified #OP(B), the header is generated and thus already correct, but if you have specified #OP(H), you have included the header in C probably in the #HEADING section in the #ADT directive for the type.
- For each parameter that should be passed as an address, add a `*' after the corresponding type name in C.
- If the result should be passed as an address, add a `*' after the result type in C, and add an extra parameter with the same C type as the updated function result, last among the parameters.
When this step has been performed for all types, the C compilation errors will be reliable again.
extern str lit1 (void);extern str op1 (str, SDL_Integer);Assume str is the type that should be passed as an address. The results of both functions and the first parameter of op1 are mentioned in the compatibility.warn file. The heading should be updated to:
extern str* lit1 (str*);extern str* op1 (str*, SDL_Integer, str*);Updating Parameter Specifications
The parameter specification and result in the function implementation must be updated to match the heading. The function implementation is probably in the #BODY section in the #ADT directive of the type.
Example 422 : Parameter Specifications (continued from Example 421)
str lit1 (void){ .... }str op1 (str P1, SDL_Integer P2){ .... }str* lit1 (str* Result){ .... }str* op1 (str* P1, SDL_Integer P2, str* Result);{ .... }Updating Operator/Literal Functions
The implementation of the operator/literal functions must be updated to reflect the change in parameters.
Example 423 : Operator/Literal Functions (continued from Example 422)
In the function op1 every occurrence of:
- P1 should be replaced by (*P1)
Special cases where other changes might be more appropriate:
- &P1 should be replaced by P1
- P1.abc should be replaced by P1->abc
The new Result parameter must be assigned the result value of the function and the function must end with a return statement.
Example 424 : Return Parameter
It is not unusual that the function contains a local variable used for calculating the result. Normally this variable is no longer needed.
While updating the implementation of the function, information from the next section on, for example, assign and equal function might be valuable.
Check that parameters that are passed as addresses are NOT CHANGED within the function. If that is the case, copy the value to a local variable first, and work with that variable.
Update Calls to Functions
The calls to the changed functions must be updated. Calls made from SDL cause no problems as the SDL compilers produce the correct code. Only calls made directly from inline C code may have to be updated. The operator list in the file compatibility.warn contains cross-references to the inline C code where the operator is called using an #SDL directive.
Operator calls in C without the #SDL directive, are not listed in compatibility.warn. These calls can only be found via the compiler error list.
For parameters that has changed parameter passing mechanism from pass as value to pass as address you should perform one of the following tasks:
- If the actual parameter is a variable (or something it is possible to take the address of), add a `&', before the variable.
- If the actual parameter is a call to a function, then probably this function has changed its prototype so that it now returns an address. In that case nothing needs to be performed. In other cases proceed to the next possibility.
- If none of the situation above is appropriate, insert a new function local variable of the parameter type, assign the value of the actual parameter to this variable, and insert the address of the variable as actual parameter.
Implementation Hint
The following information is not required for the migration of the system, but can be used to improve the performance of the system.
When updating the operators, it might be worth investigating the available features in the SDL Suite, including extensions for operators, in/out parameters, no parameters, no result, etc.
One not too uncommon situation is when a value is passed as an in parameter, then changed by the operator and returned as result value. In every operator call, the same variable is used as both the actual parameter and the receiver of the result. To improve speed of the application, the operator, could be changed to an operator without result and using in/out parameters.
If you perform a change like this, remember to use the cross-reference tool to find all places where the operator is used.
Step 4: Updating typedefs
Overview
Another area where backward incompatibility problems might be present is when the typedef is changed in an #ADT directive, especially if the assign, equal, or free functions are changed as well. In the second section of the file compatibility.warn all types changing the typedef and at least one of assign, equal, or free functions are listed.
NEWTYPE example C-name:zDZ_example<<SYSTEM mysystem>>#SDTREF(TEXT,file.sdl,3096,9)Pass as Value #ADT(T(B)A(B)E(B)F(B))The example should be interpreted like this:
- The first line contains the name of the newtype in SDL and in C.
- The second line contains an appropriate qualifier that gives information on where in the system the newtype is defined.
- The third line is the SDT reference to the newtype. This can be used in the Organizer's "goto source" feature to locate the SDL source code.
- The fourth line contains either "Pass as Value" or "Pass as Address", depending on the property of the newtype, followed by the interpretation of the #ADT directive.
As the #ADT directive can be used in many different ways, it is impossible to describe a general method how to correct any problems. The type list in the compatibility.warn file indicates what newtypes that have highest probability to cause problems. It is recommended that you go through the listed newtypes and review them given the information in the following sections.
You also have to find and in some cases correct the places where the functions discussed below are called. The compiler error list is the main source of information for this task. Please see Locating Source Code if you have problems locating the corresponding SDL source listed in a C compilation error message.
Assignment Functions
For all types passed as addresses, the differences between the old-style, and the new generic assignment functions are:
- The old functions pass the value of the right-hand side expression as the second parameter, while the new pass the address of the right-hand side expression.
- The old functions returns void, but the generic functions return the first parameter, i.e. the address of variable.
- It is now required that the assignment function must be a function (it cannot be a macro), as the address of the function is stored in the type info node for the newtype.
Example 426 : The Assignment Function
The prototype for an old assign function would be:
void yAss_typename (typename*, typename, int)The prototype for a new assign function should be:
typename* yAss_typename (typename*, typename*, int)The body of the assignment function must be updated for these changes.
If assignment for a type passed as an address is used in inline C code, one of the following tasks must be performed:
- If the expression parameter is a variable, a `&', should be added before the variable.
- If the expression is an SDL operator call, a change is normally not needed, as the operator in the generic function model will return the address of a value, not the value itself (for types passed as address).
- You might want to add (void) before the yAss call to tell the compiler that you want to ignore the result.
For more information please see Generic Assignment Functions.
Equal Functions
For all types passed as addresses, the differences between the old and the new generic equal functions are:
- The old functions pass the values of the two expression, while the new generic equal functions pass the addresses of the expressions.
- It is now required that the equal function must be a function (it cannot be a macro), as the address of the function is stored in the type info node for the newtype.
Example 427 : The Equal Function
The prototype for an old equal function would be:
SDL_Boolean yEq_typename (typename, typename)The prototype for a new equal function should be:
SDL_Boolean yEq_typename (typename*, typename*)The body of the equal function must be updated for these changes.
If equal for a type passed as an address is used in inline C code, perform the same tasks as presented for the assignment function.
For more information please see Generic Equal Functions.
Free Functions
The yFree_typename function is backward compatible. However, it is now required that the equal function must be a function (it cannot be a macro), as the address of the function is stored in the type info node for the newtype.
For more information please see Generic Free Functions.
Default Functions
The yDef_typename macro or function from the non-generic mode is no longer used or generated. Initialization of SDL variables are performed as follows:
- if the variable has an initial value given in the declaration, the variable is assigned this value, using an assignment statement.
- else if the type of the variable has a default value, the variables are assigned this value, using an assignment statement.
- else the variable is set to 0 using memset. If 0 is not an appropriate initial value, the function GenericDefault is called to initialize the variable. Examples of types where 0 is not an appropriate value are structs with components with initial values, Object_identifiers, Strings, general Powersets, Bags and general Arrays.
As yDef functions/macros do not exist in Generic mode, all usage in inline C code must be changed. There are several possibilities. First, decide if assigning a default value is really necessary. If it is necessary, then some of the following principle solutions might be used:
- memset to 0
- GenericDefault(&variable,
(tSDLTypeInfo *)&ySDL_typename)- yAss_typename(variable, expression,
XASS_MR_ASS_NF)- direct C assignment, if possible
Make Functions
The yMake_typename function from the non-generic mode is no longer used or generated. All calls in inline code to yMake functions must be replaced by calls to proper GenericMake functions as described in Generic Make Functions.
yMake functions pass component values as values, while GenericMake functions pass component values as addresses
Operators in Predefined Generators
The operators in predefined generators have got new generic implementations. All the available generic implementations are listed in Generic Function for Operators in Pre-defined Generators. Macros that support the old operators names and translate them to the generic functions are generated. If you get compilation errors in such a call you should compare the call with the macro and the generic function, to see if there are any differences in the parameter passing principle.
Locating Source Code
A typical error message from a C compiler lists a file name, a line number, and a description of the error. To locate the corresponding SDL source code perform the following:
- In a text editor, open the file that is listed in the error message
- Go to the given line number.
- Search upwards for an SDT reference, that is, a C comment starting with:
/*#SDTREF(Copy the SDT reference and paste it into the Goto Source feature in the Organizer. The Organizer will show you where the C code originated from.
http://www.ibm.com/rational |
![]() |
![]() |
![]() |
![]() |