]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/fsm/fsm.h
Merge branch 'libusb'
[eurobot/public.git] / src / fsm / fsm.h
1 /**
2  * @file fsm.h
3  * @author Tran Duy Khanh
4  * @author Michal Sojka
5  * @date 07/04/17
6  *
7  * @brief Finite State Machine
8  */
9
10 /* Copyright: (c) 2007 CTU Dragons
11  *            CTU FEE - Department of Control Engineering
12  * Contacts: Tran Duy Khanh <trandk1@fel.cvut.cz>
13  * License: GNU GPL v.2
14  */
15
16 /**
17 \defgroup fsm Finite State Machines
18
19 Finite state machines/automatons (FSM) are used to control various
20 parts of the %robot. 
21
22 Content:
23 - \ref fsm_general
24 - \ref state_functions
25 - \ref fsm_events
26 - \ref fsm_usage
27 - \ref subfsm
28
29 \section fsm_general Introduction
30
31 FSMs are used to write applications that need to react on events. In
32 the simples cases it is sufficient to write such applications only by
33 combinations of switch and if statements. In other cases when the
34 number of events is higher than a small number and the response to
35 events differs depending on many conditions, such approach is usually
36 error prone, since the code becomes complicated. This library provides
37 a framework which makes programming such applications more easy.
38
39 The fundamental entity in this library is FSM. Every FSM is defined by
40 structure ::robo_fsm and a set of state functions.  The state
41 functions are executed as a response to some events. The events can be
42 generated internally (see ::fsm_common_events), by another FSM or by
43 some other piece of code.  There is exactly one "current" state
44 function at a given time. The goal of the current state functions is
45 to react to events. The reaction to an event can be represented by an
46 arbitrary piece of code that does something useful. It is also
47 possible to change the current state (function) of FSM (so called
48 state transition). Having several state functions, it is possible to
49 react differently on the same events depending on what is the current
50 state.
51
52 Every FSM can be executed either in its dedicated threads or together
53 with other FSMs in a single thread. Which way is better for your
54 application depends on your needs. If the code in state functions may
55 take long time to execute and you need to react quickly to some
56 events, use the threaded FSMs and assign higher priority to threads
57 with real-time requirements and low priority to non-real-time threads
58 with long execution times.
59
60 On the other hand, having all FSMs running in a single thread may
61 simplify your application, because you do not have to deal with
62 concurrent execution. The price for this is, that response time to an
63 critical event may be too high.
64
65 It is also possible to have something in between the above two
66 approaches. You can have, for instance, real-time FSMs running in
67 their own high-priority threads and non-real-time FSMs, sharing a
68 single low-priority thread.
69
70 \section state_functions State Functions
71
72 The state function is a function taking a pointer to FSM structure as
73 an argument and returning an integer value. To make declaration of
74 state function easier, there is a macro FSM_STATE(). This macro
75 declares the state functions and also adds some code to conditionally
76 print debugging messages. Thanks to this macro, programmer can
77 concentrate on the real programming task and the complexity of
78 declaration is hidden.
79
80 The usual structure of a state function is one big switch
81 statement. The switch condition is the #FSM_EVENT macro, whose value
82 is the identifier of the event (see section \ref fsm_events) to be
83 handled. In the handling code you can execute whatever you want. If
84 there is some data associated with the event, it can be retrieved by
85 #FSM_EVENT_PTR or #FSM_EVENT_INT. Additionally, FSM infrastructure
86 provides some useful functions and macros. To work with time, you can
87 use FSM_TIMER(). To execute transition to another state, use
88 FSM_TRANSITION() or SUBFSM_TRANSITION() (see \ref subfsm). To send an
89 event to another FSM, use FSM_SIGNAL().
90
91 An example state function, whose only function is to wait 1 second
92 before entering \c another_state is shown here:
93
94 \code
95 FSM_STATE(my_state) {
96   switch (FSM_EVENT) {
97     case EV_ENTRY:
98       FSM_TIMER(1000);
99       break;
100     case EV_TIMER:
101       FSM_TRANSITION(another_state);
102       break;
103   }
104 }
105 \endcode
106
107 For the above to work, it is important to declare the macro @c FSM_<id>
108 before including header with event definition and fsm.h. See the note in \ref
109 fsm_events section. This means, that state functions for different
110 FSMs have to be declared in separate files.
111
112 \section fsm_events Events
113
114 An event is identified by an event identifier. This is a string
115 usually starting with @c EV_ prefix. Some data can be associated with
116 events. This data can be a pointer or integer typecasted to pointer.
117
118 Every FSM can handle so called common events (e.g. #EV_ENTRY,
119 see ::fsm_common_events) and also some additional events specific to
120 the FSM. Those additional events are declared only for a given FSM and
121 can be sent to that FSM from another place by the FSM_SIGNAL()
122 macro. To avid programming errors we have three requirements for
123 working with events:
124
125 -# It is not possible to send an event to FSM, which didn't declare
126    it. This situation should produce compile-time error.
127 -# In a state function, an attempt to handle an event declared for
128    another FSM should also produce compile-time error.
129 -# If some event, which can be handled by the FSM, is omitted in the switch
130    command, we want to be warned.
131
132 These requirements are hard to achieve in plain C. Therefore,
133 additional events for FSMs are declared as a data structure in Python
134 and there is a Python script eventgen.py, which converts this definition to .h a
135 .c files.
136
137 The event definition is a Python dictionary (associative array) called
138 @c events. Keys to this dictionary are the lowercase identifiers of
139 FSM. The value is another dictionary, which defines the events for
140 that FSM. The key is the event identifier and value is a comment. In
141 the example below, event for two FSMs called "tested" and "tester" are
142 defined. The "tested" FSM can handle additional events EV_PING and EV_OTHER and
143 "tester" FSM handles "EV_PONG".
144
145 \include example_ev.py
146
147 The script, which generates .c and .h source code is called
148 eventgen.py. In .h, there is one enum for each FSM with all events
149 this FSM can handle. The members of enums are not directly event identifiers,
150 but some internal identifiers starting with double underscore
151 (__). You should never use these identifiers directly in your
152 application. Then, there are macros, which translates the event
153 identifiers to internal event identifiers. Thanks to this, the above
154 requirements 1. and 2. are fulfilled. Requirement no. 3 is also
155 fulfilled because recent versions of GCC warns if some enum member is
156 not handled in switch statement (unless you use @c default statement).
157
158 @note You have to always include the generated header file with events before fsm.h.
159 If you do not do so, an error is generated.
160
161 @note In the source, where you define your state function, you have to
162 define macro @c FSM_&lt;id&gt;, where @c &lt;id&gt; is uppercase identifier of FSM
163 as defined in event definition. If you do not do so, you get a compilation error
164 on definition of state function. GCC generates this error message:
165 @verbatim
166 error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘FSM_XXX_not_defined’
167 @endverbatim
168
169 \section fsm_usage Usage
170
171 To use FSMs provided by this library in your application, you need to
172 -# define additional event for your automatons (see section \ref fsm_events),
173 -# define state functions for your automatons (see section \ref
174 state_functions) and
175 -# start execution of the automatons (every FSM executes in its own thread).
176
177 Definition of state functions usually starts with lines like this:
178 @code
179 #define FSM_SOME_NAME // define which FSM state functions are to be declared here
180 #include "events.h"   // include definition of additional events (generated from events.py)
181 #include <fsm.h>
182
183 FSM_STATE(test_state1) {
184         ...
185 }
186 @endcode
187
188 Initialization of an automaton looks like:
189 @code
190 struct robo_fsm fsm;
191 struct fsm_main_loop loop;
192 fsm_main_loop_init(&loop);
193 fsm_init(&fsm, "id_for_debug_massages", &loop);
194 fsm.state = &fsm_state_test_state1;       // Initial state of the automaton
195 @endcode
196
197 To start the FSM in its own thread do:
198 @code
199 if (fsm_start(&loop, NULL) != 0) {
200         perror("fsm_start");
201         exit(1);
202 }
203 @endcode
204 To start it in the current thread do:
205 @code
206 fsm_main_loop(&loop);
207 @endcode
208
209 \section subfsm Sub-Automatons
210
211 Sometimes, it may be useful to enter a state of sub-automaton and
212 return back to current state after this sub-automaton finishes its
213 task. You can enter the sub-automaton state by calling
214 SUBFSM_TRANSITION(). When the sub-automaton is done, call from some of
215 its state functions SUBFSM_RET(). Then the original state function
216 will be called with ::EV_RETURN.
217
218 Sub-automaton calling can be nested up to the level of 10.
219
220  */
221
222
223
224 #ifndef __robofsm__
225 #define __robofsm__
226
227 #include <stdlib.h>
228 #include <stdbool.h>
229 #include <pthread.h>
230 #include <semaphore.h>
231 #include <sys/time.h>
232 #include <errno.h>
233 #include "fsm_common_events.h"
234 #include <stdio.h>
235
236 /**
237  * Type for FSM events
238  * @ingroup fsm
239  */
240 typedef struct fsm_event {
241         int id;                 /** Event identifier (e.g. EV_TIMER) */
242         void *data;             /** Any data sent together with the event */
243 } fsm_event;
244
245 #ifndef __FSM_ALIASES_DEFINED
246 #define EV_NOEVENT        __COMMON_EV_NOEVENT
247 #define EV_ENTRY          __COMMON_EV_ENTRY
248 #define EV_EXIT           __COMMON_EV_EXIT
249 #define EV_RETURN         __COMMON_EV_RETURN
250 #define EV_TIMER          __COMMON_EV_TIMER
251 #endif
252
253 struct robo_fsm;
254
255 struct fsm_main_loop {
256         pthread_t threadid;     /**< Thread running the main loop or NULL. */
257         struct robo_fsm *fsm; /**< List of FSMs handled by this loop */
258
259         /** Main loop waits on this semaphore while it waits for an event. */
260         sem_t event_sent;
261         /** Pointer to FSM whose timer expires first or NULL on no
262          * timer is active. */
263         struct robo_fsm *first;
264         struct timespec now;    /**< Time when an event occurred */
265 };
266
267 /** Event handler function for FSM.
268  * @ingroup fsm
269  */
270 typedef int (*robo_fsm_state_t)(struct robo_fsm *fsm);
271
272 #define FSM_EVENT_QUEUE_LEN 10
273
274 /** Set on event queue overrun, never zeroed. */
275 #define FSM_FLAG_EVENT_LOST     0x01
276 /** Set by fsm_exit() */
277 #define FSM_FLAG_FINISH         0x02
278
279 /** Structure describing FSM.
280  * @ingroup fsm
281  */
282 struct robo_fsm {
283         struct robo_fsm *next;
284         /** Main loop, which dispatches events for this FSM. */
285         struct fsm_main_loop *loop;
286         unsigned flags;
287         pthread_mutex_t send_mutex;
288          /** Ring-buffer for incomming events */
289         struct fsm_event events[FSM_EVENT_QUEUE_LEN];
290         /** Index in the @a events of the next event to be processed.  */
291         unsigned ev_head;       
292         /** Index in the @a events where to put events for this
293          * message. Protected by @a send_mutex */
294         unsigned ev_tail;   
295
296         struct timespec timer;  /**< Time of next timer expiration */
297
298         /** Pointer to current state function. This function is called
299          * when an event occurs. */
300         robo_fsm_state_t state;
301         const char *state_name;                  /**< Name of the current state  */
302         robo_fsm_state_t last_state; /**< Pointer to previous state function */
303         /** Stack of sub-automaton states for use by FCALL() and SUBFSM_TRANSITION(). */
304         const char *last_state_name;             /**< Name of the last state  */
305         robo_fsm_state_t fnc_stack[10];
306         /** Pointer to the top of fnc_stack */
307         robo_fsm_state_t *fnc_sp;
308         int debug_states;       /**< Whether to print debug messages on state transitions. */
309         char *debug_name;       /**< The name of automaton (printed in debug messages) */
310         /**
311          * Pointer to transition callback function. This function is
312          * called whenever fsm changes state. This callback can be
313          * used to track/debug the state of FSM. @c fsm->state_name
314          * will contain the name of current state, @c fsm->last_state_name
315          * the name of last state.
316          */
317         void (*transition_callback)(struct robo_fsm *fsm);
318 };      /* robo_fsm */
319
320 #ifdef __cplusplus
321 extern "C" {
322 #endif
323
324 void fsm_main_loop_init(struct fsm_main_loop *loop);
325 void fsm_init(struct robo_fsm *fsm, char *debug_name, struct fsm_main_loop *loop);
326 int fsm_start(struct fsm_main_loop *loop, pthread_attr_t *attr);
327 void fsm_exit(struct robo_fsm *fsm);
328 void fsm_destroy(struct robo_fsm *fsm);
329 void fsm_main_loop(struct fsm_main_loop *loop);
330 void __fsm_timespec_add_ms(struct timespec *ts, struct timespec *now, long ms);
331 void __fsm_timespec_invalidate(struct timespec *ts);
332 int __fsm_timespec_cmp(struct timespec *ts1, struct timespec *ts2);
333
334
335
336 /* FSM (Finite State Machine) */
337 /* do nothing */
338 int fsm_nop_state(struct robo_fsm *fsm);
339
340 /**
341  * Returns string with the name of event submitted as parameter.
342  * @param ev Indetifier of the event
343  * @return The name of event or "undefined event!!!" if the @c ev
344  * doesn't refer to a valid event.
345  *
346  * @ingroup fsm
347  */
348 const char *fsm_event_str(fsm_event ev);
349 const char *fsm_common_event_str(fsm_event ev);
350
351 /** \name Return codes of state functions */
352 //@{
353 /** After return, FSM thread starts waiting for the new event. */
354 #define RC_WAIT         0
355 /** After return, current state function (fnc_act) will be immediately
356  * called again. Used by FSM_TRANSITION(). */
357 #define RC_PROC         1
358 //@}
359
360 #define FSM_WAIT_FOREVER -1l
361
362 static inline void fsm_set_flags(struct robo_fsm *fsm, int flag_mask)
363 {
364         __sync_fetch_and_or(&fsm->flags, flag_mask);
365 }
366
367  static inline void __fsm_signal(struct robo_fsm *fsm, fsm_event event,
368                                  bool sem)
369 {
370         unsigned new_tail;
371         pthread_mutex_lock(&fsm->send_mutex);
372         fsm->events[fsm->ev_tail] = event;
373         new_tail = fsm->ev_tail + 1;
374         if (new_tail >= FSM_EVENT_QUEUE_LEN) 
375                 new_tail = 0;
376         
377         if (new_tail != fsm->ev_head) {
378                 fsm->ev_tail = new_tail;
379                 if (sem && fsm->loop)
380                         sem_post(&fsm->loop->event_sent);
381         } else {
382                 fsm_set_flags(fsm, FSM_FLAG_EVENT_LOST);
383                 fprintf(stderr, "fsm %s: Event lost\n", fsm->debug_name);
384         }
385         pthread_mutex_unlock(&fsm->send_mutex);
386 }
387
388 /**
389  * Sends an event to another FSM, which may run  in another
390  * thread. Event sending is asynchronous, but each FSM has a buffer for
391  * several events. If this buffer is full, @a event_lost flag is set
392  * and the event is lost. This should never happen in a carefully
393  * designed application.
394  *
395  * @note This macro ensures that it is not possible to send an event
396  * to other FSM than the one for which it was declared. If you get
397  * compilation error, that @c __<FSM_ID>_<EVENT_ID> is not declared,
398  * it means the recipient doesn't handle this event.
399  *
400  * @ingroup fsm
401  * @param fsm_id Event recipient's ID.
402  * @param event Event ID to send.
403  * @param data Any data (pointer or typecasted int) sent together with
404  *             the event.
405  */
406 #define FSM_SIGNAL(fsm_id, event, data)                                   \
407         do {                                                              \
408                 fsm_event e = {__##fsm_id##_##event, data};               \
409                 __fsm_signal(FSM_GET_BY_ID(fsm_id), e, true);             \
410         } while(0)
411
412 /**
413  * \def FSM_GET_BY_ID(fsm_id)
414  * 
415  * Returns pointer to struct ::fsm identified by the id. This macro
416  * should be defined by the application, which uses fsm.h. 
417  * 
418  * @param fsm_id FSM indentifier. This is the uppercase variant of the
419  * string, which defines the FSM in definition of events in python
420  * source.
421  *
422  * @ingroup fsm
423  */
424
425 #define DBG_STATE()     DBG_FSM_STATE(__FUNCTION__)
426 #define DBG_FSM_STATE(name)     do { if (fsm->debug_states) printf("fsm %s: %s(%s)\n", fsm->debug_name, name, fsm_event_str(fsm->events[fsm->ev_head])); } while(0)
427 /**
428  * Prints current event in a human readable form.
429  * @ingroup fsm
430  */
431 #define DBG_PRINT_EVENT(msg)    printf("fsm %s %s %s: %s\n", fsm->debug_name, fsm->state_name, fsm_event_str(fsm->events[fsm->ev_head]), msg)
432
433 #ifdef __cplusplus
434 }
435 #endif
436
437 static inline void call_transition_callback(struct robo_fsm *fsm)
438 {
439         if (fsm->transition_callback != NULL &&
440             (fsm->last_state != (fsm)->state) &&
441             (fsm->events[fsm->ev_head].id == EV_ENTRY || /* FIXME: Is this line correct? */
442              fsm->events[fsm->ev_head].id == EV_RETURN)) {
443                 fsm->transition_callback(fsm);
444         }
445 }
446
447 /**********************/
448 /* High level FSM API */
449 /**********************/
450
451 /**
452  * Specifies state function visibility.
453  *
454  * If this macro is redefined from "" (empty) to static, then the
455  * state functions are declared as static.
456  */
457 #define FSM_STATE_VISIBILITY
458
459 #define ___fsm_func_name(fsm, state, suf) fsm_state_##fsm##_##state##suf
460 #define __fsm_func_name(fsm, state, suf) ___fsm_func_name(fsm, state, suf)
461
462 /**
463  * Defines a state function for finite state machine. This function is
464  * called by FSM framework whenever some event occurs. The event can
465  * be read by using ::FSM_EVENT macro. In the function body, other @a
466  * FSM_xxx macros can be used to invoke state transition or set
467  * the timer. When no state transition is invoked, FSM waits
468  * for the next event, after the function returns. Then, after another
469  * event occurs, this state function is called again with that event.
470  *
471  * @note The body of state function is declared as void inline
472  * function. This function is called from state function stub, which
473  * contains debugging macros.
474  *
475  * The actual name of the function stub is @c fsm_state_<name> and the
476  * name of inline implementation is @c fsm_state_<name>_impl.
477  *
478  * @param name Name of the state.
479  * @ingroup fsm
480  */
481 #ifdef __FSM_NAME
482 #define FSM_STATE(name)                                                 \
483         static inline void __fsm_func_name(__FSM_NAME, name, _impl)(struct robo_fsm *fsm, int *__ret); \
484         FSM_STATE_VISIBILITY int __fsm_func_name(__FSM_NAME, name,)(struct robo_fsm *fsm) { \
485                 int ret=RC_WAIT;                                        \
486                 DBG_FSM_STATE(#name);                                   \
487                 fsm->state_name = #name;                                \
488                 call_transition_callback(fsm);                          \
489                 __fsm_func_name(__FSM_NAME, name, _impl)(fsm, &ret);    \
490                 return ret;                                             \
491         }                                                               \
492         static inline void __fsm_func_name(__FSM_NAME, name, _impl)(struct robo_fsm *fsm, int *__ret)
493 #else
494 #define FSM_STATE(name) error_FSM_XXX_not_defined
495 #endif
496 /**
497  * Declares a prototype of state function defined later.
498  * @ingroup fsm
499  * @param name Name of state function.
500  */
501 #ifdef __FSM_NAME
502 #define FSM_STATE_DECL(name) \
503 FSM_STATE_VISIBILITY int __fsm_func_name(__FSM_NAME, name,)(struct robo_fsm *fsm)
504 #else
505 #define FSM_STATE_DECL(name) error_FSM_XXX_not_defined
506 #endif
507
508 /**
509  * Declares a prototype of state function of given FSM. This can be
510  * used to declare state function in header files (of other .c files)
511  * that the one with the state functions itself
512  * 
513  * @ingroup fsm
514  * @param fsm_name Name of FSM
515  * @param name Name of state function.
516  */
517 #define FSM_STATE_FULL_DECL(fsm_name, name)                     \
518 int __fsm_func_name(fsm_name, name,)(struct robo_fsm *fsm)
519
520 /**
521  * Sets FSM's one-shot timer. After the specified number of
522  * milliseconds elapses, ::EV_TIMER is generated, unless
523  * FSM_TIMER_STOP() is used. The timer is automatically stopped on
524  * every trnasition.
525  *
526  * @param ms Time to timer expiration in milliseconds.
527  * @ingroup fsm
528  */
529 #define FSM_TIMER(ms) \
530         if (FSM_EVENT != EV_EXIT) {                                     \
531                 __fsm_timespec_add_ms(&fsm->timer, &fsm->loop->now, (ms)); \
532                 if (!fsm->loop->first ||                                \
533                     __fsm_timespec_cmp(&fsm->timer,                     \
534                                        &fsm->loop->first->timer) == -1) { \
535                         fsm->loop->first = fsm;                         \
536                 }                                                       \
537         }
538
539 /**
540  * Stops the timer.
541  * @ingroup fsm
542  */
543 #define FSM_TIMER_STOP() __fsm_timer_stop(fsm)
544
545 void __fsm_timer_stop(struct robo_fsm *);
546
547 #ifndef __FSM_EVENT_ENUM
548 /* This macro is normally declared in automatically generated event
549  * header file. If fsm.h is included from other files, we fall back to
550  * fsm_common_events. If you get warning: "__FSM_EVENT_ENUM"
551  * redefined, it means that FSM_xxx definition of event is included
552  * after fsm.h, which is not correct. */
553 #define __FSM_EVENT_ENUM enum fsm_common_events
554 #endif
555 /**
556  * Value of current event in state functions.
557  * @ingroup fsm
558  */
559 #define FSM_EVENT ((__FSM_EVENT_ENUM)(fsm->events[fsm->ev_head].id))
560
561 /**
562  * Value of the pointer sent together with the event.
563  * @ingroup fsm
564  */
565 #define FSM_EVENT_PTR (fsm->events[fsm->ev_head].data)
566
567 /**
568  * Value of the integer data sent together with the event.
569  * @ingroup fsm
570  */
571 #define FSM_EVENT_INT ((long int)(fsm->events[fsm->ev_head].data))
572
573 /**
574  * Sets current state to @c next. The state is not changed
575  * immediately. The rest of current state function finishes its
576  * execution and then, if @c next is not the current state, the
577  * current state function is called again with ::EV_EXIT
578  * event. Finally a call to the @c next state function (even if it is
579  * the same as current) is executed with ::EV_ENTRY as event.
580  *
581  * @param next Next state.
582  * @ingroup fsm
583  */
584 #ifdef __FSM_NAME
585 #define FSM_TRANSITION(next)                                            \
586         do {                                                            \
587                 if (fsm->events[fsm->ev_head].id != EV_EXIT) {          \
588                         fsm_event e = {EV_ENTRY, NULL};                 \
589                         fsm->last_state = fsm->state;                   \
590                         fsm->last_state_name = fsm->state_name;         \
591                         fsm->state = &__fsm_func_name(__FSM_NAME, next,); \
592                         fsm->events[fsm->ev_head] = e;                  \
593                         *__ret=RC_PROC;                                 \
594                 }                                                       \
595         } while(0)
596 #else
597 #define FSM_TRANSITION(next) error_FSM_XXX_not_defined
598 #endif
599
600 /**
601  * Invoke state transition to sub-FSM. The behaviour is almost the
602  * same as of FSM_TRANSITION(), but whenever the sub-FSM returns (see
603  * ::SUBFSM_RET), the current state function is executed with
604  * ::EV_RETURN as event. Moreover, the current state function is not
605  * called with ::EV_EXIT before the transtition.
606  *
607  * @param substate Initial state of sub-FSM.
608  * @param data Data passed to the sub-FSM.
609  * @ingroup fsm
610  */
611 #ifdef __FSM_NAME
612 #define SUBFSM_TRANSITION(substate, data)                               \
613         do {                                                            \
614                 if (fsm->events[fsm->ev_head].id != EV_EXIT) {          \
615                         fsm_event e = {EV_ENTRY, data};                 \
616                         *(fsm->fnc_sp++) = fsm->state;                  \
617                         fsm->last_state = fsm->state;                   \
618                         fsm->last_state_name = fsm->state_name;         \
619                         fsm->state = &__fsm_func_name(__FSM_NAME, substate,); \
620                         fsm->events[fsm->ev_head] = e;                  \
621                         *__ret = RC_PROC;                               \
622                 }                                                       \
623         } while(0)
624 #else
625 #define SUBFSM_TRANSITION(substate, data) error_FSM_XXX_not_defined
626 #endif
627 /**
628  * Return from sub-FSM. ::EV_EXIT is executed for the current state
629  * and ::EV_RETURN for the state where it is returning.
630  *
631  * @param data Data returned back to the caller
632  * @ingroup fsm
633  */
634 #define SUBFSM_RET(data)                                                \
635         do {                                                            \
636                 if (fsm->events[fsm->ev_head].id != EV_EXIT) {          \
637                         fsm_event e = {EV_RETURN, data};                \
638                         fsm->last_state = fsm->state;                   \
639                         fsm->last_state_name = fsm->state_name;         \
640                         fsm->state = *(--fsm->fnc_sp);                  \
641                         fsm->events[fsm->ev_head] = e;                  \
642                         *__ret = RC_PROC;                               \
643                 }                                                       \
644         } while(0)
645
646 #endif  /* __robofsm__ */