sync/gen_statemachine.ysl2
author Edouard Tisserant <edouard@pep-project.org>
Fri, 07 Oct 2016 13:55:23 +0200
changeset 1256 8bc2e3636021
parent 1205 73464cbee361
child 1264 7e69c59a659b
permissions -rw-r--r--
KEYSYNC: adapted to new update_identity behaviour + fixed some memory leak.
vb@577
     1
// generate state machine code
vb@577
     2
vb@577
     3
// Copyleft (c) 2016, p≡p foundation
vb@577
     4
vb@577
     5
// Written by Volker Birk
vb@577
     6
vb@577
     7
include yslt.yml2
vb@577
     8
vb@577
     9
tstylesheet {
vb@623
    10
    include ./functions.ysl2
Edouard@605
    11
vb@811
    12
    template "/protocol" {
vb@811
    13
        document "../src/Makefile.protocols", "text"
vb@811
    14
            apply "fsm", 0, mode="make";
vb@811
    15
        apply "fsm", 0, mode=gen;
vb@811
    16
    }
vb@811
    17
vb@811
    18
    template "fsm", mode=make
vb@811
    19
    ||
vb@811
    20
    «@filename»_fsm.c: ../sync/devicegroup.fsm
vb@811
    21
    \tmake -C ../«@filename»
vb@811
    22
    ||
vb@811
    23
vb@811
    24
    template "fsm", mode=gen {
vb@807
    25
        document "../src/{@filename}_fsm.h", "text" {
vb@609
    26
        ||
vb@609
    27
        #pragma once
vb@577
    28
vb@609
    29
        // state machine for «@name»
vb@577
    30
vb@1099
    31
        #include "message_api.h"
vb@654
    32
        
vb@654
    33
        #ifdef __cplusplus
vb@654
    34
        extern "C" {
vb@654
    35
        #endif
vb@608
    36
vb@609
    37
        // types
Edouard@605
    38
vb@609
    39
        typedef pEp_identity * Identity;
vb@939
    40
        typedef stringlist_t * Stringlist;
vb@939
    41
        typedef union _param { Identity partner; stringlist_t *keylist; } param_t;
vb@583
    42
vb@609
    43
        // error values
vb@577
    44
vb@609
    45
        typedef enum _fsm_error {
vb@964
    46
            // these error values are corresponding to
vb@964
    47
            // PEP_SYNC_STATEMACHINE_ERROR - value
vb@743
    48
            invalid_state = -2,
vb@959
    49
            invalid_event = -3,
vb@959
    50
            invalid_condition = -4,
vb@964
    51
            invalid_action = -5,
vb@964
    52
vb@964
    53
            // out of memory condition
vb@964
    54
            invalid_out_of_memory = -128
vb@609
    55
        } fsm_error;
vb@583
    56
vb@951
    57
        // conditions
vb@951
    58
vb@959
    59
        `` for "func:distinctName(condition)" | int «@name»(PEP_SESSION session`apply "parm", 0`);
vb@951
    60
vb@609
    61
        // states
vb@578
    62
vb@609
    63
        typedef enum _«@name»_state {
vb@1043
    64
            // error values also in this namespace
vb@1043
    65
            «@name»_state_invalid_state = (int) invalid_state,
vb@1043
    66
            «@name»_state_invalid_event = (int) invalid_event,
vb@1043
    67
            «@name»_state_invalid_condition = (int) invalid_condition,
vb@1043
    68
            «@name»_state_invalid_action = (int) invalid_action,
vb@1043
    69
            «@name»_state_invalid_out_of_memory = (int) invalid_out_of_memory,
vb@1043
    70
vb@951
    71
            «@name»_state_NONE = 0,
vb@623
    72
        `` for "func:distinctName(state)" |> «@name»`if "position()!=last()" > , `
vb@609
    73
        } «@name»_state;
vb@583
    74
vb@609
    75
        // events
vb@578
    76
vb@609
    77
        typedef enum _«@name»_event {
vb@951
    78
            «@name»_event_NONE = 0,
vb@711
    79
        ||
vb@711
    80
        for "func:distinctName(state/event[not(not(/protocol/fsm/tag/@name=@name))])" {
vb@711
    81
            const "name", "@name";
vb@711
    82
            |> «$name» = «/protocol/fsm/tag[@name=$name]/@id»,
vb@711
    83
        }
vb@711
    84
        for "func:distinctName(state/event[not(/protocol/fsm/tag/@name=@name)])"
vb@711
    85
            |> «@name»`if "position()!=last()" > , `
vb@711
    86
        ||
vb@609
    87
        } «@name»_event;
vb@583
    88
vb@609
    89
        // actions
vb@582
    90
vb@690
    91
        `` const "name", "@name"
vb@939
    92
        `` for "func:distinctName(//action)" | PEP_STATUS «@name»(PEP_SESSION session, «$name»_state state, Identity partner, void *extra);
Edouard@605
    93
edouard@1205
    94
        // event injector
edouard@1205
    95
edouard@1205
    96
        PEP_STATUS inject_DeviceState_event(
edouard@1205
    97
            PEP_SESSION session, 
edouard@1205
    98
            DeviceState_event event,
edouard@1205
    99
            Identity partner,
edouard@1205
   100
            void *extra);
edouard@1205
   101
vb@951
   102
        // message receiver
vb@951
   103
        
edouard@1165
   104
        PEP_STATUS receive_DeviceState_msg(
edouard@1165
   105
                PEP_SESSION session, 
edouard@1165
   106
                message *src, 
edouard@1165
   107
                PEP_rating rating, 
edouard@1165
   108
                stringlist_t *keylist
edouard@1165
   109
            );
vb@951
   110
vb@626
   111
        // state machine
vb@626
   112
vb@626
   113
        «@name»_state fsm_«@name»(
vb@627
   114
                PEP_SESSION session,
vb@626
   115
                «@name»_state state,
vb@626
   116
                «@name»_event event,
vb@939
   117
                Identity partner,
vb@951
   118
                void *extra
vb@626
   119
            );
vb@626
   120
vb@609
   121
        // driver
Edouard@605
   122
vb@782
   123
        DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
vb@690
   124
                PEP_SESSION session,
vb@690
   125
                «@name»_event event,
vb@690
   126
                Identity partner,
vb@951
   127
                void *extra
vb@690
   128
            );
Edouard@605
   129
vb@654
   130
        #ifdef __cplusplus
vb@654
   131
        }
vb@654
   132
        #endif
vb@654
   133
vb@609
   134
        ||
vb@711
   135
        }
vb@807
   136
        document "../src/{@filename}_driver.c", "text"
vb@690
   137
        ||
vb@690
   138
        // Driver for «@name» state machine
vb@690
   139
vb@690
   140
        #include <assert.h>
vb@690
   141
        #include "pEp_internal.h"
vb@690
   142
vb@690
   143
vb@743
   144
        DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
vb@690
   145
                PEP_SESSION session,
vb@690
   146
                «@name»_event event,
vb@690
   147
                Identity partner,
vb@951
   148
                void *extra
vb@690
   149
            )
