home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gwm18a.zip / wl_fsm.c < prev    next >
C/C++ Source or Header  |  1995-07-03  |  9KB  |  394 lines

  1. /* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT
  2.  * Copyright 1989 Massachusetts Institute of Technology
  3.  */
  4. /*********************\
  5. *               *
  6. *  WOOL_OBJECT: Fsm  *
  7. *  BODY              *
  8. *               *
  9. \*********************/
  10.  
  11. #include "EXTERN.h"
  12. #include <stdio.h>
  13. #include <assert.h>
  14. #include "wool.h"
  15. #include "wl_number.h"
  16. #include "wl_atom.h"
  17. #include "wl_list.h"
  18. #include "wl_func.h"
  19. #include "gwm.h"
  20. #include "wl_event.h"
  21. #include "INTERN.h"
  22. #include "wl_fsm.h"
  23.  
  24. WOOL_FsmState WLFsmState_copy();
  25. WOOL_FsmState WLState_fp();
  26. WOOL_StateArc WLArc_fp();
  27.  
  28. #define SAME_STATE  ((WOOL_Atom) -1)
  29.  
  30. /*
  31.  * Constructor: wool_fsm_make callable from wool
  32.  */
  33.  
  34. WOOL_Fsm
  35. wool_fsm_make(argc, argv)
  36. int    argc;
  37. WOOL_FsmState *argv;
  38. {
  39.     WOOL_Fsm        fsm;
  40.     int             i;
  41.  
  42.     for (i = 0; i < argc; i++) /* check args are all states */
  43.     must_be(WLFsmState, argv[i], i);
  44.     fsm = (WOOL_Fsm) Malloc(sizeof(struct _WOOL_Fsm) + Max(0,argc - 1) *
  45.                 sizeof(WOOL_OBJECT));
  46.     zrt_put(fsm);
  47.     fsm -> type = WLFsm;
  48.     fsm -> mask = 0;
  49.     fsm -> user_mask = 0;
  50.     fsm -> states_size = argc;
  51.     for (i = 0; i < argc; i++) {
  52.     fsm -> mask |= argv[i] -> mask;
  53.     fsm -> user_mask |= argv[i] -> user_mask;
  54.     increase_reference(fsm -> states[i] = WLFsmState_copy(argv[i]));
  55.     }
  56.     WLFsm_fix(fsm, argc, argv);
  57.     return fsm;
  58. }
  59.  
  60. /*
  61.  * fixes the states to go to in the fsm
  62.  */
  63.  
  64. WLFsm_fix(fsm, argc, argv)
  65. WOOL_Fsm    fsm;
  66. int        argc;
  67. WOOL_FsmState   argv[];
  68. {
  69.     int    nstate, narc, i;
  70.  
  71.     for (nstate = 0; nstate < fsm -> states_size; nstate++)
  72.     for (narc = 0; narc < fsm -> states[nstate] -> arcs_size; narc++)
  73.         if (fsm -> states[nstate] -> arcs[narc] -> state != SAME_STATE) {
  74.         for (i = 0; i < argc; i++)
  75.             if (fsm -> states[nstate] -> arcs[narc] -> state -> c_val
  76.             == (WOOL_OBJECT) ((argv[i]) -> copy_of)) {
  77.             fsm -> states[nstate] -> arcs[narc] -> state =
  78.                 (WOOL_Atom) i;
  79.             break;
  80.             }
  81.         if (i == argc)
  82.             wool_error("State %s not found!", fsm -> states[nstate]
  83.                    -> arcs[narc] -> state -> p_name);
  84.         }
  85. }
  86.  
  87. /*
  88.  * WLFsm_print prints any object of this package.
  89.  */
  90.  
  91. WOOL_OBJECT 
  92. WLFsm_print(obj)
  93. WOOL_Fsm     obj;
  94. {
  95.     wool_printf("{%s", WOOL_TYPE_P_NAME(obj -> type));
  96.     wool_printf(" 0x%x}", obj);
  97.     return (WOOL_OBJECT) obj;
  98. }
  99.  
  100. #ifdef DEBUG
  101. WOOL_Fsm
  102. WLFsm_fp(obj)
  103.     WOOL_Fsm     obj;
  104. {
  105.     int nstate;
  106.  
  107.     wool_printf("{%s", WOOL_TYPE_P_NAME(obj -> type));
  108.     wool_printf(" 0x%x:\n", obj);
  109.     for (nstate = 0; nstate < obj -> states_size; nstate++) {
  110.     wool_printf("State %d:\n", nstate);
  111.     WLState_fp(obj->states[nstate]);
  112.     }
  113.     wool_printf("}\n");
  114.     return obj;
  115. }
  116.  
  117. WOOL_FsmState
  118. WLState_fp(obj)
  119. WOOL_FsmState obj;
  120. {
  121.     int narc;
  122.     for (narc = 0; narc < obj-> arcs_size; narc++) {
  123.     wool_puts(" * ");
  124.     WLArc_fp(obj->arcs[narc]);
  125.     wool_puts("\n");
  126.     }
  127.     return obj;
  128. }
  129.  
  130. WOOL_StateArc
  131. WLArc_fp(obj)
  132. WOOL_StateArc obj;
  133. {
  134.     wool_print(obj->event);
  135.     wool_puts(" ");
  136.     wool_print(obj->action);
  137.     return obj;
  138. }
  139.  
  140. #endif /*DEBUG*/
  141.  
  142.  
  143. /* the main routine:
  144.  * check the incoming event against all transitions of the current
  145.  * state of the fsm, and triggers the action if necessary
  146.  */
  147.  
  148. WOOL_OBJECT
  149. WLFsm_action(fsm, wob, evt)
  150. WOOL_Fsm    fsm;
  151. Wob             wob;
  152. Event           evt;
  153. {
  154.     int             i;
  155.     WOOL_FsmState state;
  156.     WOOL_StateArc arc;
  157.     WOOL_List       l;
  158.     int             local_zrt_size = zrt_size;
  159.  
  160.     TargetWob = wob;
  161.     GWM_invalid_context = 1;
  162.     state = fsm -> states[wob -> curstate];
  163.     for (i = 0; i < state -> arcs_size; i++) {
  164.     arc = state -> arcs[i];
  165.     ASSERT(arc -> event -> match);
  166.     if (evt -> type == arc -> event -> x_type &&
  167.         ((*(arc -> event -> match)) (arc -> event, evt))) {
  168.  
  169.         TraceDo('f',
  170.             GWM_prettyprint_fsm_event(wob, evt, "MATCH",
  171.                           wob -> curstate,
  172.                           arc -> state));
  173.         if (l = arc -> action) {
  174.         save_wool_error_resume_point();
  175.         if (GWM_invalid_context)
  176.             SetTarget(wob);
  177.         TriggeringEvent = evt;
  178.         if (set_wool_error_resume_point()) {
  179.         } else {
  180.             WOOL_send(WOOL_execute, (*(l -> list)), (*(l -> list), l));
  181.             zrt_gc(local_zrt_size);
  182.         }
  183.         restore_wool_error_resume_point();   
  184.         }
  185.         
  186.         if (arc -> event -> release)
  187.         (*(arc -> event -> release)) (arc -> event, evt);
  188.         if (arc -> state != SAME_STATE)
  189.             wob -> curstate = (int) arc -> state;
  190.  
  191.         return NULL;
  192.     }
  193.     }
  194.     TraceDo('f',
  195.         GWM_prettyprint_fsm_event(wob, evt, "REJECT",
  196.                       wob -> curstate,
  197.                       arc -> state));
  198.     return NULL;
  199. }
  200.     
  201. /*
  202.  * Routine used to construct a state 
  203.  * USAGE:
  204.  *     (state-make arc1 arc2 ... arcn)
  205.  */
  206.  
  207. WOOL_FsmState
  208. wool_fsm_state_make(argc, argv)
  209. int         argc;
  210. WOOL_StateArc    argv[];
  211. {
  212.     WOOL_FsmState   state;
  213.     int             i, j, narc = argc;
  214.     WOOL_FsmState   inc_state;
  215.  
  216.     for (i = 0; i < argc; i++)
  217.     if (argv[i] -> type == WLFsmState)
  218.         narc += ((WOOL_FsmState) argv[i]) -> arcs_size - 1;
  219.     else if (argv[i] == (WOOL_StateArc) NIL)
  220.         narc--;
  221.     state = (WOOL_FsmState)
  222.     Malloc(sizeof(struct _WOOL_FsmState) +
  223.            Max(0, narc - 1) * sizeof(WOOL_OBJECT));
  224.     state -> type = WLFsmState;
  225.     state -> mask = state -> user_mask = 0;
  226.     zrt_put(state);
  227.     state -> arcs_size = narc;
  228.     state -> copy_of = state;
  229.     narc = 0;
  230.     for (i = 0; i < argc; i++) {
  231.     if (argv[i] -> type == WLStateArc) {
  232.         increase_reference(state -> arcs[narc++] = argv[i]);
  233.         state -> mask |= argv[i] -> event -> mask;
  234.         state -> user_mask |= argv[i] -> event -> user_mask;
  235.     } else if (argv[i] -> type == WLFsmState) {
  236.         inc_state = (WOOL_FsmState) argv[i];
  237.         for (j = 0; j < inc_state -> arcs_size; j++) {
  238.         increase_reference(state -> arcs[narc++]
  239.                    = inc_state -> arcs[j]);
  240.         state -> mask |= inc_state -> arcs[j] -> event -> mask;
  241.         state -> user_mask |=
  242.             inc_state -> arcs[j] -> event -> user_mask;
  243.         }
  244.     } else if (argv[i] == (WOOL_StateArc) NIL) 
  245.         ;                /* skip () */
  246.         else
  247.         bad_argument(argv[i], i, "fsm state");
  248.     }
  249.     return state;
  250. }
  251.  
  252.     
  253. /*
  254.  * make an arc: (FSUBR)
  255.  * syntax: (on event [action [state]])
  256.  * action (list) and state (atom) MUST NOT BE QUOTED!
  257.  */
  258.  
  259. WOOL_StateArc
  260. wool_state_arc_make(argc, argv)
  261. int         argc;
  262. WOOL_OBJECT    argv[];
  263. {
  264.     WOOL_StateArc   arc = (WOOL_StateArc)
  265.     Calloc(sizeof(struct _WOOL_StateArc),1);
  266.  
  267.     arc -> type = WLStateArc;
  268.     zrt_put(arc);
  269.     if (argc == 0 || argc > 3)
  270.     wool_error(BAD_NUMBER_OF_ARGS, argc);
  271.     arc -> state = SAME_STATE;
  272.     arc -> action = NULL;
  273.     increase_reference(arc -> event = (WOOL_Event)
  274.                wool_type_or_evaluate(argv[0], WLEvent));
  275.     if (arc -> event == (WOOL_Event) NIL)
  276.     bad_argument(argv[0], 0, "event");
  277.     switch (argc) {
  278.     case 3:
  279.     must_be_atom(argv[2], 2);
  280.     arc -> state = (WOOL_Atom) argv[2];
  281.     case 2:
  282.     must_be_or_nil(WLList, argv[1], 1);
  283.     if (argv[1] != (WOOL_OBJECT) NIL)
  284.         increase_reference(arc -> action = (WOOL_List) argv[1]);
  285.     }
  286.     return arc;
  287. }
  288.  
  289. WOOL_OBJECT
  290. WLFsm_free(obj)
  291. WOOL_Fsm obj;
  292. {
  293.     decrease_reference_in_list(obj -> states_size, obj -> states);
  294.     Free(obj);
  295.     return NULL;
  296. }
  297.  
  298. WOOL_OBJECT
  299. WLFsmState_free(obj)
  300. WOOL_FsmState obj;
  301. {
  302.     decrease_reference_in_list(obj -> arcs_size, obj -> arcs);
  303.     Free(obj);
  304.     return NULL;
  305. }
  306.  
  307. WOOL_OBJECT
  308. WLStateArc_free(obj)
  309. WOOL_StateArc obj;
  310. {
  311.     decrease_reference(obj -> event);
  312.     decrease_reference(obj -> action);
  313.     Free(obj);
  314.     return NULL;
  315. }
  316.  
  317. WOOL_OBJECT
  318. WLFsm_open(fsm)
  319. WOOL_Fsm fsm;
  320. {
  321.     return 0;
  322. }
  323.  
  324. WOOL_StateArc
  325. WLStateArc_copy(oldarc)
  326. WOOL_StateArc oldarc;
  327. {
  328.     WOOL_StateArc   arc =
  329.     (WOOL_StateArc) Malloc(sizeof(struct _WOOL_StateArc));
  330.  
  331.     arc -> type = WLStateArc;
  332.     zrt_put(arc);
  333.     increase_reference(arc -> event = oldarc -> event);
  334.     if(arc -> action = oldarc -> action)
  335.     increase_reference(arc -> action);
  336.     if((arc -> state = oldarc -> state) != (WOOL_Atom) ANY)
  337.     increase_reference(arc -> state);
  338.     return arc;
  339. }
  340.  
  341. WOOL_FsmState
  342. WLFsmState_copy(oldstate)
  343. WOOL_FsmState oldstate;
  344. {
  345.     WOOL_FsmState   state = (WOOL_FsmState)
  346.     Malloc(sizeof(struct _WOOL_FsmState) + Max(0,oldstate -> arcs_size - 1)
  347.        * sizeof(WOOL_OBJECT));
  348.     int             i;
  349.  
  350.     state -> type = WLFsmState;
  351.     zrt_put(state);
  352.     state -> mask = oldstate -> mask;
  353.     state -> user_mask = oldstate -> user_mask;
  354.     state -> arcs_size = oldstate -> arcs_size;
  355.     state -> copy_of = oldstate -> copy_of;
  356.     for (i = 0; i < state -> arcs_size; i++)
  357.     increase_reference(state -> arcs[i] =
  358.                WLStateArc_copy(oldstate -> arcs[i]));
  359.     return state;
  360. }
  361.  
  362. /*
  363.  * NIL_FSM_make:
  364.  * used to build the nil fsm on startup
  365.  */
  366.  
  367. NIL_FSM_make()
  368. {
  369.     WOOL_FsmState   state = (WOOL_FsmState)
  370.     Malloc(sizeof(struct _WOOL_FsmState));
  371.  
  372.     NIL_FSM = (WOOL_Fsm) Malloc(sizeof(struct _WOOL_Fsm));
  373.     state -> type = WLFsmState;
  374.     state -> mask = state -> user_mask = 0;
  375.     zrt_put(state);
  376.     increase_reference(state);
  377.     state -> arcs_size = 0;
  378.     zrt_put(NIL_FSM);
  379.     NIL_FSM -> type = WLFsm;
  380.     NIL_FSM -> mask = 0;
  381.     NIL_FSM -> user_mask = 0;
  382.     NIL_FSM -> states_size = 1;
  383.     NIL_FSM -> states[0] = state;
  384.     increase_reference(NIL_FSM);
  385. }
  386.  
  387. void
  388. fix_fsm(ptr)
  389. WOOL_Fsm    *ptr;
  390. {
  391.     if (*ptr == (WOOL_Fsm) NIL)
  392.     increase_reference(*ptr = (WOOL_Fsm) NIL_FSM);
  393. }
  394.