ec2c, poc - ansi C code generator

NAME

ec2c, poc - ansi C code generator

SYNOPSIS

ec2c file.ec [options]

poc file.oc [options]

DESCRIPTION

These tools are Ansi-C code generators. They are presented together, since they share the same conventions for the generated user interface. Otherwise, they are completely separated tools, working in different formats, and performing different tasks:

TARGET CODE

The code generated by those compilers consists essentially in a procedure implementing a step of the reactive program described in the source file. In order to run the reactive program, the user must write a main loop around the "step" procedure.

In the following, we precise what it is automatically generated, and what the user has to write. Let us call foo.oc (resp. foo.ec) the source file, FOO the oc module (resp. the ec node) defined in the source file, foo.c and foo.h the generated files, and loop.c the main program written by the user.

Execution context

The generated code allows multiple allocations of a reactive module. The memory needed for an instance of the reactive module is defined in foo.c, and declared in foo.h:

struct FOO_ctx;

The user does not have to know what this structure is made of, he is only allowed to manipulate pointers. The user can get a new context using a procedure declared in foo.h:

struct FOO_ctx * FOO_new_ctx(void* client_data);

The user can associate an extra information to a new execution context using the client_data argument. This information is necessary if the user wants to run several instances of a same reactive module concurrently.

Step procedure

The procedure implementing a step of the reactive module is declared in foo.h:

void FOO_step(struct FOO_ctx * ctx);

This procedure is called with an execution context previously created by a call to FOO_new_ctx. This step procedure has no input/output parameters, since communication between the main loop and the reactive module is made via input/output procedures. More precisely, the user must call input procedures to set the input values before he calls the step procedure. The step procedure calls output procedures to send its outputs to the environment.

Inputs and outputs

Communications between foo.c and loop.c are made via input and output procedures. The input procedures are defined in foo.c and used in the main loop, the output procedures are defined by the user (in loop.c for instance), and used in foo.c.

For each input IN, of type TYP, foo.c contains the definition of the procedure:

void FOO_I_IN(struct FOO_ctx* context, TYP value);

Note that if IN is a pure signal (poc only), the value parameter is omitted:

void FOO_I_IN(struct FOO_ctx* context);

For each output OUT, of type TYP, the user must define a procedure:

void FOO_O_OUT(void* client_data, TYP value);

Note that if OUT is a pure signal (poc only), the value parameter is omitted:

void FOO_O_OUT(void* client_data);

Output procedures are called within FOO_step(FOO_ctx* ctx), using the client data which has been associated with ctx when it was created.

Example

Here is a simple example of a main loop using a reactive module (whose name is sum) with two real inputs (x and y) and a single real output s; note that the client data is not necessary, since the loop uses only one instance of the reactive module:

 #include <stdlib.h>
 #include "sum.h"

 void sum_O_s(void* cdata, float _V){
    printf("result: %f\n", _V);
 }

 main(){
    _float x;
    _float y;
    struct sum_ctx* prg = sum_new_ctx(NULL);
 
    while(1){
       printf("(float) x ?\n");
       scanf("%f", &x);
       sum_I_x(prg, x);
       printf("(float) y ?\n");
       scanf("%f", &y);
       sum_I_y(prg, y);
       sum_step(prg);
    }
 }

External objects

Each external object declared in the source file is supposed to be implemented by the user. Some information is necessary for the compilation of the c generated code, other is necessary only for linking.

Standard main loop

When called with the -loop option, poc (resp. ec2c) produces an extra c-file FOO_loop.c. This code contains a main procedure implementing a loop which reads inputs on stdin and write outputs to stdout. If foo.c does not need external object, it is a simple way to obtain executable code. For instance:

poc sum.oc -loop
gcc sum.c sum_loop.c -o sum

produces an interactive program sum, which allows the user to test his code.

If external objects are needed, the user must write all the necessary code plus two procedures for each external type TYP:

Pragmas

In order to allow automatic manipulation of the code generated, the compiler generates special comments (pragmas) in the header file. Pragmas are single line Ansi C comments, begining with the string poc:. Ther is a pragma which gives the name of the module, and a pragma for each input and each output, giving its type and its name. Here is an example of pragma section:

//poc:MODULE sum 
//poc:IN _float x
//poc:IN _float y
//poc:OUT _float s

OPTIONS

-v

set the verbose mode.

-o name

define the prefix for the target files. The default is to use the name of the module (i.e. node), which is not necessarily the name of the source file.

-loop

generate an extra main file called name_loop.c. This main is sufficient to build a stand-alone application if the reactive module does not need any external definitions.

 ec2c, poc - ansi C code generator