sync/gen_statemachine.ysl2
author Volker Birk <vb@pep.foundation>
Tue, 02 Aug 2016 12:06:45 +0200
branchkeysync
changeset 964 ef02296c41ca
parent 959 c1c463ecf30c
child 985 087d5d60c082
permissions -rw-r--r--
store group keys
     1 // generate state machine code
     2 
     3 // Copyleft (c) 2016, p≡p foundation
     4 
     5 // Written by Volker Birk
     6 
     7 include yslt.yml2
     8 
     9 tstylesheet {
    10     include ./functions.ysl2
    11 
    12     template "/protocol" {
    13         document "../src/Makefile.protocols", "text"
    14             apply "fsm", 0, mode="make";
    15         apply "fsm", 0, mode=gen;
    16     }
    17 
    18     template "fsm", mode=make
    19     ||
    20     «@filename»_fsm.c: ../sync/devicegroup.fsm
    21     \tmake -C ../«@filename»
    22     ||
    23 
    24     template "fsm", mode=gen {
    25         document "../src/{@filename}_fsm.h", "text" {
    26         ||
    27         #pragma once
    28 
    29         // state machine for «@name»
    30 
    31         #include "pEpEngine.h"
    32         #include "message.h"
    33         #include "../asn.1/«../@name»-Protocol.h"
    34         
    35         #ifdef __cplusplus
    36         extern "C" {
    37         #endif
    38 
    39         // types
    40 
    41         typedef pEp_identity * Identity;
    42         typedef stringlist_t * Stringlist;
    43         typedef union _param { Identity partner; stringlist_t *keylist; } param_t;
    44 
    45         // error values
    46 
    47         typedef enum _fsm_error {
    48             // these error values are corresponding to
    49             // PEP_SYNC_STATEMACHINE_ERROR - value
    50             invalid_state = -2,
    51             invalid_event = -3,
    52             invalid_condition = -4,
    53             invalid_action = -5,
    54 
    55             // out of memory condition
    56             invalid_out_of_memory = -128
    57         } fsm_error;
    58 
    59         // conditions
    60 
    61         `` for "func:distinctName(condition)" | int «@name»(PEP_SESSION session`apply "parm", 0`);
    62 
    63         // states
    64 
    65         typedef enum _«@name»_state {
    66             «@name»_state_NONE = 0,
    67         `` for "func:distinctName(state)" |> «@name»`if "position()!=last()" > , `
    68         } «@name»_state;
    69 
    70         // events
    71 
    72         typedef enum _«@name»_event {
    73             «@name»_event_NONE = 0,
    74         ||
    75         for "func:distinctName(state/event[not(not(/protocol/fsm/tag/@name=@name))])" {
    76             const "name", "@name";
    77             |> «$name» = «/protocol/fsm/tag[@name=$name]/@id»,
    78         }
    79         for "func:distinctName(state/event[not(/protocol/fsm/tag/@name=@name)])"
    80             |> «@name»`if "position()!=last()" > , `
    81         ||
    82         } «@name»_event;
    83 
    84         // actions
    85 
    86         `` const "name", "@name"
    87         `` for "func:distinctName(//action)" | PEP_STATUS «@name»(PEP_SESSION session, «$name»_state state, Identity partner, void *extra);
    88 
    89         // message receiver
    90         
    91         PEP_STATUS receive_«@name»_msg(PEP_SESSION session, message *msg);
    92 
    93         // state machine
    94 
    95         «@name»_state fsm_«@name»(
    96                 PEP_SESSION session,
    97                 «@name»_state state,
    98                 «@name»_event event,
    99                 Identity partner,
   100                 void *extra
   101             );
   102 
   103         // driver
   104 
   105         DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
   106                 PEP_SESSION session,
   107                 «@name»_event event,
   108                 Identity partner,
   109                 void *extra
   110             );
   111 
   112         #ifdef __cplusplus
   113         }
   114         #endif
   115 
   116         ||
   117         }
   118         document "../src/{@filename}_driver.c", "text"
   119         ||
   120         // Driver for «@name» state machine
   121 
   122         #include <assert.h>
   123         #include "pEp_internal.h"
   124 
   125 
   126         DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
   127                 PEP_SESSION session,
   128                 «@name»_event event,
   129                 Identity partner,
   130                 void *extra
   131             )
   132         {
   133             assert(session);
   134             if (!session)
   135                 return PEP_ILLEGAL_VALUE;
   136 
   137             «@name»_state state = fsm_«@name»(session,
   138                     session->«@filename»_state, event, partner, extra);
   139             if (state == invalid_out_of_memory)
   140                 return PEP_OUT_OF_MEMORY;
   141             if (state < 0)
   142                 return PEP_SYNC_STATEMACHINE_ERROR - state;
   143 
   144             session->«@filename»_state = state;
   145             return PEP_STATUS_OK;
   146         }
   147 
   148         ||
   149         document "../src/{@filename}_fsm.c", "text"
   150         ||
   151         #include "«@filename»_fsm.h"
   152 
   153         // state machine for «@name»
   154 
   155         «@name»_state fsm_«@name»(
   156                 PEP_SESSION session,
   157                 «@name»_state state,
   158                 «@name»_event event,
   159                 Identity partner,
   160                 void *extra
   161             )
   162         {
   163             int cond_result;
   164             PEP_STATUS status = PEP_STATUS_OK;
   165 
   166             switch (state) {
   167             `` apply "state", 2
   168                 default:
   169                     return («@name»_state) invalid_state;
   170             }
   171 
   172             return state;
   173         }
   174 
   175         ||
   176     }
   177 
   178     template "state"
   179     ||
   180     case «@name»:
   181         switch (event) {
   182         `` apply "event", 2
   183             default:
   184                 return («../@name»_state) invalid_event;
   185         }
   186         break;
   187 
   188     ||
   189 
   190     template "event"
   191     ||
   192     case «@name»:
   193     `` apply "action|transition|condition";
   194     `` if "name(*[position()=last()]) != 'transition'" |> break;
   195     ||
   196 
   197     template "action" {
   198         indent(0);
   199         > status = «@name»(session, state, 
   200         choose {
   201             when "parm" > «name(parm/*)»
   202             otherwise > NULL
   203         }
   204         > , NULL);\n
   205         | if (status == PEP_OUT_OF_MEMORY)
   206         |> return invalid_out_of_memory;
   207         | if (status != PEP_STATUS_OK)
   208         |> return invalid_action;
   209     }
   210 
   211     template "condition" {
   212         | cond_result = «@name»(session`apply "parm", 0`);
   213         | if (cond_result < 0)
   214         |> return cond_result;
   215         | if (cond_result) {
   216         apply "action|transition|condition";
   217         | }
   218     }
   219 
   220     template "parm" choose {
   221         when "count(*) = 1"
   222             > , «name(*)»
   223         otherwise
   224             > , «name(*[1])» «name(*[2])»
   225     }
   226 
   227     template "transition" | return «@target»;
   228 }
   229