sync/gen_statemachine.ysl2
author Volker Birk <vb@pep.foundation>
Sun, 31 Jul 2016 20:25:27 +0200
branchkeysync
changeset 952 986fd7b2eb8f
parent 951 dec407deb10e
child 959 c1c463ecf30c
permissions -rw-r--r--
...
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@609
    31
        #include "pEpEngine.h"
vb@952
    32
        #include "message.h"
vb@951
    33
        #include "../asn.1/«../@name»-Protocol.h"
vb@654
    34
        
vb@654
    35
        #ifdef __cplusplus
vb@654
    36
        extern "C" {
vb@654
    37
        #endif
vb@608
    38
vb@609
    39
        // types
Edouard@605
    40
vb@609
    41
        typedef pEp_identity * Identity;
vb@939
    42
        typedef stringlist_t * Stringlist;
vb@939
    43
        typedef union _param { Identity partner; stringlist_t *keylist; } param_t;
vb@583
    44
vb@609
    45
        // error values
vb@577
    46
vb@609
    47
        typedef enum _fsm_error {
vb@743
    48
            invalid_state = -2,
vb@743
    49
            invalid_event = -3
vb@609
    50
        } fsm_error;
vb@583
    51
vb@951
    52
        // conditions
vb@951
    53
vb@951
    54
        `` for "func:distinctName(condition)" | bool «@name»(PEP_SESSION session`apply "parm", 0`);
vb@951
    55
vb@609
    56
        // states
vb@578
    57
vb@609
    58
        typedef enum _«@name»_state {
vb@951
    59
            «@name»_state_NONE = 0,
vb@623
    60
        `` for "func:distinctName(state)" |> «@name»`if "position()!=last()" > , `
vb@609
    61
        } «@name»_state;
vb@583
    62
vb@609
    63
        // events
vb@578
    64
vb@609
    65
        typedef enum _«@name»_event {
vb@951
    66
            «@name»_event_NONE = 0,
vb@711
    67
        ||
vb@711
    68
        for "func:distinctName(state/event[not(not(/protocol/fsm/tag/@name=@name))])" {
vb@711
    69
            const "name", "@name";
vb@711
    70
            |> «$name» = «/protocol/fsm/tag[@name=$name]/@id»,
vb@711
    71
        }
vb@711
    72
        for "func:distinctName(state/event[not(/protocol/fsm/tag/@name=@name)])"
vb@711
    73
            |> «@name»`if "position()!=last()" > , `
vb@711
    74
        ||
vb@609
    75
        } «@name»_event;
vb@583
    76
vb@609
    77
        // actions
vb@582
    78
vb@690
    79
        `` const "name", "@name"
vb@939
    80
        `` for "func:distinctName(//action)" | PEP_STATUS «@name»(PEP_SESSION session, «$name»_state state, Identity partner, void *extra);
Edouard@605
    81
vb@951
    82
        // message receiver
vb@951
    83
        
vb@952
    84
        PEP_STATUS receive_«@name»_msg(PEP_SESSION session, message *msg);
vb@951
    85
vb@626
    86
        // state machine
vb@626
    87
vb@626
    88
        «@name»_state fsm_«@name»(
vb@627
    89
                PEP_SESSION session,
vb@626
    90
                «@name»_state state,
vb@626
    91
                «@name»_event event,
vb@939
    92
                Identity partner,
vb@951
    93
                void *extra
vb@626
    94
            );
vb@626
    95
vb@609
    96
        // driver
Edouard@605
    97
vb@782
    98
        DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
vb@690
    99
                PEP_SESSION session,
vb@690
   100
                «@name»_event event,
vb@690
   101
                Identity partner,
vb@951
   102
                void *extra
vb@690
   103
            );
Edouard@605
   104
vb@654
   105
        #ifdef __cplusplus
vb@654
   106
        }
vb@654
   107
        #endif
vb@654
   108
vb@609
   109
        ||
vb@711
   110
        }
vb@807
   111
        document "../src/{@filename}_driver.c", "text"
vb@690
   112
        ||
vb@690
   113
        // Driver for «@name» state machine
vb@690
   114
vb@690
   115
        #include <assert.h>
vb@690
   116
        #include "pEp_internal.h"
vb@690
   117
vb@690
   118
vb@743
   119
        DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
vb@690
   120
                PEP_SESSION session,
vb@690
   121
                «@name»_event event,
vb@690
   122
                Identity partner,
vb@951
   123
                void *extra
vb@690
   124
            )
vb@690
   125
        {
vb@951
   126
            assert(session);
vb@951
   127
            if (!session)
vb@951
   128
                return PEP_ILLEGAL_VALUE;
vb@690
   129
vb@807
   130
            session->«@filename»_state = fsm_«@name»(session, session->«@filename»_state,
vb@951
   131
                    event, partner, extra);
vb@690
   132
vb@951
   133
            return PEP_STATUS_OK;
vb@690
   134
        }
vb@690
   135
vb@690
   136
        ||
vb@807
   137
        document "../src/{@filename}_fsm.c", "text"
vb@609
   138
        ||
vb@807
   139
        #include "«@filename»_fsm.h"
vb@609
   140
vb@609
   141
        // state machine for «@name»
vb@609
   142
vb@609
   143
        «@name»_state fsm_«@name»(
vb@627
   144
                PEP_SESSION session,
vb@609
   145
                «@name»_state state,
vb@609
   146
                «@name»_event event,
vb@939
   147
                Identity partner,
vb@951
   148
                void *extra
vb@609
   149
            )
vb@609
   150
        {
vb@609
   151
            switch (state) {
vb@951
   152
            `` apply "state", 2
vb@609
   153
                default:
vb@743
   154
                    return («@name»_state) invalid_state;
vb@609
   155
            }
vb@609
   156
vb@609
   157
            return state;
vb@577
   158
        }
vb@582
   159
vb@609
   160
        ||
vb@577
   161
    }
vb@577
   162
vb@580
   163
    template "state"
vb@577
   164
    ||
vb@577
   165
    case «@name»:
vb@578
   166
        switch (event) {
vb@578
   167
        `` apply "event", 2
vb@951
   168
            default:
vb@951
   169
                return («../@name»_state) invalid_event;
vb@578
   170
        }
vb@577
   171
        break;
vb@577
   172
vb@577
   173
    ||
vb@578
   174
vb@578
   175
    template "event"
vb@578
   176
    ||
vb@578
   177
    case «@name»:
vb@951
   178
    `` apply "action|transition|condition";
vb@582
   179
    `` if "name(*[position()=last()]) != 'transition'" |> break;
vb@578
   180
    ||
vb@578
   181
vb@582
   182
    template "action" {
vb@582
   183
        indent(0);
vb@690
   184
        > «@name»(session, state, 
vb@582
   185
        choose {
vb@582
   186
            when "parm" > «name(parm/*)»
vb@582
   187
            otherwise > NULL
vb@582
   188
        }
vb@939
   189
        > , NULL);\n
vb@582
   190
    }
vb@582
   191
vb@951
   192
    template "condition" {
vb@951
   193
        | if («@name»(session`apply "parm", 0`)) {
vb@951
   194
        apply "action|transition|condition";
vb@951
   195
        | }
vb@951
   196
    }
vb@951
   197
vb@951
   198
    template "parm" choose {
vb@951
   199
        when "count(*) = 1"
vb@951
   200
            > , «name(*)»
vb@951
   201
        otherwise
vb@951
   202
            > , «name(*[1])» «name(*[2])»
vb@951
   203
    }
vb@951
   204
vb@578
   205
    template "transition" | return «@target»;
vb@577
   206
}
vb@577
   207