summaryrefslogtreecommitdiff
path: root/agen5/fsm-trans.tlib
diff options
context:
space:
mode:
Diffstat (limited to 'agen5/fsm-trans.tlib')
-rw-r--r--agen5/fsm-trans.tlib359
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 =]