User Guide

Getting Started

Installing UML Generators

PENDING

Model design

Template

Your UML model has to fit a template to be well interpreted by the generator. The chosen template is common to C generator and reverser in order to be consistent.

The default template is structured on several sub-packages and each of them plays a role. The three most important are "Source Artifacts", "Types" and "Libs":

EAnnotations

EAnnotations bring additional information needed by the generator. They are always related to an UML element. Two distinct EAnnotations are used :

Detail entry key Expected value On UML element See
PROJECT_CHARSET The charset to use Model Project charset
IFNDEF Conditional inclusion Classifier Conditional inclusion
C_FILENAME Relative path to the C file Classifier Module creation, Module and header creation
H_FILENAME Relative path to the H file Classifier

Header creation, Module and header creation

STD_LIBRARY true or false Usage

System-defined file inclusions

REGISTER true or false Property __
VOLATILE true or false Property __

Project charset

Before making generation, the project charset must be specified to avoid encoding issues. This step will have to be done at the highest level, directly under the uml:Model element of your model.

This step is not mandatory and can be skipped. In this case, the UTF-8 encoding will be applied while generating.

Element visibility

The visibility of the elements is used to define the target of the generated block.

Module creation

In the Source Artifacts package:

Header creation

In the Source Artifacts package:

Module and header both creation

In the Source Artifacts package:

Inclusions

UML Usage elements are used to manage inclusions. Create a UML Usage between the source (client) module and the target (supplier) UML Interface.

Generated code in Engine.h:
#include "Sensor.h"

To make the inclusion of a system-defined file (i.e. stdio), you have to add a "STD_LIBRARY" EAnnotation (see EAnnotations section) with "true" as value, on the UML Usage

Generated code:
#include <stdio.h>

Macros

Conditional one

From a UML Classifier ( UML Class or UML Interface), you can specify a conditional inclusion.

For that, add a "IFNDEF" EAnnotation (see EAnnotations section) with the macro constant label you want (i.e. "__ENGINE_H__") as value, on the UML Classifier.

Only the header file will be impacted during the generation. It will look like that:

#ifndef __ENGINE_H__
#define __ENGINE_H__
[...]
#endif

Object-like one

On the Types package of the model, create a UML Primitive Type named "Macro" if not already existing.

On a given UML Class, in a Source Artifacts package, add a UML Property and:

Generated code:
#define BUFFER_SIZE 1024

Function-like one

Same thing as the Object-like_one section. The name will be the signature of the function (i.e. "MAX(a, b)") and the value will be a statement ("((a < b) ? b : a)").

Generated code:
MAX(a, b) ((a < b) ? b : a)

Variable declaration

On a UML Class, create a UML Property and set the name, type and visibility of your variable.

If your variable is private, you can set isStatic to true to obtain a static variable (static will be added during generation).

Set isReadOnly to true to create a constant (const will be added during generation)

When the property visibility is public, the variable declaration will be generated in the header file while the definition part will be located in the C file. If it is private, the variable declaration and definition will be both on the module file.

To define the variable as volatile or register, respectively add a "VOLATILE" or "REGISTER" EAnnotation (see EAnnotations section).

To initialize the variable, set the default value with a UML OpaqueExpression or UML Literal String and set the value you want on it.

Generated code:

In the header file:
extern const char* address;

In the module file:
const char* address = "0x456FEA";

For multi-dimensional variables, the dimension(s) is directly defined in the name of the ''UML Property" (i.e. "address_array[3]" or "record_matrix[MAX_ROW][MAX_COL]").

Type definition

A typedef declaration lets you define your own identifiers that can be used in place of type specifiers such as int, float, double and so on.

You can make this definition creating a UML DataType and setting the name you want to express (i.e. "LENGTH"). Then, you have to set the redefined classifier feature with the type you want to redefine (i.e. UML Primitive Type int).

Generated code:
typedef int LENGTH

To redefine a pointer type, you have to reference your own type as redefined classifier (i.e. UML DataType int*)

Generated code:
typedef int* PTR_LENGTH

