2 * Bug test contains code fragments from qpnano framework,
3 * Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
4 * and released under the GPL
5 * See www.quantum-leaps.com/downloads/index.htm#QPN
10 #define Q_REENTRANT reentrant
12 #define Q_SIG(me_) (((QFsm *)(me_))->evt.sig)
14 #define QEP_MAX_NEST_DEPTH 5
16 #define QEP_EMPTY_SIG 0
18 enum QReservedSignals {
19 Q_ENTRY_SIG = 1, /**< signal for coding entry actions */
20 Q_EXIT_SIG, /**< signal for coding exit actions */
21 Q_INIT_SIG, /**< signal for coding nested initial transitions */
22 Q_TIMEOUT_SIG, /**< signal used by time events */
23 Q_USER_SIG /**< first signal that can be used in user applications */
26 typedef int8_t QSignal;
27 typedef struct QEventTag {
34 typedef void (*QState)(struct QFsmTag *me);
35 typedef QState (*QHsmState)(struct QHsmTag *me);
37 typedef QState QSTATE;
39 typedef struct QFsmTag {
44 typedef struct QHsmTag {
49 typedef struct QHsmDerivedTag {
54 QHsmDerived AO_derived;
56 QSTATE state_1(QHsmDerived *me) Q_REENTRANT
58 if (Q_SIG(me) == Q_INIT_SIG)
64 QSTATE state_2(QHsmDerived *me) Q_REENTRANT
66 if (Q_SIG(me) == Q_USER_SIG)
67 return (QSTATE)state_1;
72 void QHsm_dispatch(QHsm *me) Q_REENTRANT
74 QHsmState path[QEP_MAX_NEST_DEPTH];
76 QHsmState t = me->state;
78 path[1] = t; /* save the current state in case a transition is taken */
80 do { /* process the event hierarchically... */
83 /********************************************************************
85 * The call which fails when s is copied from the stack frame
87 ********************************************************************/
88 t = (QHsmState)((*s)(me)); /* invoke state handler s */
90 } while (t != (QHsmState)0);
92 if (me->evt.sig == (QSignal)0) { /* transition taken? */
93 QHsmState src = s; /* the source of the transition */
94 int8_t ip = (int8_t)(-1); /* transition entry path index */
96 path[0] = me->state; /* save the new state */
97 me->state = path[1]; /* restore the current state */
99 /* exit current state to the transition source src... */
100 for (s = path[1]; s != src; ) {
101 Q_SIG(me) = (QSignal)Q_EXIT_SIG;
102 t = (QHsmState)(*s)(me); /* find superstate of s */
103 if (t != (QHsmState)0) { /* exit action unhandled */
104 s = t; /* t points to superstate */
106 else { /* exit action handled */
107 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
108 s = (QHsmState)(*s)(me); /* find superstate of s */
112 t = path[0]; /* target of the transition */
120 AO_derived.super.state = state_2;
121 AO_derived.super.evt.sig = 2;
123 QHsm_dispatch((QHsm *)&AO_derived);
125 ASSERT(1); /*if we don't get here the regression test will timeout */