|
QP/C
|
00001 /***************************************************************************** 00002 * Product: QEP/C 00003 * Last Updated for Version: 4.4.00 00004 * Date of the Last Update: Jan 21, 2012 00005 * 00006 * Q u a n t u m L e a P s 00007 * --------------------------- 00008 * innovating embedded systems 00009 * 00010 * Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved. 00011 * 00012 * This software may be distributed and modified under the terms of the GNU 00013 * General Public License version 2 (GPL) as published by the Free Software 00014 * Foundation and appearing in the file GPL.TXT included in the packaging of 00015 * this file. Please note that GPL Section 2[b] requires that all works based 00016 * on this software must also be made publicly available under the terms of 00017 * the GPL ("Copyleft"). 00018 * 00019 * Alternatively, this software may be distributed and modified under the 00020 * terms of Quantum Leaps commercial licenses, which expressly supersede 00021 * the GPL and are specifically designed for licensees interested in 00022 * retaining the proprietary status of their code. 00023 * 00024 * Contact information: 00025 * Quantum Leaps Web site: http://www.quantum-leaps.com 00026 * e-mail: info@quantum-leaps.com 00027 *****************************************************************************/ 00028 #include "qep_pkg.h" 00029 #include "qassert.h" 00030 00031 Q_DEFINE_THIS_MODULE("qhsm_dis") 00032 00033 00039 /*..........................................................................*/ 00040 void QHsm_dispatch(QHsm *me, QEvent const *e) { 00041 QStateHandler path[QEP_MAX_NEST_DEPTH_]; 00042 QStateHandler s; 00043 QStateHandler t; 00044 QState r; 00045 QS_CRIT_STAT_ 00046 00047 t = me->state; /* save the current state */ 00048 00049 QS_BEGIN_(QS_QEP_DISPATCH, QS_smObj_, me) 00050 QS_TIME_(); /* time stamp */ 00051 QS_SIG_(e->sig); /* the signal of the event */ 00052 QS_OBJ_(me); /* this state machine object */ 00053 QS_FUN_(t); /* the current state */ 00054 QS_END_() 00055 00056 do { /* process the event hierarchically... */ 00057 s = me->state; 00058 r = (*s)(me, e); /* invoke state handler s */ 00059 } while (r == Q_RET_SUPER); 00060 00061 if (r == Q_RET_TRAN) { /* transition taken? */ 00062 #ifdef Q_SPY 00063 QStateHandler src = s; /* save the transition source for tracing */ 00064 #endif 00065 int8_t ip = (int8_t)(-1); /* transition entry path index */ 00066 int8_t iq; /* helper transition entry path index */ 00067 00068 path[0] = me->state; /* save the target of the transition */ 00069 path[1] = t; 00070 00071 while (t != s) { /* exit current state to transition source s... */ 00072 if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {/*exit handled? */ 00073 QS_BEGIN_(QS_QEP_STATE_EXIT, QS_smObj_, me) 00074 QS_OBJ_(me); /* this state machine object */ 00075 QS_FUN_(t); /* the exited state */ 00076 QS_END_() 00077 00078 (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); /* find superstate of t */ 00079 } 00080 t = me->state; /* me->state holds the superstate */ 00081 } 00082 00083 t = path[0]; /* target of the transition */ 00084 00085 if (s == t) { /* (a) check source==target (transition to self) */ 00086 QEP_EXIT_(s) /* exit the source */ 00087 ip = (int8_t)0; /* enter the target */ 00088 } 00089 else { 00090 (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); /* superstate of target */ 00091 00092 t = me->state; 00093 if (s == t) { /* (b) check source==target->super */ 00094 ip = (int8_t)0; /* enter the target */ 00095 } 00096 else { 00097 (void)QEP_TRIG_(s, QEP_EMPTY_SIG_); /* superstate of src */ 00098 00099 /* (c) check source->super==target->super */ 00100 if (me->state == t) { 00101 QEP_EXIT_(s) /* exit the source */ 00102 ip = (int8_t)0; /* enter the target */ 00103 } 00104 else { 00105 /* (d) check source->super==target */ 00106 if (me->state == path[0]) { 00107 QEP_EXIT_(s) /* exit the source */ 00108 } 00109 else { /* (e) check rest of source==target->super->super.. 00110 * and store the entry path along the way 00111 */ 00112 iq = (int8_t)0; /* indicate that LCA not found */ 00113 ip = (int8_t)1; /* enter target and its superstate */ 00114 path[1] = t; /* save the superstate of target */ 00115 t = me->state; /* save source->super */ 00116 /* find target->super->super */ 00117 r = QEP_TRIG_(path[1], QEP_EMPTY_SIG_); 00118 while (r == Q_RET_SUPER) { 00119 ++ip; 00120 path[ip] = me->state; /* store the entry path */ 00121 if (me->state == s) { /* is it the source? */ 00122 iq = (int8_t)1; /* indicate that LCA found */ 00123 /* entry path must not overflow */ 00124 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); 00125 --ip; /* do not enter the source */ 00126 r = Q_RET_HANDLED; /* terminate the loop */ 00127 } 00128 else { /* it is not the source, keep going up */ 00129 r = QEP_TRIG_(me->state, QEP_EMPTY_SIG_); 00130 } 00131 } 00132 if (iq == (int8_t)0) { /* the LCA not found yet? */ 00133 00134 /* entry path must not overflow */ 00135 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); 00136 00137 QEP_EXIT_(s) /* exit the source */ 00138 00139 /* (f) check the rest of source->super 00140 * == target->super->super... 00141 */ 00142 iq = ip; 00143 r = Q_RET_IGNORED; /* indicate LCA NOT found */ 00144 do { 00145 if (t == path[iq]) { /* is this the LCA? */ 00146 r = Q_RET_HANDLED;/* indicate LCA found */ 00147 /*do not enter LCA*/ 00148 ip = (int8_t)(iq - (int8_t)1); 00149 iq = (int8_t)(-1);/* terminate the loop */ 00150 } 00151 else { 00152 --iq; /* try lower superstate of target */ 00153 } 00154 } while (iq >= (int8_t)0); 00155 00156 if (r != Q_RET_HANDLED) { /* LCA not found yet? */ 00157 /* (g) check each source->super->... 00158 * for each target->super... 00159 */ 00160 r = Q_RET_IGNORED; /* keep looping */ 00161 do { 00162 /* exit t unhandled? */ 00163 if (QEP_TRIG_(t, Q_EXIT_SIG) 00164 == Q_RET_HANDLED) 00165 { 00166 QS_BEGIN_(QS_QEP_STATE_EXIT, 00167 QS_smObj_, me) 00168 QS_OBJ_(me); 00169 QS_FUN_(t); 00170 QS_END_() 00171 00172 (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); 00173 } 00174 t = me->state; /* set to super of t */ 00175 iq = ip; 00176 do { 00177 if (t == path[iq]) {/* is this LCA? */ 00178 /* do not enter LCA */ 00179 ip = (int8_t)(iq - (int8_t)1); 00180 iq = (int8_t)(-1);/*break inner */ 00181 r = Q_RET_HANDLED;/*break outer */ 00182 } 00183 else { 00184 --iq; 00185 } 00186 } while (iq >= (int8_t)0); 00187 } while (r != Q_RET_HANDLED); 00188 } 00189 } 00190 } 00191 } 00192 } 00193 } 00194 /* retrace the entry path in reverse (desired) order... */ 00195 for (; ip >= (int8_t)0; --ip) { 00196 QEP_ENTER_(path[ip]) /* enter path[ip] */ 00197 } 00198 t = path[0]; /* stick the target into register */ 00199 me->state = t; /* update the current state */ 00200 00201 /* drill into the target hierarchy... */ 00202 while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN) { 00203 00204 QS_BEGIN_(QS_QEP_STATE_INIT, QS_smObj_, me) 00205 QS_OBJ_(me); /* this state machine object */ 00206 QS_FUN_(t); /* the source (pseudo)state */ 00207 QS_FUN_(me->state); /* the target of the transition */ 00208 QS_END_() 00209 00210 ip = (int8_t)0; 00211 path[0] = me->state; 00212 00213 (void)QEP_TRIG_(me->state, QEP_EMPTY_SIG_); /* find superstate */ 00214 00215 while (me->state != t) { 00216 ++ip; 00217 path[ip] = me->state; 00218 /* find superstate */ 00219 (void)QEP_TRIG_(me->state, QEP_EMPTY_SIG_); 00220 } 00221 me->state = path[0]; 00222 /* entry path must not overflow */ 00223 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); 00224 00225 do { /* retrace the entry path in reverse (correct) order... */ 00226 QEP_ENTER_(path[ip]) /* enter path[ip] */ 00227 --ip; 00228 } while (ip >= (int8_t)0); 00229 00230 t = path[0]; 00231 } 00232 00233 QS_BEGIN_(QS_QEP_TRAN, QS_smObj_, me) 00234 QS_TIME_(); /* time stamp */ 00235 QS_SIG_(e->sig); /* the signal of the event */ 00236 QS_OBJ_(me); /* this state machine object */ 00237 QS_FUN_(src); /* the source of the transition */ 00238 QS_FUN_(t); /* the new active state */ 00239 QS_END_() 00240 00241 } 00242 else { /* transition not taken */ 00243 #ifdef Q_SPY 00244 if (r == Q_RET_IGNORED) { /* event ignored? */ 00245 00246 QS_BEGIN_(QS_QEP_IGNORED, QS_smObj_, me) 00247 QS_TIME_(); /* time stamp */ 00248 QS_SIG_(e->sig); /* the signal of the event */ 00249 QS_OBJ_(me); /* this state machine object */ 00250 QS_FUN_(t); /* the current state */ 00251 QS_END_() 00252 00253 } 00254 else { /* event handled */ 00255 00256 QS_BEGIN_(QS_QEP_INTERN_TRAN, QS_smObj_, me) 00257 QS_TIME_(); /* time stamp */ 00258 QS_SIG_(e->sig); /* the signal of the event */ 00259 QS_OBJ_(me); /* this state machine object */ 00260 QS_FUN_(s); /* the state that handled the event */ 00261 QS_END_() 00262 00263 } 00264 #endif 00265 } 00266 me->state = t; /* set new state or restore the current state */ 00267 }
1.7.6.1