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