sync/gen_statemachine.ysl2
branchKeySyncWaitForAccept
changeset 1590 6e007351ccde
parent 1587 6db4fde2cdae
child 1595 ddf2993d75fe
     1.1 --- a/sync/gen_statemachine.ysl2	Mon Feb 20 09:31:58 2017 +0100
     1.2 +++ b/sync/gen_statemachine.ysl2	Mon Feb 20 10:29:45 2017 +0100
     1.3 @@ -186,6 +186,10 @@
     1.4          #include "pEp_internal.h"
     1.5          #include "«@filename»_fsm.h"
     1.6  
     1.7 +        // local definitions for «@name»'s state machine 
     1.8 +
     1.9 +        `` apply "state", 2 mode="declStatePayload"
    1.10 +
    1.11          // state machine for «@name»
    1.12  
    1.13          «@name»_state fsm_«@name»(
    1.14 @@ -212,28 +216,59 @@
    1.15          ||
    1.16      }
    1.17  
    1.18 -    template "state"
    1.19 +    template "state" {
    1.20 +        ||
    1.21 +        case «@name»:
    1.22 +        {
    1.23 +            DEBUG_LOG("Entering FSM state", "«../@filename»_fsm.c", "state=«@name»")
    1.24 +        ||
    1.25 +
    1.26 +        if "count(parm) > 0" 
    1.27 +        || 
    1.28 +            assert(session->sync_state_payload);
    1.29 +            if(!session->sync_state_payload) return («../@name»_state) invalid_state;
    1.30 +            `` apply "parm", 1 mode="unpackStatePayloadParm" with "stateName", "@name"
    1.31 +        ||
    1.32 +
    1.33 +        ||
    1.34 +            *timeout = «@timeout»;
    1.35 +            switch (event) {
    1.36 +        ||
    1.37 +
    1.38 +        if "not(event[@name='Init'])" 
    1.39 +        ||
    1.40 +                case Init: 
    1.41 +                    DEBUG_LOG("FSM event", "«../@filename»_fsm.c, state=«@name»", "event=Init") 
    1.42 +                    break;
    1.43 +        ||
    1.44 +
    1.45 +        apply "event", 2;
    1.46 +
    1.47 +        ||
    1.48 +                default:
    1.49 +                    return («../@name»_state) invalid_event;
    1.50 +            }
    1.51 +            break;
    1.52 +        }
    1.53 +        ||
    1.54 +    }
    1.55 +
    1.56 +    template "parm" mode="unpackStatePayloadParm" 
    1.57 +    {
    1.58 +        param "stateName";
    1.59 +        | «name(*[1])» «name(*[2])» = ((«$stateName»_state_payload_t*)session->sync_state_payload)->«name(*[2])»;
    1.60 +    }
    1.61 +
    1.62 +    template "state" mode="declStatePayload" if "count(parm) > 0"
    1.63      ||
    1.64 -    case «@name»:
    1.65 -    {
    1.66 -        `` if "count(parm) > 1" error | # TODO composite state payload 
    1.67 -        `` apply "parm", 1 mode="stateParm"
    1.68 -        *timeout = «@timeout»;
    1.69 -        DEBUG_LOG("Entering FSM state", "«../@filename»_fsm.c", "state=«@name»")
    1.70 -        switch (event) {
    1.71 -        `` if "not(event[@name='Init'])" |>> case Init: DEBUG_LOG("FSM event", "«../@filename»_fsm.c, state=«@name»", "event=Init") break;
    1.72 -        `` apply "event", 2
    1.73 -            default:
    1.74 -                return («../@name»_state) invalid_event;
    1.75 -        }
    1.76 -        break;
    1.77 -    }
    1.78 +    typedef struct _«@name»_state_payload {
    1.79 +        `` apply "parm", 1 mode="declStatePayloadParm"
    1.80 +    } «@name»_state_payload_t;
    1.81 +
    1.82      ||
    1.83  
    1.84 -    template "parm" mode="stateParm" 
    1.85 -    {
    1.86 -        | «name(*[1])» «name(*[2])» = («name(*[1])»)session->sync_state_payload;
    1.87 -    }
    1.88 +    template "parm" mode="declStatePayloadParm" 
    1.89 +    | «name(*[1])» «name(*[2])»;
    1.90  
    1.91      template "event"
    1.92      ||
    1.93 @@ -293,19 +328,46 @@
    1.94  
    1.95      template "transition"{
    1.96          const "stateparm", "ancestor::state/child::parm";
    1.97 -        if "$stateparm" {
    1.98 -            | if(session->sync_state_payload){
    1.99 -            |     free_«yml:lcase(name($stateparm[1]/*))»((«name($stateparm[1]/*)»)session->sync_state_payload);
   1.100 -            |     session->sync_state_payload = NULL;
   1.101 -            | }
   1.102 +        if "count($stateparm) > 0" {
   1.103 +            ||
   1.104 +            assert(session->sync_state_payload);
   1.105 +            if(!session->sync_state_payload) return («ancestor::fsm/@name»_state) invalid_state;
   1.106 +            `` apply "$stateparm", 0 mode="freeStatePayloadParm" with "stateName", "ancestor::state/@name"
   1.107 +            free(session->sync_state_payload);
   1.108 +            session->sync_state_payload = NULL;
   1.109 +            ||
   1.110          }
   1.111 -        if "parm" {
   1.112 +        if "count(parm) > 0" {
   1.113              const "nextstatename", "@target";
   1.114              const "nextstateparm", "ancestor::fsm/child::state[@name = $nextstatename]/child::parm";
   1.115 -            | session->sync_state_payload = «yml:lcase(name($nextstateparm/*))»_dup(«name(parm/*)»);
   1.116 +            if "count(parm) != count($nextstateparm)" 
   1.117 +                error > different state parameters and transition parameters count state=«ancestor::state/@name», event=«ancestor::event/@name» target=«@target»
   1.118 +            ||
   1.119 +            session->sync_state_payload = malloc(sizeof(«$nextstatename»_state_payload_t));
   1.120 +            assert(session->sync_state_payload);
   1.121 +            if(!session->sync_state_payload) return («ancestor::fsm/@name»_state) invalid_out_of_memory;
   1.122 +            ||
   1.123 +            apply "$nextstateparm", 0 mode="dupStatePayloadParm" {
   1.124 +                with "stateName", "$nextstatename";
   1.125 +                with "transitionParms", "parm";
   1.126 +            }
   1.127          }
   1.128          | DEBUG_LOG("FSM transition", "«ancestor::fsm/@filename»_fsm.c, state=«ancestor::state/@name», event=«ancestor::event/@name»", "target=«@target»")
   1.129          | return «@target»;
   1.130      }
   1.131 +
   1.132 +    template "parm" mode="freeStatePayloadParm" 
   1.133 +    {
   1.134 +        param "stateName";
   1.135 +        | free_«yml:lcase(name(*[1]))»(((«$stateName»_state_payload_t*)session->sync_state_payload)->«name(*[2])»);
   1.136 +    }
   1.137 +
   1.138 +    template "parm" mode="dupStatePayloadParm" 
   1.139 +    {
   1.140 +        param "stateName";
   1.141 +        param "transitionParms";
   1.142 +        | ((«$stateName»_state_payload_t*)session->sync_state_payload)->«name(*[2])» =
   1.143 +        |     «yml:lcase(name(*[1]))»_dup(«name($transitionParms[position()]/*)»);
   1.144 +    }
   1.145  }
   1.146