vb@690
   150
        {
vb@951
   151
            assert(session);
vb@951
   152
            if (!session)
vb@951
   153
                return PEP_ILLEGAL_VALUE;
vb@690
   154
edouard@1152
   155
            while(true)
edouard@1152
   156
            {
edouard@1152
   157
                «@name»_state new_state = fsm_«@name»(session,
edouard@1162
   158
                    session->«@filename»_state, event, partner, extra);
edouard@1157
   159
edouard@1152
   160
                if (new_state == «@name»_state_invalid_out_of_memory)
edouard@1152
   161
                    return PEP_OUT_OF_MEMORY;
edouard@1157
   162
edouard@1152
   163
                if (new_state < 0)
edouard@1152
   164
                    return PEP_SYNC_STATEMACHINE_ERROR - new_state;
edouard@1152
   165
                
edouard@1157
   166
                if (new_state == session->«@filename»_state)
edouard@1152
   167
                    break;
vb@690
   168
edouard@1157
   169
                event = Init;
edouard@1157
   170
                extra = NULL;
edouard@1152
   171
                session->«@filename»_state = new_state;
edouard@1152
   172
            } 
edouard@1152
   173
vb@951
   174
            return PEP_STATUS_OK;
vb@690
   175
        }
vb@690
   176
vb@690
   177
        ||
