build_sdl_glue.c 13.2 KB
Newer Older
Maxime Perrotin's avatar
Maxime Perrotin committed
1 2 3 4 5 6 7
/* Buildsupport is (c) 2008-2015 European Space Agency
 * contact: maxime.perrotin@esa.int
 * License is LGPL, check LICENSE file */
/* build_sdl_glue.c

  this program generates the code to interface an objectgeode generated application with the assert virtual machine
  It creates vm_if.c, hpredef.h and hpostdef.h
8

Maxime Perrotin's avatar
Maxime Perrotin committed
9 10
  updated 20/04/2009 to disable in case "-onlycv" flag is set

11 12
  update 09/2016 - This code is legacy - ObjectGEODE is discontinued and no
  further support is ever expected. This file is not maintained.
Maxime Perrotin's avatar
Maxime Perrotin committed
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 */

#define ID "$Id: build_sdl_glue.c 414 2009-12-04 16:21:52Z maxime1008 $"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>

#include "my_types.h"
#include "practical_functions.h"
 static FILE *vm_if, *hpredef, *hpostdef;

#define PARAM_TYPE(p) (p->value->type)
#define PARAM_NAME(p) (p->value->name)


/* create_gluefiles()
**
** Open/Creates glue files (vm_if, hpredef, hpostdef)
** Returns -1 if problem opening one of the files.
*/
int create_gluefiles(FV * fv)
{
    char *path = NULL;
    if (NULL != fv->system_ast->context->output)
39 40
        build_string(&path, fv->system_ast->context->output,
                      strlen(fv->system_ast->context->output));
Maxime Perrotin's avatar
Maxime Perrotin committed
41 42 43 44 45 46
    build_string(&path, fv->name, strlen(fv->name));
    create_file(path, "vm_if.c", &vm_if);
    create_file(path, "hpredef.h", &hpredef);
    create_file(path, "hpostdef.h", &hpostdef);
    free(path);
    if (NULL == vm_if || NULL == hpredef || NULL == hpostdef)
47
        return -1;
Maxime Perrotin's avatar
Maxime Perrotin committed
48 49

    else
50
        return 0;
Maxime Perrotin's avatar
Maxime Perrotin committed
51 52 53 54 55 56 57
}

void close_gluefiles()
{
    close_file(&vm_if);
    close_file(&hpredef);
    close_file(&hpostdef);
58 59 60
}

void vm_if_preamble(FV * fv)
Maxime Perrotin's avatar
Maxime Perrotin committed
61 62
{
    if (NULL == vm_if)
63
        return;
Maxime Perrotin's avatar
Maxime Perrotin committed
64
    fprintf(vm_if,
65 66
              "#include \"g2_appli.h\"\n#include \"g2_com.h\"\n#include \"s_%s.h\"\n",
              fv->name);
Maxime Perrotin's avatar
Maxime Perrotin committed
67 68 69 70 71 72
    fprintf(vm_if, "#include \"OG_ASN1_Types.h\"\n\n\n");
}

