Imported Upstream version 2.9.0
[debian/cc1111] / support / regression / tests / bug1908493.c
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 #define Q_REENTRANT reentrant
11 #define Q_ASSERT
12 #define Q_SIG(me_) (((QFsm *)(me_))->evt.sig)
13 #define int8_t char
14 #define QEP_MAX_NEST_DEPTH 5
15
16 #define QEP_EMPTY_SIG 0
17
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 */
24 };
25
26 typedef int8_t QSignal;
27 typedef struct QEventTag {
28     QSignal sig;
29 } QEvent;
30
31 struct QFsmTag;
32 struct QHsmTag;
33
34 typedef void (*QState)(struct QFsmTag *me);
35 typedef QState (*QHsmState)(struct QHsmTag *me);
36
37 typedef QState QSTATE;
38
39 typedef struct QFsmTag {
40     QState state;
41     QEvent evt;
42 } QFsm;
43
44 typedef struct QHsmTag {
45     QHsmState state;
46     QEvent evt;
47 } QHsm;
48
49 typedef struct QHsmDerivedTag {
50     QHsm super;
51     char value;
52 } QHsmDerived;
53
54 QHsmDerived AO_derived;
55
56 QSTATE state_1(QHsmDerived *me) Q_REENTRANT
57 {
58     if (Q_SIG(me) == Q_INIT_SIG)
59         me->value = 3;
60
61     return (QSTATE)0;
62 }
63
64 QSTATE state_2(QHsmDerived *me) Q_REENTRANT
65 {
66     if (Q_SIG(me) == Q_USER_SIG)
67         return (QSTATE)state_1;
68
69     return (QSTATE)0;
70 }
71
72 void QHsm_dispatch(QHsm *me) Q_REENTRANT
73 {
74     QHsmState path[QEP_MAX_NEST_DEPTH];
75     QHsmState s;
76     QHsmState t = me->state;
77
78     path[1] = t;    /* save the current state in case a transition is taken */
79
80     do {                             /* process the event hierarchically... */
81         s = t;
82
83         /********************************************************************
84          *
85          *    The call which fails when s is copied from the stack frame
86          *
87          ********************************************************************/
88         t = (QHsmState)((*s)(me));                /* invoke state handler s */
89
90     } while (t != (QHsmState)0);
91
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 */
95
96         path[0] = me->state;                          /* save the new state */
97         me->state = path[1];                   /* restore the current state */
98
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 */
105             }
106             else {                                   /* exit action handled */
107                 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
108                 s = (QHsmState)(*s)(me);            /* find superstate of s */
109             }
110         }
111
112         t = path[0];                            /* target of the transition */
113
114     }
115 }
116
117 void
118 testBug (void)
119 {
120     AO_derived.super.state = state_2;
121     AO_derived.super.evt.sig = 2;
122
123     QHsm_dispatch((QHsm *)&AO_derived);
124
125     ASSERT(1);      /*if we don't get here the regression test will timeout */
126 }