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