void add_PI_to_vm_if(Interface * i)
{
    if (NULL == vm_if)
73
        return;
Maxime Perrotin's avatar
Maxime Perrotin committed
74 75 76 77 78

    /* Create glue for the PI */

    // a. If this PI has a parameter, declare an external global variable of type SIGNAL_signalname * for the data. Else of type GX_SIG_P
    if (NULL != i->in) {
79 80
        fprintf(vm_if, "extern SIGNAL_%s *p_%s;\n\n", (i->name),
                 (i->name));
Maxime Perrotin's avatar
Maxime Perrotin committed
81 82 83
    }

    else {
84
        fprintf(vm_if, "extern GX_SIG_P p_%s;\n\n", (i->name));
Maxime Perrotin's avatar
Maxime Perrotin committed
85 86 87 88
    }

    // b. function name and preamble (declaration of g2x_self used in OG macros)
    fprintf(vm_if, "void %s_%s(%s) {\n\n\tint g2x_self=0;\n\n",
89 90 91
             (i->parent_fv->name),
             (i->name),
             (NULL != i->in) ? "char *param, int length" : "" );
Maxime Perrotin's avatar
Maxime Perrotin committed
92 93 94

    // c. if the PI has NO PARAMETER, only make a simple output of the signal corresponding to the PI. Use G2S_OUTPUT and not SDL_OUTPUT (which makes malloc)
    if (NULL == i->in) {
95 96 97
        fprintf(vm_if, "\t// Send the message to the SDL model\n");
        fprintf(vm_if, "\tG2S_OUTPUT(sig_%s,(G2P_FINDPID(%s)),(GX_SIG_P)p_%s);\n\n", (i->name), (i->parent_fv->name),   // SDL_DEST
                 (i->name) );
Maxime Perrotin's avatar
Maxime Perrotin committed
98
    }
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123

        // d. if the PI has a parameter
        // generate 3 lines:
        // G2M_INIT_REC (p_signalname, SIGNAL_signalname);
        // DECODE_paramtype(...): call to Thanassis macros
        // G2S_OUTPUT(sig_signalname,(G2P_FINDPID(nodename)),(GX_SIG_P)p_signalname);
        else {
        fprintf(vm_if,
                 "\t//1. Clean the global variable before putting the decoded data\n");
        fprintf(vm_if, "\tG2M_INIT_REC (p_%s, SIGNAL_%s);\n\n",
                 (i->name), (i->name) );

        // call to Thanassis Decoding macro (in the future replace by a loop: there can be several params)
        fprintf(vm_if,
                "\t//2. Decode the ASN.1 binary stream and put it in the SDL variable\n");
        fprintf(vm_if, "\tDECODE_%s_%s(param, length, &p_%s->sg1_%s)\n\n",
                 BINARY_ENCODING(i->in->value),
                 /*(PARAM_ENCODING(i->in)),*/
                 (PARAM_TYPE(i->in)),
                 (i->name), 
                 (PARAM_TYPE(i->in)) 
        );
        fprintf(vm_if, "\t//3. Send the message to the SDL model\n");
        fprintf(vm_if, "\tG2S_OUTPUT(sig_%s,(G2P_FINDPID(%s)),(GX_SIG_P)p_%s);\n\n", (i->name), (i->parent_fv->name),   // SDL_DEST
                 (i->name) );
Maxime Perrotin's avatar
Maxime Perrotin committed
124 125 126 127 128 129 130 131 132
    }

    // e. function postamble (call to sdl_loop() and return)
    fprintf(vm_if, "\tsdl_loop_%s();\n}\n\n", (i->parent_fv->name));
}

void add_PI_to_hpostdef(Interface * i)
{
    if (NULL == hpostdef)
133
        return;
Maxime Perrotin's avatar
Maxime Perrotin committed
134 135 136 137 138 139

    /* Declaration for PI with parameters: global variable + undef of the SDL_OUTPUT not used anymore */
    fprintf(hpostdef, "// PROVIDED INTERFACE %s\n\n", i->name);

    // a. global variables if there is a parameter: use the type SIGNAL_signalname
    if (NULL != i->in) {
140 141 142
        fprintf(hpostdef, "SIGNAL_%s %s;\nSIGNAL_%s *p_%s=&%s;\n\n",
                 (i->name),
                 (i->name), (i->name), (i->name), (i->name) );
Maxime Perrotin's avatar
Maxime Perrotin committed
143 144 145
    }
    // b. global variables if there is no parameter: use the types GX_SIG_T and GX_SIG_P
    else {
146 147
        fprintf(hpostdef, "GX_SIG_T %s;\nGX_SIG_P p_%s = &%s;\n\n",
                 (i->name), (i->name), (i->name) );
Maxime Perrotin's avatar
Maxime Perrotin committed
148 149 150 151 152 153 154
    }
    fprintf(hpostdef, "#undef SDL_OUTPUT_%s\n\n", (i->name));
}

void hpredef_preamble()
{
    if (NULL == hpredef)
155
        return;
Maxime Perrotin's avatar
Maxime Perrotin committed
156
    fprintf(hpredef,
157
              "/* External declaration of VM callback function for each REQUIRED INTERFACE */\n\n");
Maxime Perrotin's avatar
Maxime Perrotin committed
158 159 160 161 162 163 164 165 166
}