vb@807
   178
        document "../src/{@filename}_fsm.c", "text"
vb@609
   179
        ||
vb@807
   180
        #include "«@filename»_fsm.h"
vb@609
   181
vb@609
   182
        // state machine for «@name»
vb@609
   183
vb@609
   184
        «@name»_state fsm_«@name»(
vb@627
   185
                PEP_SESSION session,
vb@609
   186
                «@name»_state state,
vb@609
   187
                «@name»_event event,
vb@939
   188
                Identity partner,
vb@951
   189
                void *extra
vb@609
   190
            )
vb@609
   191
        {
vb@964
   192
            int cond_result;
vb@959
   193
            PEP_STATUS status = PEP_STATUS_OK;
vb@959
   194
vb@609
   195
            switch (state) {
vb@951
   196
            `` apply "state", 2
vb@609
   197
                default:
vb@743
   198
                    return («@name»_state) invalid_state;
vb@609
   199
            }
vb@609
   200
vb@609
   201
            return state;
vb@577
   202
        }
vb@582
   203
vb@609
   204
        ||
vb@577
   205
    }
vb@577
   206
vb@580
   207
    template "state"
vb@577
   208
    ||
vb@577
   209
    case «@name»:
edouard@1256
   210
        printf("State : «@name»\\\\n");
vb@578
   211
        switch (event) {
edouard@1256
   212
        `` if "not(event[@name='Init'])" |>> case Init: printf("Event : Init\\\\n"); break;
vb@578
   213
        `` apply "event", 2
vb@951
   214
            default:
vb@951
   215
                return («../@name»_state) invalid_event;
vb@578
   216
        }
vb@577
   217
        break;
vb@577
   218
vb@577
   219
    ||
vb@578
   220
vb@578
   221
    template "event"
vb@578
   222
    ||
vb@578
   223
    case «@name»:
edouard@1256
   224
    printf("Event : «@name»\\\\n");
vb@951
   225
    `` apply "action|transition|condition";
vb@582
   226
    `` if "name(*[position()=last()]) != 'transition'" |> break;
vb@578
   227
    ||
vb@578
   228
vb@582
   229
    template "action" {
vb@582
   230
        indent(0);
vb@959
   231
        > status = «@name»(session, state, 
vb@582
   232
        choose {
vb@582
   233
            when "parm" > «name(parm/*)»
vb@582
   234
            otherwise > NULL
vb@582
   235
        }
edouard@1166
   236
        choose {
edouard@1166
   237
            when "parm[2]" > , extra /*«name(parm[2]/*)»*/
edouard@1166
   238
            otherwise > , NULL
edouard@1166
   239
        }
edouard@1166
   240
        > );\n
vb@964
   241
        | if (status == PEP_OUT_OF_MEMORY)
vb@1043
   242
        |> return (int) invalid_out_of_memory;
vb@959
   243
        | if (status != PEP_STATUS_OK)
vb@1043
   244
        |> return (int) invalid_action;
vb@582
   245
    }
vb@582
   246
vb@951
   247
    template "condition" {
vb@959
   248
        | cond_result = «@name»(session`apply "parm", 0`);
vb@964
   249
        | if (cond_result < 0)
vb@964
   250
        |> return cond_result;
vb@959
   251
        | if (cond_result) {
vb@951
   252
        apply "action|transition|condition";
vb@951
   253
        | }
vb@951
   254
    }
vb@951
   255
vb@951
   256
    template "parm" choose {
vb@951
   257
        when "count(*) = 1"
vb@951
   258
            > , «name(*)»
vb@951
   259
        otherwise
vb@951
   260
            > , «name(*[1])» «name(*[2])»
vb@951
   261
    }
vb@951
   262
vb@578
   263
    template "transition" | return «@target»;
vb@577
   264
}
vb@577
   265