statemap.h
Go to the documentation of this file.
1 //
2 // The contents of this file are subject to the Mozilla Public
3 // License Version 1.1 (the "License"); you may not use this file
4 // except in compliance with the License. You may obtain a copy
5 // of the License at http://www.mozilla.org/MPL/
6 //
7 // Software distributed under the License is distributed on an
8 // "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 // implied. See the License for the specific language governing
10 // rights and limitations under the License.
11 //
12 // The Original Code is State Machine Compiler (SMC).
13 //
14 // The Initial Developer of the Original Code is Charles W. Rapp.
15 // Portions created by Charles W. Rapp are
16 // Copyright (C) 2000 - 2007. Charles W. Rapp.
17 // All Rights Reserved.
18 //
19 // Contributor(s):
20 //
21 // Namespace
22 // statemap
23 //
24 // Description
25 // This namespace contains the finite state machine context
26 // class. The user can derive FSM contexts from this class and
27 // interface to them with the methods of this class.
28 //
29 // Notes
30 // The finite state machine needs to be initialized to the
31 // starting state of the FSM. This must be done manually in
32 // the constructor of the derived class.
33 //
34 // Author
35 // C. W. Rapp
36 //
37 // RCS ID
38 // $Id: statemap.h,v 1.15 2009/11/24 20:42:39 cwrapp Exp $
39 //
40 // CHANGE LOG
41 // (See bottom of file)
42 //
43 
44 #ifndef SMCLIB__STATEMAP_H_
45 #define SMCLIB__STATEMAP_H_
46 
47 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
48 #include <iostream>
49 #if defined(SMC_NO_EXCEPTIONS)
50 #include <cassert>
51 #endif // SMC_NO_EXCEPTIONS
52 #include <cstdio>
53 #elif defined(WIN32)
54 #include <iostream>
55 #if defined(SMC_NO_EXCEPTIONS)
56 #include <cassert>
57 #endif // SMC_NO_EXCEPTIONS
58 #else
59 #include <iostream.h>
60 #if defined(SMC_NO_EXCEPTIONS)
61 #include <assert.h>
62 #endif // SMC_NO_EXCEPTIONS
63 #include <stdio.h>
64 #endif
65 #if !defined(SMC_NO_EXCEPTIONS)
66 #include <stdexcept>
67 #include <cstring>
68 #endif
69 
70 #include <string>
71 
72 // Limit names to 100 ASCII characters.
73 // Why 100? Because it is a round number.
74 #define MAX_NAME_LEN 100
75 
76 namespace statemap
77 {
78 //---------------------------------------------------------------
79 // Routines.
80 //
81 
82 inline char* copyString(const char *s)
83 {
84  char *retval = NULL;
85 
86  if (s != NULL)
87  {
88  retval = new char[MAX_NAME_LEN + 1];
89  retval[MAX_NAME_LEN] = '\0';
90  (void) std::strncpy(retval, s, MAX_NAME_LEN);
91  }
92 
93  return (retval);
94 }
95 
96 //---------------------------------------------------------------
97 // Exception Classes.
98 //
99 
100 #ifndef SMC_NO_EXCEPTIONS
101 // Base class for all SMC exceptions.
103  public std::runtime_error
104 {
105  //-----------------------------------------------------------
106  // Member methods
107  //
108  public:
109  // Destructor.
110  virtual ~SmcException() throw()
111  {};
112 
113  protected:
114  // Constructor.
115  SmcException(const std::string& reason)
116  : std::runtime_error(reason)
117  {};
118 
119  private:
120  // Default construction not allowed.
121  SmcException();
122 
123  //-----------------------------------------------------------
124  // Member data.
125  //
126  public:
127  protected:
128  private:
129 };
130 
131 // This class is thrown when a pop is issued on an empty
132 // state stack.
134  public SmcException
135 {
136  //-----------------------------------------------------------
137  // Member methods.
138  //
139  public:
140  // Default constructor.
142  : SmcException("no state to pop from state stack")
143  {};
144 
145  // Destructor.
147  {};
148 
149  protected:
150  private:
151  //-----------------------------------------------------------
152  // Member data.
153  //
154  public:
155  protected:
156  private:
157 };
158 
159 // This class is thrown when a transition is issued
160 // but there is no current state. This happens when
161 // a transition is issued from within a transition
162 // action.
164  public SmcException
165 {
166  //-----------------------------------------------------------
167  // Member methods.
168  //
169  public:
170  // Default constructor.
172  : SmcException("transition invoked while in transition")
173  {};
174 
175  // Destructor.
176  virtual ~StateUndefinedException() throw()
177  {};
178 
179  protected:
180  private:
181  //-----------------------------------------------------------
182  // Member data.
183  //
184  public:
185  protected:
186  private:
187 };
188 
189 // This class is thrown when a transition is issued
190 // but there is no code to handle it.
192  public SmcException
193 {
194  //-----------------------------------------------------------
195  // Member methods.
196  //
197  public:
198  // Default constructor.
200  : SmcException("no such transition in current state"),
201  _state(NULL),
202  _transition(NULL)
203  {};
204 
205  // Construct an exception using the specified state
206  // and transition.
207  TransitionUndefinedException(const char *state,
208  const char *transition)
209  : SmcException("no such transition in current state"),
210  _state(copyString(state)),
211  _transition(copyString(transition))
212  {};
213 
214  // Copy constructor.
217  : SmcException("no such transition in current state"),
218  _state(copyString(ex._state)),
219  _transition(copyString(ex._transition))
220  {};
221 
222  // Destructor.
224  {
225  if (_state != NULL)
226  {
227  delete[] _state;
228  _state = NULL;
229  }
230 
231  if (_transition != NULL)
232  {
233  delete[] _transition;
234  _transition = NULL;
235  }
236  };
237 
238  // Assignment operator.
241  {
242  // Don't do self assignment.
243  if (this != &ex)
244  {
245  if (_state != NULL)
246  {
247  delete[] _state;
248  _state = NULL;
249  }
250 
251  if (_transition != NULL)
252  {
253  delete[] _transition;
254  _transition = NULL;
255  }
256 
257  _state = copyString(ex._state);
258  _transition = copyString(ex._transition);
259  }
260 
261  return (*this);
262  };
263 
264  // Returns the state. May be NULL.
265  const char* getState() const
266  {
267  return(_state);
268  };
269 
270  // Returns the transition. May be NULL.
271  const char* getTransition() const
272  {
273  return (_transition);
274  };
275 
276  protected:
277  private:
278  //-----------------------------------------------------------
279  // Member data.
280  //
281  public:
282  protected:
283  private:
284  char *_state;
285  char *_transition;
286 };
287 
288 // This class is thrown when a state ID is either less than
289 // the minimal value or greater than the maximal value.
291  public SmcException
292 {
293  //-----------------------------------------------------------
294  // Member methods.
295  //
296  public:
297  // Default constructor.
299  : SmcException("index out of bounds"),
300  _index(0),
301  _minIndex(0),
302  _maxIndex(0)
303  {};
304 
305  // Constructs an exception using the specified index,
306  // minimum index and maximum index.
307  IndexOutOfBoundsException(const int index,
308  const int minIndex,
309  const int maxIndex)
310  : SmcException("index out of bounds"),
311  _index(index),
312  _minIndex(minIndex),
313  _maxIndex(maxIndex)
314  {};
315 
316  // Copy constructor.
318  const IndexOutOfBoundsException& ex)
319  : SmcException("index out of bounds"),
320  _index(ex._index),
321  _minIndex(ex._minIndex),
322  _maxIndex(ex._maxIndex)
323  {};
324 
325  // Destructor.
326  virtual ~IndexOutOfBoundsException() throw()
327  {};
328 
329  // Assignment operator.
332  {
333  // Don't do self assignment.
334  if (this != &ex)
335  {
336  _index = ex._index;
337  _minIndex = ex._minIndex;
338  _maxIndex = ex._maxIndex;
339  }
340 
341  return (*this);
342  };
343 
344  // Returns the out-of-bounds index.
345  int getIndex() const
346  {
347  return(_index);
348  };
349 
350  // Returns the minimum allowed index value.
351  int getMinIndex() const
352  {
353  return (_minIndex);
354  };
355 
356  // Returns the maximum allowed index value.
357  int getMaxIndex() const
358  {
359  return (_maxIndex);
360  };
361 
362  protected:
363  private:
364  //-----------------------------------------------------------
365  // Member data.
366  //
367  public:
368  protected:
369  private:
370  int _index;
373 };
374 #endif // !SMC_NO_EXCEPTIONS
375 
376 //
377 // end of Exception Classes.
378 //---------------------------------------------------------------
379 
380 class State
381 {
382 //-----------------------------------------------------------
383 // Member functions.
384 //
385 public:
386  const char* getName() const
387  {
388  return (_name);
389  };
390 
391  int getId() const
392  {
393  return (_stateId);
394  }
395 
396 protected:
397  State(const char *name, int stateId)
398  : _name(NULL),
399  _stateId(stateId)
400  {
401  if (name != NULL)
402  {
403  _name = copyString(name);
404  }
405  else
406  {
407  _name = copyString("NAME NOT SET");
408  }
409  };
410 
411  virtual ~State()
412  {
413  if (_name != NULL)
414  {
415  delete[] _name;
416  _name = NULL;
417  }
418  };
419 
420 private:
421  // Make the default and copy constructors private to
422  // prevent their use.
423  State() {}
424  State(const State&) {}
425 
426 //-----------------------------------------------------------
427 // Member data.
428 //
429 public:
430 protected:
431  // This state's printable name.
432  char *_name;
433 
434  // This state's unique identifier.
435  int _stateId;
436 
437 private:
438 };
439 
441 {
442 //-----------------------------------------------------------
443 // Nested classes.
444 //
445 public:
446 protected:
447 private:
448  // Implements the state stack.
450  {
451  //-------------------------------------------------------
452  // Member functions.
453  //
454  public:
455  StateEntry(State *state, StateEntry *next)
456  : _state(state),
457  _next(next)
458  {};
459 
461  {
462  _state = NULL;
463  _next = NULL;
464  };
465 
467  {
468  return(_state);
469  };
470 
472  {
473  return(_next);
474  };
475 
476  protected:
477  private:
478  //-------------------------------------------------------
479  // Member data.
480  //
481  public:
482  protected:
483  private:
484  State *_state;
486 
487  //-------------------------------------------------------
488  // Friends
489  //
490  friend class FSMContext;
491  }; // end of class StateEntry
492 
493 //-----------------------------------------------------------
494 // Member functions
495 //
496 public:
497  // Destructor.
498  virtual ~FSMContext()
499  {
500  StateEntry *state;
501 
502  if (_transition != NULL)
503  {
504  delete[] _transition;
505  _transition = NULL;
506  }
507 
508  // But we did allocate the state stack.
509  while (_state_stack != NULL)
510  {
511  state = _state_stack;
512  _state_stack = _state_stack->_next;
513  delete state;
514  }
515  };
516 
517  // Comparison and assignment operators
518  // Assignment operator
520  {
521  // Don't do the assignment if the left and right
522  // hand sides are the same object.
523  if (this != &fsm)
524  {
525  _state = fsm._state;
526  }
527 
528  return(*this);
529  };
530 
531  // Starts the finite state machine running by executing
532  // the initial state's entry actions.
533  virtual void enterStartState() = 0;
534 
535  // Exact same object (is it me?)
536  int same(const FSMContext& fsm) const
537  {
538  return(this == &fsm);
539  };
540 
541  // Returns the debug flag's current setting.
543  {
544  return(_debug_flag);
545  };
546 
547  // Sets the debug flag. A true value means debugging
548  // is on and false means off.
549  void setDebugFlag(bool flag)
550  {
551  _debug_flag = flag;
552  return;
553  };
554 
555 #ifdef SMC_USES_IOSTREAMS
556  // Returns the stream to which debug output is written.
557  std::ostream& getDebugStream()
558  {
559  return (*_debug_stream);
560  };
561 
562  // Sets the debug output stream.
563  void setDebugStream(std::ostream& debug_stream)
564  {
565  _debug_stream = &debug_stream;
566  return;
567  }
568 #endif // SMC_USES_IOSTREAMS
569 
570  // Is this state machine already inside a transition?
571  // Yes if state is null.
572  bool isInTransition() const
573  {
574  return(_state == NULL ? true : false);
575  };
576 
577  // Returns the current transition's name.
578  // Used only for debugging purposes.
580  {
581  return (_transition);
582  };
583 
584  // Saves away the transition name only if debugging
585  // is turned on.
586  void setTransition(const char *transition)
587  {
588  if (_transition != NULL)
589  {
590  delete[] _transition;
591  _transition = NULL;
592  }
593 
594  _transition = copyString(transition);
595 
596  return;
597  };
598 
599  // Clears the current state.
600  void clearState()
601  {
602  _previous_state = _state;
603  _state = NULL;
604  };
605 
606  // Returns the state which a transition left.
607  // May be NULL.
609  {
610  return (_previous_state);
611  }
612 
613  // Sets the current state to the specified state.
614  void setState(const State& state)
615  {
616  _state = const_cast<State *>(&state);
617 
618  if (_debug_flag == true)
619  {
620 #ifdef SMC_USES_IOSTREAMS
621  *_debug_stream << "ENTER STATE : "
622  << _state->getName()
623  << std::endl;
624 #else
625  TRACE("ENTER STATE : %s\n\r",
626  _state->getName());
627 #endif // SMC_USES_IOSTREAMS
628  }
629  };
630 
631  // Returns true if the state stack is empty and false
632  // otherwise.
633  bool isStateStackEmpty() const
634  {
635  return (_state_stack == NULL);
636  }
637 
638  // Returns the state stack's depth.
639  int getStateStackDepth() const
640  {
641  StateEntry *state_ptr;
642  int retval;
643 
644  for (state_ptr = _state_stack, retval = 0;
645  state_ptr != NULL;
646  state_ptr = state_ptr->getNext(), ++retval)
647  ;
648 
649  return (retval);
650  }
651 
652  // Push the current state on top of the state stack
653  // and make the specified state the current state.
654  void pushState(const State& state)
655  {
656  StateEntry *new_entry;
657 
658  // Do the push only if there is a state to be pushed
659  // on the stack.
660  if (_state != NULL)
661  {
662  new_entry = new StateEntry(_state, _state_stack);
663  _state_stack = new_entry;
664  }
665 
666  _state = const_cast<State *>(&state);
667 
668  if (_debug_flag == true)
669  {
670 #ifdef SMC_USES_IOSTREAMS
671  *_debug_stream << "PUSH TO STATE : "
672  << _state->getName()
673  << std::endl;
674 #else
675  TRACE("PUSH TO STATE : %s\n\r",
676  _state->getName());
677 #endif // SMC_USES_IOSTREAMS
678  }
679  };
680 
681  // Make the state on top of the state stack the
682  // current state.
683  void popState()
684  {
685  StateEntry *entry;
686 
687  // Popping when there was no previous push is an error.
688 #ifdef SMC_NO_EXCEPTIONS
689  assert(_state_stack != NULL);
690 #else
691  if (_state_stack == NULL)
692  {
694  }
695 #endif // SMC_NO_EXCEPTIONS
696 
697  _state = _state_stack->getState();
698  entry = _state_stack;
699  _state_stack = _state_stack->getNext();
700  delete entry;
701 
702  if (_debug_flag == true)
703  {
704 #ifdef SMC_USES_IOSTREAMS
705  *_debug_stream << "POP TO STATE : "
706  << _state->getName()
707  << std::endl;
708 #else
709  TRACE("POP TO STATE : %s\n\r",
710  _state->getName());
711 #endif // SMC_USES_IOSTREAMS
712  }
713  };
714 
715  // Remove all states from the state stack.
717  {
718  StateEntry *state_ptr,
719  *next_ptr;
720 
721  for (state_ptr = _state_stack;
722  state_ptr != NULL;
723  state_ptr = next_ptr)
724  {
725  next_ptr = state_ptr->getNext();
726  delete state_ptr;
727  }
728 
729  _state_stack = NULL;
730  };
731 
732 protected:
733  // Default constructor.
734  FSMContext(const State& state)
735  : _state(const_cast<State *>(&state)),
736  _previous_state(NULL),
737  _state_stack(NULL),
738  _transition(NULL),
739 #ifdef SMC_USES_IOSTREAMS
740  _debug_flag(false),
741  _debug_stream(&std::cerr)
742 #else
743  _debug_flag(false)
744 #endif // SMC_USES_IOSTREAMS
745  {};
746 
747 private:
748  // I don't believe that it makes sense to copy a
749  // context. It may make sense to copy the application
750  // class but the new object is *not* in the same
751  // state as the old - the new object must start in
752  // the FSM's initial state. Therefore, the copy
753  // constructor is private in order to prevent it
754  // being used.
756  {};
757 
758 //-----------------------------------------------------------
759 // Member data
760 //
761 public:
762 protected:
763  // The current state of the finite state machine.
764  State *_state;
765 
766  // Remember which state a transition left.
768 
769  // The stack of pushed states.
771 
772  // The current transition *name*. Use for debugging
773  // purposes.
774  char *_transition;
775 
776 private:
777  // When this flag is set to true, this class will print
778  // out debug messages.
780 
781 // Include the following only if C++ iostreams are being used.
782 #ifdef SMC_USES_IOSTREAMS
783  // When FSM debugging is on, debug messages will be
784  // written to this output stream. This stream is set to
785  // standard error by default.
786  std::ostream *_debug_stream;
787 #endif // SMC_USES_IOSTREAMS
788 }; // end of class FSMContext
789 } // namespace statemap
790 
791 //
792 // CHANGE LOG
793 // $Log: statemap.h,v $
794 // Revision 1.15 2009/11/24 20:42:39 cwrapp
795 // v. 6.0.1 update
796 //
797 // Revision 1.14 2009/03/01 18:20:40 cwrapp
798 // Preliminary v. 6.0.0 commit.
799 //
800 // Revision 1.13 2008/05/20 18:31:12 cwrapp
801 // ----------------------------------------------------------------------
802 //
803 // Committing release 5.1.0.
804 //
805 // Modified Files:
806 // Makefile README.txt smc.mk tar_list.txt bin/Smc.jar
807 // examples/Ant/EX1/build.xml examples/Ant/EX2/build.xml
808 // examples/Ant/EX3/build.xml examples/Ant/EX4/build.xml
809 // examples/Ant/EX5/build.xml examples/Ant/EX6/build.xml
810 // examples/Ant/EX7/build.xml examples/Ant/EX7/src/Telephone.java
811 // examples/Java/EX1/Makefile examples/Java/EX4/Makefile
812 // examples/Java/EX5/Makefile examples/Java/EX6/Makefile
813 // examples/Java/EX7/Makefile examples/Ruby/EX1/Makefile
814 // lib/statemap.jar lib/C++/statemap.h lib/Java/Makefile
815 // lib/Php/statemap.php lib/Scala/Makefile
816 // lib/Scala/statemap.scala net/sf/smc/CODE_README.txt
817 // net/sf/smc/README.txt net/sf/smc/Smc.java
818 // ----------------------------------------------------------------------
819 //
820 // Revision 1.12 2007/12/28 12:34:40 cwrapp
821 // Version 5.0.1 check-in.
822 //
823 // Revision 1.11 2007/08/05 12:58:54 cwrapp
824 // Version 5.0.1 check-in. See net/sf/smc/CODE_README.txt for more information.
825 //
826 // Revision 1.10 2007/01/15 00:23:50 cwrapp
827 // Release 4.4.0 initial commit.
828 //
829 // Revision 1.9 2006/07/11 18:28:22 cwrapp
830 // Move SmcException::copyString() to a package-wide routine.
831 //
832 // Revision 1.8 2006/04/22 12:45:24 cwrapp
833 // Version 4.3.1
834 //
835 // Revision 1.7 2005/06/08 11:09:14 cwrapp
836 // + Updated Python code generator to place "pass" in methods with empty
837 // bodies.
838 // + Corrected FSM errors in Python example 7.
839 // + Removed unnecessary includes from C++ examples.
840 // + Corrected errors in top-level makefile's distribution build.
841 //
842 // Revision 1.6 2005/05/28 18:44:13 cwrapp
843 // Updated C++, Java and Tcl libraries, added CSharp, Python and VB.
844 //
845 // Revision 1.2 2005/02/21 19:01:42 charlesr
846 // Changed State::_id to State::_stateId because of Object-C++
847 // reserved word conflict.
848 //
849 // Revision 1.1 2004/05/31 13:44:41 charlesr
850 // Added support for non-iostreams output.
851 //
852 // Revision 1.0 2003/12/14 20:37:49 charlesr
853 // Initial revision
854 
855 #endif // SMCLIB__STATEMAP_H_
const IndexOutOfBoundsException & operator=(const IndexOutOfBoundsException &ex)
Definition: statemap.h:331
IndexOutOfBoundsException(const IndexOutOfBoundsException &ex)
Definition: statemap.h:317
virtual ~FSMContext()
Definition: statemap.h:498
const char * getTransition() const
Definition: statemap.h:271
char * getTransition()
Definition: statemap.h:579
TransitionUndefinedException(const TransitionUndefinedException &ex)
Definition: statemap.h:215
State * _previous_state
Definition: statemap.h:767
SmcException(const std::string &reason)
Definition: statemap.h:115
FSMContext(const State &state)
Definition: statemap.h:734
int getStateStackDepth() const
Definition: statemap.h:639
TransitionUndefinedException(const char *state, const char *transition)
Definition: statemap.h:207
virtual ~SmcException()
Definition: statemap.h:110
void emptyStateStack()
Definition: statemap.h:716
void pushState(const State &state)
Definition: statemap.h:654
int same(const FSMContext &fsm) const
Definition: statemap.h:536
State * getPreviousState()
Definition: statemap.h:608
#define MAX_NAME_LEN
Definition: statemap.h:74
bool isStateStackEmpty() const
Definition: statemap.h:633
bool isInTransition() const
Definition: statemap.h:572
void setState(const State &state)
Definition: statemap.h:614
int getId() const
Definition: statemap.h:391
char * copyString(const char *s)
Definition: statemap.h:82
State(const State &)
Definition: statemap.h:424
FSMContext(const FSMContext &)
Definition: statemap.h:755
StateEntry * _state_stack
Definition: statemap.h:770
virtual ~State()
Definition: statemap.h:411
State(const char *name, int stateId)
Definition: statemap.h:397
IndexOutOfBoundsException(const int index, const int minIndex, const int maxIndex)
Definition: statemap.h:307
FSMContext & operator=(const FSMContext &fsm)
Definition: statemap.h:519
const char * getName() const
Definition: statemap.h:386
void setDebugFlag(bool flag)
Definition: statemap.h:549
StateEntry(State *state, StateEntry *next)
Definition: statemap.h:455
const TransitionUndefinedException & operator=(const TransitionUndefinedException &ex)
Definition: statemap.h:240
char * _name
Definition: statemap.h:432
void setTransition(const char *transition)
Definition: statemap.h:586


smclib
Author(s): Various
autogenerated on Mon Feb 28 2022 21:58:33