void add_RI_to_hpredef(Interface * i)
{
    Parameter_list * v_local;
    int count_in_param = 0;
    int count_out_param = 0;
    int i_in = 0, i_out = 0;
    if (NULL == hpredef)
167
        return;
Maxime Perrotin's avatar
Maxime Perrotin committed
168 169 170 171

    /* Count IN and OUT param */
    v_local = i->in;
    while (v_local != NULL) {
172 173
        v_local = v_local->next;
        count_in_param++;
Maxime Perrotin's avatar
Maxime Perrotin committed
174 175 176
    }
    v_local = i->out;
    while (v_local != NULL) {
177 178
        v_local = v_local->next;
        count_out_param++;
Maxime Perrotin's avatar
Maxime Perrotin committed
179 180 181 182
    }

    /* Preamble (function declaration) */
    fprintf(hpredef, "extern void vm_%s_%s(",
183
            (i->parent_fv->name), (i->name));
Maxime Perrotin's avatar
Maxime Perrotin committed
184 185 186

    /* For each IN param, add "char *, int" to the declaration */
    while (i_in < count_in_param) {
187 188
        fprintf(hpredef, "%schar *, int", (i_in > 0) ? ", " : "");
        i_in++;
Maxime Perrotin's avatar
Maxime Perrotin committed
189 190 191 192
    }

    /* For each OUT param, add "char *, int*" to the declaration */
    while (i_out < count_out_param) {
193 194 195
        fprintf(hpredef, "%schar *, int *",
                 (i_out > 0 || count_in_param > 0) ? ", " : "");
        i_out++;
Maxime Perrotin's avatar
Maxime Perrotin committed
196 197 198 199 200 201 202 203 204
    }

    /* Postamble */
    fprintf(hpredef, ");\n");
}

void hpostdef_preamble()
{
    if (NULL == hpostdef)
205
        return;
Maxime Perrotin's avatar
Maxime Perrotin committed
206 207 208 209 210 211
    fprintf(hpostdef, "#include \"OG_ASN1_Types.h\"\n\n\n");
}

void hpostdef_postamble()
{
    if (NULL == hpostdef)
212
        return;
Maxime Perrotin's avatar
Maxime Perrotin committed
213
    fprintf(hpostdef,
214
              "/* ** Redefinition of the macro G2S_RELEASE that makes a free of the current message */\n");
Maxime Perrotin's avatar
Maxime Perrotin committed
215 216
    fprintf(hpostdef, "#undef G2S_RELEASE\n\n#define G2S_RELEASE()\n\n");
    fprintf(hpostdef,
217
              "/* ** Redefinition of the macro G2I_CRE_START (call of malloc to send the START message at system startup) */\n");
Maxime Perrotin's avatar
Maxime Perrotin committed
218
    fprintf(hpostdef,
219
             "#undef G2I_CRE_START\n\n#define G2I_CRE_START(proc) \\\n{GX_SIG_T sig; \\\nsig.sg_signo=sig_START;\\\nsig.sg_receiver=new_pid;\\\nCAT(PROCESS_, proc)(&sig); }");
Maxime Perrotin's avatar
Maxime Perrotin committed
220 221 222 223 224 225 226 227 228
}

