1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
/* Bug 1908493
* Bug test contains code fragments from qpnano framework,
* Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
* and released under the GPL
* See www.quantum-leaps.com/downloads/index.htm#QPN
*/
#include <testfwk.h>
#define Q_REENTRANT reentrant
#define Q_ASSERT
#define Q_SIG(me_) (((QFsm *)(me_))->evt.sig)
#define int8_t char
#define QEP_MAX_NEST_DEPTH 5
#define QEP_EMPTY_SIG 0
enum QReservedSignals {
Q_ENTRY_SIG = 1, /**< signal for coding entry actions */
Q_EXIT_SIG, /**< signal for coding exit actions */
Q_INIT_SIG, /**< signal for coding nested initial transitions */
Q_TIMEOUT_SIG, /**< signal used by time events */
Q_USER_SIG /**< first signal that can be used in user applications */
};
typedef int8_t QSignal;
typedef struct QEventTag {
QSignal sig;
} QEvent;
struct QFsmTag;
struct QHsmTag;
typedef void (*QState)(struct QFsmTag *me);
typedef QState (*QHsmState)(struct QHsmTag *me);
typedef QState QSTATE;
typedef struct QFsmTag {
QState state;
QEvent evt;
} QFsm;
typedef struct QHsmTag {
QHsmState state;
QEvent evt;
} QHsm;
typedef struct QHsmDerivedTag {
QHsm super;
char value;
} QHsmDerived;
QHsmDerived AO_derived;
QSTATE state_1(QHsmDerived *me) Q_REENTRANT
{
if (Q_SIG(me) == Q_INIT_SIG)
me->value = 3;
return (QSTATE)0;
}
QSTATE state_2(QHsmDerived *me) Q_REENTRANT
{
if (Q_SIG(me) == Q_USER_SIG)
return (QSTATE)state_1;
return (QSTATE)0;
}
void QHsm_dispatch(QHsm *me) Q_REENTRANT
{
QHsmState path[QEP_MAX_NEST_DEPTH];
QHsmState s;
QHsmState t = me->state;
path[1] = t; /* save the current state in case a transition is taken */
do { /* process the event hierarchically... */
s = t;
/********************************************************************
*
* The call which fails when s is copied from the stack frame
*
********************************************************************/
t = (QHsmState)((*s)(me)); /* invoke state handler s */
} while (t != (QHsmState)0);
if (me->evt.sig == (QSignal)0) { /* transition taken? */
QHsmState src = s; /* the source of the transition */
int8_t ip = (int8_t)(-1); /* transition entry path index */
path[0] = me->state; /* save the new state */
me->state = path[1]; /* restore the current state */
/* exit current state to the transition source src... */
for (s = path[1]; s != src; ) {
Q_SIG(me) = (QSignal)Q_EXIT_SIG;
t = (QHsmState)(*s)(me); /* find superstate of s */
if (t != (QHsmState)0) { /* exit action unhandled */
s = t; /* t points to superstate */
}
else { /* exit action handled */
Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
s = (QHsmState)(*s)(me); /* find superstate of s */
}
}
t = path[0]; /* target of the transition */
}
}
void
testBug (void)
{
AO_derived.super.state = state_2;
AO_derived.super.evt.sig = 2;
QHsm_dispatch((QHsm *)&AO_derived);
ASSERT(1); /*if we don't get here the regression test will timeout */
}
|