To define a multi-dimensional array type, you have to set, on the UML DataType, the named expression with a UML String Expression in order to specify the dimension(s). The value of the dimension must be set in the symbol feature, with brackets.

To define a function pointer, you have to add, in the UML DataType, through the ownedOperation feature, a UML Operation.

For example, here is the generated code for a function pointer type named "TYPES_COMMUNS__T_POINTER_FCT" which points to an operation with returns a type (output parameter) named "TYPES_COMMUNS__T_STATUS":
typedef TYPES_COMMUNS__T_STATUS (*TYPES_COMMUNS__T_POINTER_FCT)();

Structures

To define a structure, add a UML DataType, in your UML Class, with a name (i.e. "person") and a visibility. Then, add on it a UML Property with a name and type (i.e. "age") for each field of the structure.

Generated code:
struct person
{

char forename[20];
char surname[20];
float age;
int childcount;

};

To declare a structure, add a UML Property in your UML Class with a name and setting the type to the defined structure ( UML DataType).

For example, here is the generated code for 3 person declared structures as john, ed and paul:
struct person
{

char forename[20];
char surname[20];
float age;
int childcount;

} john, ed, paul;

To define a shorthand structure, create a new UML DataType with a name (i.e. "PEOPLE") and reference your structure as redefined classifier (i.e. UML DataType person).

For example:
typedef struct person
{

char forename[20];
char surname[20];
float age;
int childcount;

} PEOPLE;

Enumerations

To define an enumeration, add a UML Enumeration, in your UML Class, with a name (i.e. "week") and a visibility. The content of the enumeration is specified with a set of named UML Enumeration Literal. To specify a default value to a literal, set the specification feature on the literal with a new OpaqueExpression or LiteralString and set the value on it.

Example:
enum week
{

Monday = 0,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday

};

To declare an enumeration, add a UML Property in your UML Class with a name and setting the type to the defined enumeration ( UML Enumeration).

For example, here is the generated code for 2 week declared enumeration as week30 and week31:
enum week
{

Monday = 0,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday

} week30, week31;

To define a shorthand enumeration, create a new UML Enumeration' with a name (i.e. "WEEK") and reference your enumeration as ''redefined classifier (i.e. UML Enumeration week).

For example:
typedef enum week
{

Monday = 0,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday

} WEEK;

Functions

To declare a function, create a UML Operation in your UML Class and:

Generated code example:
static BOOL checkValues(const INT32* valueA, const INT32* valueB);

To define a function, a UML OpaqueBehavior has to be created with the same name and parameters as the previous declaration, in the same UML Class. Its body feature must be set with your code implementation. At last, its specification feature must reference the previous declaration ( UML Operation).

Example of generated code:
// function declaration
static BOOL checkValues(const INT32* valueA, const INT32* valueB);

// function definition
static BOOL checkValues(const INT32* valueA, const INT32* valueB)
{

if (*valueA >=0 && *valueA < 256)
{
if (*valueB >=0 && *valueB < 256)
{
return TRUE;
}
}
return FALSE;

}

Comments

Comments can be added for every UML NamedElement objects and will be injected into the generated code.

To add a comment, you have to create a " http://www.eclipse.org/umlgen/c/documentation" EAnnotation, under the UML element to document, containing a detail entry where the key is "documentation" and the value is set to your comment content. The content must be raw comments, without any comment formatting characters (slash or star).

Generated code example:
/*
* This buffer will store information on 1024 bytes.
*/
#define BUFFER_SIZE 1024

For that, you must create a " http://www.eclipse.org/umlgen/annotation/c" EAnnotation with different detail entry keys, according to the context: "C_INLINE_COMMENT_AFTER_DECLARATION", "C_INLINE_COMMENT_BEFORE_DECLARATION", "H_INLINE_COMMENT_AFTER_DECLARATION", "H_INLINE_COMMENT_BEFORE_DECLARATION".

Generate C code

To generate C code, your UML model must be compliant with the template defined for this purpose (see Template organization). The generator will look for the source package ('Source Artefacts' by default) and will focus on the classifiers contained inside.