void add_Immediate_RI_to_hpostdef(Interface * i)
{
    Parameter_list * v_local;
    int count_in_param = 0;
    int count_out_param = 0;
    int j;
    if (NULL == hpostdef)
229
        return;
Maxime Perrotin's avatar
Maxime Perrotin committed
230 231
    fprintf(hpostdef, "// IMMEDIATE REQUIRED INTERFACE %s\n\n", i->name);
    
232 233 234
        /* 1) for all parameters (in/out) declare encoding/decoding buffers: DEFINE_type(IN/OUT_RIname_varname) */
        // First IN param
        v_local = i->in;
Maxime Perrotin's avatar
Maxime Perrotin committed
235
    while (NULL != v_local) {
236 237 238
        fprintf(hpostdef, "DEFINE_%s(IN_%s_%s)\n\n",
                  (PARAM_TYPE(v_local)),
                  (i->name), (PARAM_NAME(v_local)) );
Maxime Perrotin's avatar
Maxime Perrotin committed
239

240 241 242
        /* In the meantime, also count the number of params */
        count_in_param++;
        v_local = v_local->next;
Maxime Perrotin's avatar
Maxime Perrotin committed
243 244 245 246 247
    }

    // Then OUT param
    v_local = i->out;
    while (NULL != v_local) {
248 249 250
        fprintf(hpostdef, "DEFINE_%s(OUT_%s_%s)\n\n",
                  (PARAM_TYPE(v_local)),
                  (i->name), (PARAM_NAME(v_local)) );
Maxime Perrotin's avatar
Maxime Perrotin committed
251

252 253 254
        /* In the meantime, also count the number of params */
        count_out_param++;
        v_local = v_local->next;
Maxime Perrotin's avatar
Maxime Perrotin committed
255 256 257 258 259
    }

    /* 2) Macro declaration:  "#define RI_NAME(...)" */
    fprintf(hpostdef, "#define %s(", (i->name));
    for (j = 0; j < count_in_param; j++) {
260 261 262
        if (j > 0)
            fprintf(hpostdef, ", ");
        fprintf(hpostdef, "param_in_%d", j + 1);
Maxime Perrotin's avatar
Maxime Perrotin committed
263 264
    }
    if (count_in_param > 0 && count_out_param > 0)
265
        fprintf(hpostdef, ", ");
Maxime Perrotin's avatar
Maxime Perrotin committed
266
    for (j = 0; j < count_out_param; j++) {
267 268 269
        if (j > 0)
            fprintf(hpostdef, ", ");
        fprintf(hpostdef, "param_out_%d", j + 1);
Maxime Perrotin's avatar
Maxime Perrotin committed
270 271 272 273 274 275 276 277
    }
    fprintf(hpostdef, ")\\\n{ ");

    /* 3) Inside the macro: add a call to ENCODE_SYNC macros for each IN param */
    /* Note: the SYNC postfix to ENCODE had to be added because OG treats differently the parameters of SIGNAL and CALL actions */
    v_local = i->in;
    j = 1;
    while (NULL != v_local) {
278 279 280 281 282 283
        fprintf(hpostdef, "ENCODE_SYNC_%s_%s(IN_%s_%s,param_in_%d)\\\n",
                   BINARY_ENCODING(v_local->value),
                   (PARAM_TYPE(v_local)),
                   (i->name), (PARAM_NAME(v_local)), j );
        j++;
        v_local = v_local->next;
Maxime Perrotin's avatar
Maxime Perrotin committed
284
    }
285 286 287

        /* 4a) Inside the macro: add the call to the VM interface (preamble) */
        fprintf(hpostdef, "vm_%s_%s(", (i->parent_fv->name), (i->name) );
Maxime Perrotin's avatar
Maxime Perrotin committed
288 289 290 291 292

    /* 4b) Add each IN param (IN_RIname_varname, IN_RIname_varname_len) */
    v_local = i->in;
    j = 0;
    while (NULL != v_local) {
293 294 295 296 297 298 299
        fprintf(hpostdef, "%sIN_%s_%s,IN_%s_%s_len",
                  (j > 0) ? ", " : "",
                  (i->name),
                  (PARAM_NAME(v_local)),
                  (i->name), (PARAM_NAME(v_local)) );
        j++;
        v_local = v_local->next;
Maxime Perrotin's avatar
Maxime Perrotin committed
300 301
    }
    if (count_in_param > 0 && count_out_param > 0)
302
        fprintf(hpostdef, ", ");
Maxime Perrotin's avatar
Maxime Perrotin committed
303 304 305 306 307

    /* 4c) Add each OUT param (OUT_RIname_varname, &OUT_RIname_varname_len) */
    v_local = i->out;
    j = 0;
    while (NULL != v_local) {
308 309 310 311 312 313 314
        fprintf(hpostdef, "%sOUT_%s_%s,&OUT_%s_%s_len",
                  (j > 0) ? ", " : "",
                  (i->name),
                  (PARAM_NAME(v_local)),
                  (i->name), (PARAM_NAME(v_local)) );
        j++;
        v_local = v_local->next;
Maxime Perrotin's avatar
Maxime Perrotin committed
315 316 317 318 319
    }
    fprintf(hpostdef, ");\\\n");

    /* 5) Inside the macro: add DECODE for each OUT param */
    if (count_out_param > 0) {
320 321 322 323 324 325 326 327 328 329 330 331
        v_local = i->out;
        j = 1;
        while (NULL != v_local) {
            fprintf(hpostdef,
                      "DECODE_%s_%s(OUT_%s_%s,OUT_%s_%s_len,param_out_%d)\\\n",
                      BINARY_ENCODING(v_local->value),
                      (PARAM_TYPE(v_local)),
                      (i->name), (PARAM_NAME(v_local)), (i->name),
                      (PARAM_NAME(v_local)), j );
            j++;
            v_local = v_local->next;
        }
Maxime Perrotin's avatar
Maxime Perrotin committed
332 333 334 335 336 337 338
    }
    fprintf(hpostdef, "}\n\n");
}

