0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <ndrx_config.h>
0036 #include <ndrstandard.h>
0037 #include <ndebug.h>
0038 #include <exsm.h>
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 typedef struct
0049 {
0050 int state;
0051 char state_name[32];
0052 int (*func)(void *data);
0053 int flags;
0054 ndrx_sm_tran_t transitions[0];
0055 } ndrx_sm_state_handle_t;
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 exprivate ndrx_sm_state_handle_t * ndrx_sm_state_get(void *sm, int nr_tran, int state)
0069 {
0070 return (ndrx_sm_state_handle_t *)(
0071 (char *)sm + (sizeof(ndrx_sm_state_handle_t)+nr_tran*sizeof(ndrx_sm_tran_t))*state);
0072 }
0073
0074
0075
0076
0077
0078
0079 exprivate size_t ndrx_sm_state_size(int nr_tran)
0080 {
0081 return (sizeof(ndrx_sm_state_handle_t) + nr_tran*sizeof(ndrx_sm_tran_t));
0082 }
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 expublic int ndrx_sm_run(void *sm, int nr_tran, int entry_state, void *data, int log_topic)
0094 {
0095 int ret = EXSUCCEED;
0096 ndrx_sm_state_handle_t *cur = ndrx_sm_state_get(sm, nr_tran, entry_state);
0097
0098 while (NDRX_SM_ST_RETURN!=cur->state)
0099 {
0100 int i;
0101 int next_state = -1;
0102 int event = -1;
0103
0104
0105 event = cur->func(data);
0106
0107
0108 if (cur->flags & NDRX_SM_FLAGS_SCAN)
0109 {
0110 for (i=0; i<nr_tran; i++)
0111 {
0112 if (NDRX_SM_EV_EOF==cur->transitions[i].event)
0113 {
0114 break;
0115 }
0116 else if (cur->transitions[i].event == event)
0117 {
0118 break;
0119 }
0120 }
0121 }
0122 else if (cur->flags & NDRX_SM_FLAGS_INDEX)
0123 {
0124 if (event>=0 && event<nr_tran)
0125 {
0126 i = event;
0127 }
0128 else
0129 {
0130
0131 if (LOG_FACILITY_TP==log_topic)
0132 {
0133 TP_LOG(log_error, "sm: ERROR ! state %s (%d), event %d: "
0134 "no transition found!", cur->state_name, cur->state, event);
0135 }
0136 else
0137 {
0138 NDRX_LOG(log_error, "sm: ERROR ! state %s (%d), event %d: "
0139 "no transition found!", cur->state_name, cur->state, event);
0140 }
0141 userlog("sm: ERROR ! state %s (%d), event %d: "
0142 "no transition found!",cur->state_name, cur->state, event);
0143 EXFAIL_OUT(ret);
0144 }
0145 }
0146 else
0147 {
0148 if (LOG_FACILITY_TP==log_topic)
0149 {
0150 TP_LOG(log_error, "sm: ERROR ! machine not compiled (flags=%x)",
0151 cur->flags);
0152 }
0153 else
0154 {
0155 NDRX_LOG(log_error, "sm: ERROR ! machine not compiled (flags=%x)",
0156 cur->flags);
0157 }
0158 userlog("sm: ERROR ! machine not compiled (flags=%x)",
0159 cur->flags);
0160 EXFAIL_OUT(ret);
0161 }
0162
0163 if (NDRX_SM_EV_EOF==cur->transitions[i].event)
0164 {
0165 if (LOG_FACILITY_TP==log_topic)
0166 {
0167 TP_LOG(log_error, "sm: ERROR ! state %s (%d), event %d: "
0168 "no transition found!", cur->state_name, cur->state, event);
0169 }
0170 else
0171 {
0172 NDRX_LOG(log_error, "sm: ERROR ! state %s (%d), event %d: "
0173 "no transition found!", cur->state_name, cur->state, event);
0174 }
0175 userlog("sm: ERROR ! state %s (%d), event %d: "
0176 "no transition found!",cur->state_name, cur->state, event);
0177 EXFAIL_OUT(ret);
0178 }
0179 else if (cur->transitions[i].event == event)
0180 {
0181 if (LOG_FACILITY_TP==log_topic)
0182 {
0183 TP_LOG(log_debug , "sm: %s, event %s",
0184 cur->state_name, cur->transitions[i].event_name);
0185 }
0186 else
0187 {
0188 NDRX_LOG(log_debug , "sm: %s, event %s",
0189 cur->state_name, cur->transitions[i].event_name);
0190 }
0191 next_state = cur->transitions[i].next_state;
0192 }
0193
0194 if (NDRX_SM_ST_RETURN==next_state)
0195 {
0196 if (LOG_FACILITY_TP==log_topic)
0197 {
0198 TP_LOG(log_debug, "sm: return from %s, with ret=%d",
0199 cur->state_name, event);
0200 }
0201 else
0202 {
0203 NDRX_LOG(log_debug, "sm: return from %s, with ret=%d",
0204 cur->state_name, event);
0205 }
0206
0207 ret=event;
0208 goto out;
0209 }
0210 else if (NDRX_SM_ST_RETURN0==next_state)
0211 {
0212 if (LOG_FACILITY_TP==log_topic)
0213 {
0214 TP_LOG(log_debug, "sm: return from %s, with ev %d as ret=0",
0215 cur->state_name, event);
0216 }
0217 else
0218 {
0219 NDRX_LOG(log_debug, "sm: return from %s, with ev %d as ret=0",
0220 cur->state_name, event);
0221 }
0222
0223 ret=0;
0224 goto out;
0225 }
0226
0227 cur = ndrx_sm_state_get(sm, nr_tran, next_state);
0228 }
0229 out:
0230 return ret;
0231 }
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 expublic int ndrx_sm_comp(void *sm, int nr_state, int nr_tran, int last_state)
0253 {
0254 int i;
0255 int tran;
0256 int ret = EXSUCCEED;
0257 int got_eof;
0258 int in_range;
0259 size_t state_size = ndrx_sm_state_size(nr_tran);
0260 char tmp[ndrx_sm_state_size(nr_tran)*nr_state];
0261
0262
0263
0264
0265 got_eof=EXFALSE;
0266 for (i=0; i<nr_state; i++)
0267 {
0268 ndrx_sm_state_handle_t *cur;
0269 cur = ndrx_sm_state_get(sm, nr_tran, i);
0270
0271 if (got_eof)
0272 {
0273 cur->state=EXFAIL;
0274 }
0275 else if (cur->state==last_state)
0276 {
0277 got_eof=EXTRUE;
0278 }
0279 else if (cur->state >=nr_state)
0280 {
0281 NDRX_LOG(log_error, "sm: ERROR ! got state %d, but max allowed is %d!",
0282 cur->state, nr_state-1);
0283 EXFAIL_OUT(ret);
0284 }
0285 }
0286
0287 memcpy(tmp, sm, sizeof(tmp));
0288
0289
0290 got_eof=EXFALSE;
0291 for (i=0; i<nr_state; i++)
0292 {
0293 ndrx_sm_state_handle_t *cur;
0294 cur = ndrx_sm_state_get(sm, nr_tran, i);
0295 cur->state=i;
0296 cur->func=NULL;
0297 if (tran>0)
0298 {
0299 cur->transitions[0].event=NDRX_SM_EV_EOF;
0300 }
0301 }
0302
0303
0304 for (i=0; i<nr_state; i++)
0305 {
0306 ndrx_sm_state_handle_t *cur;
0307 ndrx_sm_state_handle_t *tmp_cur;
0308
0309 tmp_cur = ndrx_sm_state_get(tmp, nr_tran, i);
0310
0311 if (tmp_cur->state==EXFAIL)
0312 {
0313
0314 break;
0315 }
0316
0317
0318 cur = ndrx_sm_state_get(sm, nr_tran, tmp_cur->state);
0319
0320 memcpy(cur, tmp_cur, state_size);
0321 }
0322
0323
0324
0325 for (i=0; i<nr_state; i++)
0326 {
0327 ndrx_sm_state_handle_t *cur = ndrx_sm_state_get(sm, nr_tran, i);
0328
0329
0330
0331 if (cur->state != i)
0332 {
0333 NDRX_LOG(log_error, "sm: ERROR ! state %s (%d) is not in sequence!",
0334 cur->state_name, cur->state);
0335 EXFAIL_OUT(ret);
0336 }
0337
0338 got_eof=EXFALSE;
0339 in_range=EXTRUE;
0340
0341 for (tran=0; tran<nr_tran; tran++)
0342 {
0343 if (NDRX_SM_EV_EOF==cur->transitions[tran].event)
0344 {
0345
0346 got_eof=EXTRUE;
0347 break;
0348 }
0349 else if ( (cur->transitions[tran].next_state <0 ||
0350 cur->transitions[tran].next_state >nr_state-1) &&
0351 NDRX_SM_ST_RETURN!=cur->transitions[tran].next_state &&
0352 NDRX_SM_ST_RETURN0!=cur->transitions[tran].next_state
0353 )
0354 {
0355 NDRX_LOG(log_error, "sm: ERROR ! state %s (%d), event %s (%d): "
0356 "next state %d is out of range [%d..%d]!",
0357 cur->state_name, cur->state, cur->transitions[tran].event_name,
0358 cur->transitions[tran].event, cur->transitions[tran].next_state,
0359 0, nr_state-1);
0360 EXFAIL_OUT(ret);
0361 }
0362 else if (
0363 NDRX_SM_ST_RETURN!=cur->transitions[tran].next_state &&
0364 NDRX_SM_ST_RETURN0!=cur->transitions[tran].next_state &&
0365 NULL==ndrx_sm_state_get(sm, nr_tran, cur->transitions[tran].next_state)->func
0366 )
0367 {
0368 NDRX_LOG(log_error, "sm: ERROR ! state %s (%d), event %s (%d): "
0369 "next state %d is not used!",
0370 cur->state_name, cur->state, cur->transitions[tran].event_name,
0371 cur->transitions[tran].event, cur->transitions[tran].next_state);
0372 EXFAIL_OUT(ret);
0373 }
0374 else if (cur->transitions[tran].event<0 || cur->transitions[tran].event>=nr_tran)
0375 {
0376 in_range=EXFALSE;
0377 }
0378 }
0379
0380
0381 if (in_range)
0382 {
0383 ndrx_sm_tran_t tmp_trn[nr_tran];
0384 got_eof=EXFALSE;
0385
0386 memcpy(tmp_trn, cur->transitions, sizeof(tmp_trn));
0387
0388 cur->flags |= NDRX_SM_FLAGS_INDEX;
0389
0390 for (tran=0; tran<nr_tran; tran++)
0391 {
0392
0393 cur->transitions[tran].event = NDRX_SM_EV_EOF;
0394 }
0395 for (tran=0; tran<nr_tran; tran++)
0396 {
0397 if (NDRX_SM_EV_EOF==tmp_trn[tran].event)
0398 {
0399
0400 break;
0401 }
0402
0403 cur->transitions[tmp_trn[tran].event] = tmp_trn[tran];
0404 }
0405 }
0406 else
0407 {
0408 cur->flags |= NDRX_SM_FLAGS_SCAN;
0409 }
0410 }
0411
0412 out:
0413 return ret;
0414 }
0415
0416