sync/gen_statemachine.ysl2
author Volker Birk <vb@pep.foundation>
Sat, 20 Aug 2016 18:04:13 +0200
branchkeysync
changeset 1046 73be5d9af815
parent 1043 f786ee22e281
child 1047 2a4a2ec1340b
permissions -rw-r--r--
adding broadcast function
     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         
    34         #ifdef __cplusplus
    35         extern "C" {
    36         #endif
    37 
    38         // types
    39 
    40         typedef pEp_identity * Identity;
    41         typedef stringlist_t * Stringlist;
    42         typedef union _param { Identity partner; stringlist_t *keylist; } param_t;
    43 
    44         // error values
    45 
    46         typedef enum _fsm_error {
    47             // these error values are corresponding to
    48             // PEP_SYNC_STATEMACHINE_ERROR - value
    49             invalid_state = -2,
    50             invalid_event = -3,
    51             invalid_condition = -4,
    52             invalid_action = -5,
    53 
    54             // out of memory condition
    55             invalid_out_of_memory = -128
    56         } fsm_error;
    57 
    58         // conditions
    59 
    60         `` for "func:distinctName(condition)" | int «@name»(PEP_SESSION session`apply "parm", 0`);
    61 
    62         // states
    63 
    64         typedef enum _«@name»_state {
    65             // error values also in this namespace
    66             «@name»_state_invalid_state = (int) invalid_state,
    67             «@name»_state_invalid_event = (int) invalid_event,
    68             «@name»_state_invalid_condition = (int) invalid_condition,
    69             «@name»_state_invalid_action = (int) invalid_action,
    70             «@name»_state_invalid_out_of_memory = (int) invalid_out_of_memory,
    71 
    72             «@name»_state_NONE = 0,
    73         `` for "func:distinctName(state)" |> «@name»`if "position()!=last()" > , `
    74         } «@name»_state;
    75 
    76         // events
    77 
    78         typedef enum _«@name»_event {
    79             «@name»_event_NONE = 0,
    80         ||
    81         for "func:distinctName(state/event[not(not(/protocol/fsm/tag/@name=@name))])" {
    82             const "name", "@name";
    83             |> «$name» = «/protocol/fsm/tag[@name=$name]/@id»,
    84         }
    85         for "func:distinctName(state/event[not(/protocol/fsm/tag/@name=@name)])"
    86             |> «@name»`if "position()!=last()" > , `
    87         ||
    88         } «@name»_event;
    89 
    90         // actions
    91 
    92         `` const "name", "@name"
    93         `` for "func:distinctName(//action)" | PEP_STATUS «@name»(PEP_SESSION session, «$name»_state state, Identity partner, void *extra);
    94 
    95         // message receiver
    96         
    97         PEP_STATUS receive_«@name»_msg(PEP_SESSION session, message *msg);
    98 
    99         // state machine
   100 
   101         «@name»_state fsm_«@name»(
   102                 PEP_SESSION session,
   103                 «@name»_state state,
   104                 «@name»_event event,
   105                 Identity partner,
   106                 void *extra
   107             );
   108 
   109         // driver
   110 
   111         DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
   112                 PEP_SESSION session,
   113                 «@name»_event event,
   114                 Identity partner,
   115                 void *extra
   116             );
   117 
   118         // misc
   119 
   120         PEP_STATUS broadcast_msg(PEP_SESSION session, Identity partner, char
   121                 *payload, size_t size);
   122 
   123         #ifdef __cplusplus
   124         }
   125         #endif
   126 
   127         ||
   128         }
   129         document "../src/{@filename}_driver.c", "text"
   130         ||
   131         // Driver for «@name» state machine
   132 
   133         #include <assert.h>
   134         #include "pEp_internal.h"
   135 
   136 
   137         DYNAMIC_API PEP_STATUS fsm_«@name»_inject(
   138                 PEP_SESSION session,
   139                 «@name»_event event,
   140                 Identity partner,
   141                 void *extra
   142             )
   143         {
   144             assert(session);
   145             if (!session)
   146                 return PEP_ILLEGAL_VALUE;
   147 
   148             «@name»_state state = fsm_«@name»(session,
   149                     session->«@filename»_state, event, partner, extra);
   150             if (state == «@name»_state_invalid_out_of_memory)
   151                 return PEP_OUT_OF_MEMORY;
   152             if (state < 0)
   153                 return PEP_SYNC_STATEMACHINE_ERROR - state;
   154 
   155             session->«@filename»_state = state;
   156             return PEP_STATUS_OK;
   157         }
   158 
   159         ||
   160         document "../src/{@filename}_fsm.c", "text"
   161         ||
   162         #include "«@filename»_fsm.h"
   163 
   164         // state machine for «@name»
   165 
   166         «@name»_state fsm_«@name»(
   167                 PEP_SESSION session,
   168                 «@name»_state state,
   169                 «@name»_event event,
   170                 Identity partner,
   171                 void *extra
   172             )
   173         {
   174             int cond_result;
   175             PEP_STATUS status = PEP_STATUS_OK;
   176 
   177             switch (state) {
   178             `` apply "state", 2
   179                 default:
   180                     return («@name»_state) invalid_state;
   181             }
   182 
   183             return state;
   184         }
   185 
   186         ||
   187     }
   188 
   189     template "state"
   190     ||
   191     case «@name»:
   192         switch (event) {
   193         `` apply "event", 2
   194             default:
   195                 return («../@name»_state) invalid_event;
   196         }
   197         break;
   198 
   199     ||
   200 
   201     template "event"
   202     ||
   203     case «@name»:
   204     `` apply "action|transition|condition";
   205     `` if "name(*[position()=last()]) != 'transition'" |> break;
   206     ||
   207 
   208     template "action" {
   209         indent(0);
   210         > status = «@name»(session, state, 
   211         choose {
   212             when "parm" > «name(parm/*)»
   213             otherwise > NULL
   214         }
   215         > , NULL);\n
   216         | if (status == PEP_OUT_OF_MEMORY)
   217         |> return (int) invalid_out_of_memory;
   218         | if (status != PEP_STATUS_OK)
   219         |> return (int) invalid_action;
   220     }
   221 
   222     template "condition" {
   223         | cond_result = «@name»(session`apply "parm", 0`);
   224         | if (cond_result < 0)
   225         |> return cond_result;
   226         | if (cond_result) {
   227         apply "action|transition|condition";
   228         | }
   229     }
   230 
   231     template "parm" choose {
   232         when "count(*) = 1"
   233             > , «name(*)»
   234         otherwise
   235             > , «name(*[1])» «name(*[2])»
   236     }
   237 
   238     template "transition" | return «@target»;
   239 }
   240