diff options
Diffstat (limited to 'agen5/fsm-trans.tlib')
-rw-r--r-- | agen5/fsm-trans.tlib | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/agen5/fsm-trans.tlib b/agen5/fsm-trans.tlib new file mode 100644 index 0000000..0706910 --- /dev/null +++ b/agen5/fsm-trans.tlib @@ -0,0 +1,359 @@ +[= AutoGen5 Template -*- Mode: Text -*- + +## This file is part of AutoGen. +## AutoGen Copyright (c) 1992-2012 by Bruce Korb - all rights reserved +## +## AutoGen is free software: you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by the +## Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## AutoGen is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## See the GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License along +## with this program. If not, see <http://www.gnu.org/licenses/>. + +=][= +(make-tmp-dir) + +(define get-up (lambda (nm) + (string-upcase! (string->c-name! (get nm))) )) + +(define get-down (lambda (nm) + (string-downcase! (string->c-name! (get nm))) )) + +(define stack-up (lambda (nm) + (string-upcase! (string->c-name! (join "\n" (stack nm)))) )) + +(define event-string "") =][= + +DEFINE state-table =] + + /* STATE [= (get "st_ix") =]: [= + (define STATE-NAME (get-up "state")) + (shellf "state=%s" STATE-NAME) + (string-append PFX "_ST_" STATE-NAME) =] */ + { [= + + FOR event "\n " =][= + (set! event-string (get-up "event")) + (set! fmt (shellf "echo ${FSM_TRANS_%s_%s}%s" + STATE-NAME event-string (if (last-for?) "" ",") )) + (if (exist? event-string) (set! event-string (get event-string))) + (sprintf "%-47s /* EVT: %s */" fmt event-string ) =][= + + ENDFOR + +=] + }[= + +ENDDEF state-table + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE enumerate-transitions =] +/* + * Enumeration of the valid transition types + * Some transition types may be common to several transitions. + */ +typedef enum { +[=(string-upcase! (shellf + "sed '$s/,$//;s/^/ %s_TR_/' ${tmp_dir}/xlist" PFX))=] +} te_[=(. pfx)=]_trans; +#define [=(. PFX)=]_TRANSITION_CT [= + `tct="\`wc -l < ${tmp_dir}/xlist\`" + echo $tct`=] + +/** + * State transition handling map. Map the state enumeration and the event + * enumeration to the new state and the transition enumeration code (in that + * order). It is indexed by first the current state and then the event code. + */ +typedef struct [=(. pfx)=]_transition [= (. t-trans) =]; +struct [=(. pfx)=]_transition { + te_[=(. pfx)=]_state next_state; + te_[=(. pfx)=]_trans transition; +}; +[= + + IF (exist? "use_ifdef") + +=] +#ifndef DEFINE_FSM +extern const [= (. t-trans) =] [=(. pfx)=]_trans_table[ [=(. PFX) +=]_STATE_CT ][ [=(. PFX)=]_EVENT_CT ]; + +extern int +[=(. pfx)=]_invalid_transition( te_[=(. pfx)=]_state st, te_[= + (. pfx)=]_event evt ); +#else +[= + + ELSE + +=]static [= + ENDIF + +=]const [= (. t-trans) =] +[=(. pfx)=]_trans_table[ [=(. PFX) +=]_STATE_CT ][ [=(. PFX)=]_EVENT_CT ] = {[= + state-table + state = init + st_ix = "0" =][= + + FOR state =], +[= state-table st_ix = (+ 1 (for-index)) =][= + ENDFOR =] +};[= + + IF (exist? "use_ifdef") =][= + emit-invalid-msg =] +#endif /* DEFINE_FSM */[= + ENDIF =][= + +ENDDEF enumerate-transitions + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE callback-transitions + +=] +/** + * Callback routine prototype. They return the next state. Normally, that + * should be the value of the "maybe_next" argument. + */ +typedef te_[=(. pfx)=]_state ([=(. pfx)=]_callback_t)([= + emit-cookie-args =] + te_[=(. pfx)=]_state initial, + te_[=(. pfx)=]_state maybe_next, + te_[=(. pfx)=]_event trans_evt ); + +static [=(. pfx)=]_callback_t +[=(shellf "sed '$s/,$/;/;s/^/ %s_do_/' ${tmp_dir}/xlist" pfx)=] + +/** + * Declare all the state transition handling routines. + */ +typedef struct transition [= (. t-trans) =]; +struct transition {[= + (set! fmt (sprintf "\n %%-%ds %%s;" + (+ (string-length pfx) 14) )) + (sprintf (string-append fmt fmt) + (string-append "te_" pfx "_state") "next_state" + (string-append pfx "_callback_t*") "trans_proc") =] +}; + +/** + * State transition maps. Map the enumeration and the event enumeration + * to the new state and the transition enumeration code (in that order). + * It is indexed by first the current state and then the event code. + */ +static const [= (. t-trans) =] +[=(. pfx)=]_trans_table[ [=(. PFX) +=]_STATE_CT ][ [=(. PFX)=]_EVENT_CT ] = {[= + + state-table + state = init st_ix = "0" =][= + + FOR state =],[= + state-table st_ix = (+ 1 (for-index)) =][= + ENDFOR =] +};[= + +ENDDEF callback-transitions + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE machine-step =][= + +(define trans-name "trans") +(define trans-field "transition") +(define trans-valu (string-append PFX "_TR_INVALID")) + +(if (not (=* (get "method") "case")) (begin + (set! trans-name "pT ") + (set! trans-field "trans_proc") + (set! trans-valu (string-append pfx "_do_invalid")) +) ) + +=] +#ifndef __COVERITY__ + if (trans_evt >= [=(. PFX)=]_EV_INVALID) { + nxtSt = [=(. PFX)=]_ST_INVALID; + [=(. trans-name)=] = [=(. trans-valu)=]; + } else +#endif /* __COVERITY__ */ + { + const [= (. t-trans) =]* pTT = + [=(. pfx)=]_trans_table[ [=(. pfx)=]_state ] + trans_evt; +[= IF (exist? "debug-flag") \=] +#ifdef [= (get "debug-flag") =] + firstNext = /* next line */ +#endif /* [= "debug-flag =] */ +[= ENDIF \=] + nxtSt = pTT->next_state; + [=(. trans-name)=] = pTT->[=(. trans-field)=]; + } +[= IF (exist? "debug-flag") \=] +#ifdef [= (get "debug-flag") =] + printf( "in state %s(%d) step %s(%d) to %s(%d)\n", + [=(. PFX)=]_STATE_NAME( [=(. pfx)=]_state ), [=(. pfx)=]_state, + [=(. PFX)=]_EVT_NAME( trans_evt ), trans_evt, + [=(. PFX)=]_STATE_NAME( nxtSt ), nxtSt ); +#endif /* [= "debug-flag =] */ +[= ENDIF \=][= + + IF (not (=* (get "method") "case")) =][= + INVOKE run-callback =][= + ELIF (exist? "handler-file") =] +#define FSM_SWITCH_CODE +#include "[= handler-file =]" +#undef FSM_SWITCH_CODE[= + ELSE =][= + INVOKE run-switch =][= + ENDIF + +=] +[= IF (exist? "debug-flag") \=] +#ifdef [= (get "debug-flag") =] + if (nxtSt != firstNext) + printf( "transition code changed destination state to %s(%d)\n", + [=(. PFX)=]_STATE_NAME( nxtSt ), nxtSt ); +#endif /* [= "debug-flag =] */ +[= ENDIF \=][= + + IF (not (=* (get "type") "reent")) =] + [=(. pfx)=]_state = nxtSt;[= + ENDIF =] +[= +ENDDEF machine-step + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE fsm-proc-variables + + =] +[= IF (exist? "debug-flag") \=] +#ifdef [= (get "debug-flag") =] + te_[=(. pfx)=]_state firstNext; +#endif +[= ENDIF \=] + te_[=(. pfx)=]_state nxtSt;[= + IF (=* (get "method") "call") =] + [=(. pfx)=]_callback_t* pT;[= + ELSE =] + te_[=(. pfx)=]_trans trans;[= + ENDIF =][= + +ENDDEF fsm-proc-variables + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE make-loop-proc =] +/** + * Run the FSM. Will return [=(. PFX)=]_ST_DONE or [=(. PFX)=]_ST_INVALID + */ +[=mode=]te_[=(. pfx)=]_state +[=(. pfx)=]_run_fsm([= + IF (exist? "cookie") =][= + FOR cookie "," =] + [=cookie=][= + ENDFOR=][= + ELSE=] void[=ENDIF=] )[= + +ENDDEF make-loop-proc + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE looping-machine + + =][= make-loop-proc mode = "" =] +{ + te_[=(. pfx)=]_state [=(. pfx)=]_state = [=(. PFX)=]_ST_INIT; + te_[=(. pfx)=]_event trans_evt;[= + INVOKE fsm-proc-variables =][= + IF (exist? "cookie") =] +[= (shell (string-append + "cookies='" (stack-join "\n" "cookie") "' + echo \"$cookies\" | \ + sed -e 's/^/ /' \ + -e 's@\\([a-zA-Z0-9_]*\\)*$@saved_\\1 = \\1;@' + echo \"$cookies\" | \ + sed -e 's@.*[^a-z0-9_A-Z]\\([a-zA-Z0-9_]*\\)*$@\\1;@' \ + -e 's/^/ (void)saved_/'" )) + + =][= + ENDIF=] + + while ([=(. pfx)=]_state < [=(. PFX)=]_ST_INVALID) { +[=IF (exist? "handler-file")=] +#define FSM_FIND_TRANSITION +#include "[= handler-file =]" +#undef FSM_FIND_TRANSITION[= + ELSE =] +[=(extract fsm-source " /* %s == FIND TRANSITION == %s */" "" + " trans_evt = GET_NEXT_TRANS();" ) =][= + ENDIF =] +[= (out-push-new (string-append tmp-dir "/cktbl"))=][= + INVOKE machine-step =][= + (out-pop) (shell + "sed 's/^ / /;s/ / /' ${tmp_dir}/cktbl") +=] + } + return [=(. pfx)=]_state; +}[= + +ENDDEF looping-machine + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE make-step-proc =] +/** + * Step the FSM. Returns the resulting state. If the current state is + * [=(. PFX)=]_ST_DONE or [=(. PFX)=]_ST_INVALID, it resets to + * [=(. PFX)=]_ST_INIT and returns [=(. PFX)=]_ST_INIT. + */ +[=mode=]te_[=(. pfx)=]_state +[=(. pfx)=]_step([= + IF (=* (get "type") "reent") =] + te_[= (. pfx) =]_state [= (. pfx) =]_state,[= + ENDIF =] + te_[= (. pfx) =]_event trans_evt[= + FOR cookie =], + [=cookie=][= + ENDFOR=] )[= + +ENDDEF make-step-proc + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE stepping-machine + + =][= INVOKE make-step-proc mode = "" =] +{[= + fsm-proc-variables =] + + if ((unsigned)[=(. pfx)=]_state >= [=(. PFX)=]_ST_INVALID) {[= + IF (=* (get "type") "step") =] + [=(. pfx)=]_state = [=(. PFX)=]_ST_INIT;[= + ENDIF =] + return [=(. PFX)=]_ST_INIT; + } +[=INVOKE machine-step =][= + IF (exist? "handler-file")=] +#define FSM_FINISH_STEP +#include "[= handler-file =]" +#undef FSM_FINISH_STEP[= + ELSE =] +[=(extract fsm-source " /* %s == FINISH STEP == %s */")=][= + ENDIF =] + + return nxtSt; +}[= + +ENDDEF stepping-machine + +# end of agen5/fsm-trans.tlib =] |