void add_Deffered_RI_to_hpostdef(Interface * i)
{
    if (NULL == hpostdef)
339
        return;
Maxime Perrotin's avatar
Maxime Perrotin committed
340 341 342 343
    fprintf(hpostdef, "/* DEFFERED (ASYNCHRONOUS) REQUIRED INTERFACE %s */\n\n", i->name);

    // 1). call to Thanassis macro to declare encoding buffers:
    if (NULL != i->in) {
344 345
        fprintf(hpostdef, "DEFINE_%s(%s_sg1)\n\n",
                 (PARAM_TYPE(i->in)), (i->name) );
Maxime Perrotin's avatar
Maxime Perrotin committed
346 347 348 349
    }
    // 2) redefine SDL_OUTPUT
    fprintf(hpostdef, "#undef SDL_OUTPUT_%s\n\n", (i->name));
    if (NULL != i->in) {
350 351 352 353 354 355 356
        fprintf(hpostdef, "#define SDL_OUTPUT_%s(pid, param1)\\\n{ ",
                 (i->name));
        fprintf(hpostdef, "ENCODE_ASYNC_%s_%s(%s_sg1,param1)\\\n",
                  BINARY_ENCODING(i->in->value), /*(PARAM_ENCODING(i->in)),*/
                  (PARAM_TYPE(i->in)), (i->name));
        fprintf(hpostdef, "vm_async_%s_%s(%s_sg1,%s_sg1_len);}\n\n",
                  (i->parent_fv->name), (i->name), (i->name), (i->name));
Maxime Perrotin's avatar
Maxime Perrotin committed
357 358 359
    }

    else {
360 361 362
        fprintf(hpostdef,
                 "#define SDL_OUTPUT_%s(pid)\\\n{vm_async_%s_%s();}\n\n",
                 (i->name), (i->parent_fv->name), (i->name) );
Maxime Perrotin's avatar
Maxime Perrotin committed
363 364 365 366 367 368
    }
}

int Create_OG_files(FV * fv)
{
    if (create_gluefiles(fv) != -1) {
369 370 371
        vm_if_preamble(fv);
        hpredef_preamble();
        hpostdef_preamble();
Maxime Perrotin's avatar
Maxime Perrotin committed
372
    } else {
373 374
        printf("File creation error (Build_SDL_Glue backend)\n\n");
        return -1;
Maxime Perrotin's avatar
Maxime Perrotin committed
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
    }
    return 0;
}

void End_SDL_Glue_Backend()
{
    hpostdef_postamble();
    close_gluefiles();
} 

/* Function to process one interface of the FV */
void GLUE_OG_Interface(Interface * i)
{

    switch (i->direction) {
    case PI:
391 392 393
        add_PI_to_vm_if(i);
        add_PI_to_hpostdef(i);
        break;
Maxime Perrotin's avatar
Maxime Perrotin committed
394
    case RI:
395 396 397 398 399 400 401 402 403 404
        switch (i->synchronism) {
        case asynch:
            add_Deffered_RI_to_hpostdef(i);
            break;
        case synch:
            add_Immediate_RI_to_hpostdef(i);
            break;
        default : break;
        }
        break;
Maxime Perrotin's avatar
Maxime Perrotin committed
405
    default:
406
        break;
Maxime Perrotin's avatar
Maxime Perrotin committed
407 408 409 410 411 412 413 414
    }
}


// External interface (the one and unique)
void GLUE_OG_Backend(FV * fv)
{
    if (fv->system_ast->context->onlycv)
415
        return;
Maxime Perrotin's avatar
Maxime Perrotin committed
416
    if (sdl == fv->language) {
417 418 419 420 421
        Create_OG_files(fv);
        FOREACH(i, Interface, fv->interfaces, {
            GLUE_OG_Interface(i);
        })
        End_SDL_Glue_Backend();
Maxime Perrotin's avatar
Maxime Perrotin committed
422 423
    }
}