statemap.h
Go to the documentation of this file.
00001 //
00002 // The contents of this file are subject to the Mozilla Public
00003 // License Version 1.1 (the "License"); you may not use this file
00004 // except in compliance with the License. You may obtain a copy
00005 // of the License at http://www.mozilla.org/MPL/
00006 //
00007 // Software distributed under the License is distributed on an
00008 // "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
00009 // implied. See the License for the specific language governing
00010 // rights and limitations under the License.
00011 //
00012 // The Original Code is State Machine Compiler (SMC).
00013 //
00014 // The Initial Developer of the Original Code is Charles W. Rapp.
00015 // Portions created by Charles W. Rapp are
00016 // Copyright (C) 2000 - 2007. Charles W. Rapp.
00017 // All Rights Reserved.
00018 //
00019 // Contributor(s):
00020 //
00021 // Namespace
00022 //  statemap
00023 //
00024 // Description
00025 //  This namespace contains the finite state machine context
00026 //  class. The user can derive FSM contexts from this class and
00027 //  interface to them with the methods of this class.
00028 //
00029 // Notes
00030 //  The finite state machine needs to be initialized to the
00031 //  starting state of the FSM.  This must be done manually in
00032 //  the constructor of the derived class.
00033 //
00034 // Author
00035 //  C. W. Rapp
00036 //
00037 // RCS ID
00038 // $Id: statemap.h,v 1.15 2009/11/24 20:42:39 cwrapp Exp $
00039 //
00040 // CHANGE LOG
00041 // (See bottom of file)
00042 //
00043 
00044 #ifndef SMCLIB__STATEMAP_H_
00045 #define SMCLIB__STATEMAP_H_
00046 
00047 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
00048 #include <iostream>
00049 #if defined(SMC_NO_EXCEPTIONS)
00050 #include <cassert>
00051 #endif  // SMC_NO_EXCEPTIONS
00052 #include <cstdio>
00053 #elif defined(WIN32)
00054 #include <iostream>
00055 #include <windows.h>
00056 #if defined(SMC_NO_EXCEPTIONS)
00057 #include <cassert>
00058 #endif  // SMC_NO_EXCEPTIONS
00059 #else
00060 #include <iostream.h>
00061 #if defined(SMC_NO_EXCEPTIONS)
00062 #include <assert.h>
00063 #endif  // SMC_NO_EXCEPTIONS
00064 #include <stdio.h>
00065 #endif
00066 #if !defined(SMC_NO_EXCEPTIONS)
00067 #include <stdexcept>
00068 #include <cstring>
00069 #endif
00070 
00071 #include <string>
00072 
00073 // Limit names to 100 ASCII characters.
00074 // Why 100? Because it is a round number.
00075 #define MAX_NAME_LEN 100
00076 
00077 namespace statemap
00078 {
00079 //---------------------------------------------------------------
00080 // Routines.
00081 //
00082 
00083 inline char* copyString(const char *s)
00084 {
00085     char *retval = NULL;
00086 
00087     if (s != NULL)
00088     {
00089         retval = new char[MAX_NAME_LEN + 1];
00090         retval[MAX_NAME_LEN] = '\0';
00091         (void) std::strncpy(retval, s, MAX_NAME_LEN);
00092     }
00093 
00094     return (retval);
00095 }
00096 
00097 //---------------------------------------------------------------
00098 // Exception Classes.
00099 //
00100 
00101 #ifndef SMC_NO_EXCEPTIONS
00102 // Base class for all SMC exceptions.
00103 class SmcException :
00104     public std::runtime_error
00105 {
00106     //-----------------------------------------------------------
00107     // Member methods
00108     //
00109     public:
00110         // Destructor.
00111         virtual ~SmcException() throw()
00112         {};
00113 
00114     protected:
00115         // Constructor.
00116         SmcException(const std::string& reason)
00117         : std::runtime_error(reason)
00118         {};
00119 
00120     private:
00121         // Default construction not allowed.
00122         SmcException();
00123 
00124     //-----------------------------------------------------------
00125     // Member data.
00126     //
00127     public:
00128     protected:
00129     private:
00130 };
00131 
00132 // This class is thrown when a pop is issued on an empty
00133 // state stack.
00134 class PopOnEmptyStateStackException :
00135     public SmcException
00136 {
00137     //-----------------------------------------------------------
00138     // Member methods.
00139     //
00140     public:
00141         // Default constructor.
00142         PopOnEmptyStateStackException()
00143         : SmcException("no state to pop from state stack")
00144         {};
00145 
00146         // Destructor.
00147         virtual ~PopOnEmptyStateStackException() throw()
00148         {};
00149 
00150     protected:
00151     private:
00152     //-----------------------------------------------------------
00153     // Member data.
00154     //
00155     public:
00156     protected:
00157     private:
00158 };
00159 
00160 // This class is thrown when a transition is issued
00161 // but there is no current state. This happens when
00162 // a transition is issued from within a transition
00163 // action.
00164 class StateUndefinedException :
00165     public SmcException
00166 {
00167     //-----------------------------------------------------------
00168     // Member methods.
00169     //
00170     public:
00171         // Default constructor.
00172         StateUndefinedException()
00173         : SmcException("transition invoked while in transition")
00174         {};
00175 
00176         // Destructor.
00177         virtual ~StateUndefinedException() throw()
00178         {};
00179 
00180     protected:
00181     private:
00182     //-----------------------------------------------------------
00183     // Member data.
00184     //
00185     public:
00186     protected:
00187     private:
00188 };
00189 
00190 // This class is thrown when a transition is issued
00191 // but there is no code to handle it.
00192 class TransitionUndefinedException :
00193     public SmcException
00194 {
00195     //-----------------------------------------------------------
00196     // Member methods.
00197     //
00198     public:
00199         // Default constructor.
00200         TransitionUndefinedException()
00201         : SmcException("no such transition in current state"),
00202           _state(NULL),
00203           _transition(NULL)
00204         {};
00205 
00206         // Construct an exception using the specified state
00207         // and transition.
00208         TransitionUndefinedException(const char *state,
00209                                      const char *transition)
00210         : SmcException("no such transition in current state"),
00211           _state(copyString(state)),
00212           _transition(copyString(transition))
00213         {};
00214 
00215         // Copy constructor.
00216         TransitionUndefinedException(
00217             const TransitionUndefinedException& ex)
00218         : SmcException("no such transition in current state"),
00219           _state(copyString(ex._state)),
00220           _transition(copyString(ex._transition))
00221         {};
00222 
00223         // Destructor.
00224         virtual ~TransitionUndefinedException() throw()
00225         {
00226             if (_state != NULL)
00227             {
00228                 delete[] _state;
00229                 _state = NULL;
00230             }
00231 
00232             if (_transition != NULL)
00233             {
00234                 delete[] _transition;
00235                 _transition = NULL;
00236             }
00237         };
00238 
00239         // Assignment operator.
00240         const TransitionUndefinedException&
00241             operator=(const TransitionUndefinedException& ex)
00242         {
00243             // Don't do self assignment.
00244             if (this != &ex)
00245             {
00246                 if (_state != NULL)
00247                 {
00248                     delete[] _state;
00249                     _state = NULL;
00250                 }
00251 
00252                 if (_transition != NULL)
00253                 {
00254                     delete[] _transition;
00255                     _transition = NULL;
00256                 }
00257 
00258                 _state = copyString(ex._state);
00259                 _transition = copyString(ex._transition);
00260             }
00261 
00262             return (*this);
00263         };
00264 
00265         // Returns the state. May be NULL.
00266         const char* getState() const
00267         {
00268             return(_state);
00269         };
00270 
00271         // Returns the transition. May be NULL.
00272         const char* getTransition() const
00273         {
00274             return (_transition);
00275         };
00276 
00277     protected:
00278     private:
00279     //-----------------------------------------------------------
00280     // Member data.
00281     //
00282     public:
00283     protected:
00284     private:
00285         char *_state;
00286         char *_transition;
00287 };
00288 
00289 // This class is thrown when a state ID is either less than
00290 // the minimal value or greater than the maximal value.
00291 class IndexOutOfBoundsException :
00292     public SmcException
00293 {
00294     //-----------------------------------------------------------
00295     // Member methods.
00296     //
00297     public:
00298         // Default constructor.
00299         IndexOutOfBoundsException()
00300         : SmcException("index out of bounds"),
00301           _index(0),
00302           _minIndex(0),
00303           _maxIndex(0)
00304         {};
00305 
00306         // Constructs an exception using the specified index,
00307         // minimum index and maximum index.
00308         IndexOutOfBoundsException(const int index,
00309                                   const int minIndex,
00310                                   const int maxIndex)
00311         : SmcException("index out of bounds"),
00312           _index(index),
00313           _minIndex(minIndex),
00314           _maxIndex(maxIndex)
00315         {};
00316 
00317         // Copy constructor.
00318         IndexOutOfBoundsException(
00319             const IndexOutOfBoundsException& ex)
00320         : SmcException("index out of bounds"),
00321           _index(ex._index),
00322           _minIndex(ex._minIndex),
00323           _maxIndex(ex._maxIndex)
00324         {};
00325 
00326         // Destructor.
00327         virtual ~IndexOutOfBoundsException() throw()
00328         {};
00329 
00330         // Assignment operator.
00331         const IndexOutOfBoundsException&
00332             operator=(const IndexOutOfBoundsException& ex)
00333         {
00334             // Don't do self assignment.
00335             if (this != &ex)
00336             {
00337                 _index = ex._index;
00338                 _minIndex = ex._minIndex;
00339                 _maxIndex = ex._maxIndex;
00340             }
00341 
00342             return (*this);
00343         };
00344 
00345         // Returns the out-of-bounds index.
00346         int getIndex() const
00347         {
00348             return(_index);
00349         };
00350 
00351         // Returns the minimum allowed index value.
00352         int getMinIndex() const
00353         {
00354             return (_minIndex);
00355         };
00356 
00357         // Returns the maximum allowed index value.
00358         int getMaxIndex() const
00359         {
00360             return (_maxIndex);
00361         };
00362 
00363     protected:
00364     private:
00365     //-----------------------------------------------------------
00366     // Member data.
00367     //
00368     public:
00369     protected:
00370     private:
00371         int _index;
00372         int _minIndex;
00373         int _maxIndex;
00374 };
00375 #endif  // !SMC_NO_EXCEPTIONS
00376 
00377 //
00378 // end of Exception Classes.
00379 //---------------------------------------------------------------
00380 
00381 class State
00382 {
00383 //-----------------------------------------------------------
00384 // Member functions.
00385 //
00386 public:
00387     const char* getName() const
00388     {
00389         return (_name);
00390     };
00391 
00392     int getId() const
00393     {
00394         return (_stateId);
00395     }
00396 
00397 protected:
00398     State(const char *name, int stateId)
00399     : _name(NULL),
00400       _stateId(stateId)
00401     {
00402         if (name != NULL)
00403         {
00404             _name = copyString(name);
00405         }
00406         else
00407         {
00408             _name = copyString("NAME NOT SET");
00409         }
00410     };
00411 
00412     virtual ~State()
00413     {
00414         if (_name != NULL)
00415         {
00416             delete[] _name;
00417             _name = NULL;
00418         }
00419     };
00420 
00421 private:
00422     // Make the default and copy constructors private to
00423     // prevent their use.
00424     State() {}
00425     State(const State&) {}
00426 
00427 //-----------------------------------------------------------
00428 // Member data.
00429 //
00430 public:
00431 protected:
00432     // This state's printable name.
00433     char *_name;
00434 
00435     // This state's unique identifier.
00436     int _stateId;
00437 
00438 private:
00439 };
00440 
00441 class FSMContext
00442 {
00443 //-----------------------------------------------------------
00444 // Nested classes.
00445 //
00446 public:
00447 protected:
00448 private:
00449     // Implements the state stack.
00450     class StateEntry
00451     {
00452     //-------------------------------------------------------
00453     // Member functions.
00454     //
00455     public:
00456         StateEntry(State *state, StateEntry *next)
00457         : _state(state),
00458           _next(next)
00459         {};
00460 
00461         ~StateEntry()
00462         {
00463             _state = NULL;
00464             _next = NULL;
00465         };
00466 
00467         State* getState()
00468         {
00469             return(_state);
00470         };
00471 
00472         StateEntry* getNext()
00473         {
00474             return(_next);
00475         };
00476 
00477     protected:
00478     private:
00479     //-------------------------------------------------------
00480     // Member data.
00481     //
00482     public:
00483     protected:
00484     private:
00485         State *_state;
00486         StateEntry *_next;
00487 
00488     //-------------------------------------------------------
00489     // Friends
00490     //
00491         friend class FSMContext;
00492     };  // end of class StateEntry
00493 
00494 //-----------------------------------------------------------
00495 // Member functions
00496 //
00497 public:
00498     // Destructor.
00499     virtual ~FSMContext()
00500     {
00501         StateEntry *state;
00502 
00503         if (_transition != NULL)
00504         {
00505             delete[] _transition;
00506             _transition = NULL;
00507         }
00508 
00509         // But we did allocate the state stack.
00510         while (_state_stack != NULL)
00511         {
00512             state = _state_stack;
00513             _state_stack = _state_stack->_next;
00514             delete state;
00515         }
00516     };
00517 
00518     // Comparison and assignment operators
00519     // Assignment operator
00520     FSMContext& operator=(const FSMContext& fsm)
00521     {
00522         // Don't do the assignment if the left and right
00523         // hand sides are the same object.
00524         if (this != &fsm)
00525         {
00526             _state = fsm._state;
00527         }
00528 
00529         return(*this);
00530     };
00531 
00532     // Starts the finite state machine running by executing
00533     // the initial state's entry actions.
00534     virtual void enterStartState() = 0;
00535 
00536     // Exact same object (is it me?)
00537     int same(const FSMContext& fsm) const
00538     {
00539         return(this == &fsm);
00540     };
00541 
00542     // Returns the debug flag's current setting.
00543     bool getDebugFlag()
00544     {
00545         return(_debug_flag);
00546     };
00547 
00548     // Sets the debug flag. A true value means debugging
00549     // is on and false means off.
00550     void setDebugFlag(bool flag)
00551     {
00552         _debug_flag = flag;
00553         return;
00554     };
00555 
00556 #ifdef SMC_USES_IOSTREAMS
00557     // Returns the stream to which debug output is written.
00558     std::ostream& getDebugStream()
00559     {
00560         return (*_debug_stream);
00561     };
00562 
00563     // Sets the debug output stream.
00564     void setDebugStream(std::ostream& debug_stream)
00565     {
00566         _debug_stream = &debug_stream;
00567         return;
00568     }
00569 #endif  // SMC_USES_IOSTREAMS
00570 
00571     // Is this state machine already inside a transition?
00572     // Yes if state is null.
00573     bool isInTransition() const
00574     {
00575         return(_state == NULL ? true : false);
00576     };
00577 
00578     // Returns the current transition's name.
00579     // Used only for debugging purposes.
00580     char* getTransition()
00581     {
00582         return (_transition);
00583     };
00584 
00585     // Saves away the transition name only if debugging
00586     // is turned on.
00587     void setTransition(const char *transition)
00588     {
00589         if (_transition != NULL)
00590         {
00591             delete[] _transition;
00592             _transition = NULL;
00593         }
00594 
00595         _transition = copyString(transition);
00596 
00597         return;
00598     };
00599 
00600     // Clears the current state.
00601     void clearState()
00602     {
00603         _previous_state = _state;
00604         _state = NULL;
00605     };
00606 
00607     // Returns the state which a transition left.
00608     // May be NULL.
00609     State* getPreviousState()
00610     {
00611         return (_previous_state);
00612     }
00613 
00614     // Sets the current state to the specified state.
00615     void setState(const State& state)
00616     {
00617         _state = const_cast<State *>(&state);
00618 
00619         if (_debug_flag == true)
00620         {
00621 #ifdef SMC_USES_IOSTREAMS
00622             *_debug_stream << "ENTER STATE     : "
00623                            << _state->getName()
00624                            << std::endl;
00625 #else
00626             TRACE("ENTER STATE     : %s\n\r",
00627                   _state->getName());
00628 #endif  // SMC_USES_IOSTREAMS
00629         }
00630     };
00631 
00632     // Returns true if the state stack is empty and false
00633     // otherwise.
00634     bool isStateStackEmpty() const
00635     {
00636         return (_state_stack == NULL);
00637     }
00638 
00639     // Returns the state stack's depth.
00640     int getStateStackDepth() const
00641     {
00642         StateEntry *state_ptr;
00643         int retval;
00644 
00645         for (state_ptr = _state_stack, retval = 0;
00646              state_ptr != NULL;
00647              state_ptr = state_ptr->getNext(), ++retval)
00648             ;
00649 
00650         return (retval);
00651     }
00652 
00653     // Push the current state on top of the state stack
00654     // and make the specified state the current state.
00655     void pushState(const State& state)
00656     {
00657         StateEntry *new_entry;
00658 
00659         // Do the push only if there is a state to be pushed
00660         // on the stack.
00661         if (_state != NULL)
00662         {
00663             new_entry = new StateEntry(_state, _state_stack);
00664             _state_stack = new_entry;
00665         }
00666 
00667         _state = const_cast<State *>(&state);
00668 
00669         if (_debug_flag == true)
00670         {
00671 #ifdef SMC_USES_IOSTREAMS
00672             *_debug_stream << "PUSH TO STATE   : "
00673                            << _state->getName()
00674                            << std::endl;
00675 #else
00676             TRACE("PUSH TO STATE   : %s\n\r",
00677                   _state->getName());
00678 #endif  // SMC_USES_IOSTREAMS
00679         }
00680     };
00681 
00682     // Make the state on top of the state stack the
00683     // current state.
00684     void popState()
00685     {
00686         StateEntry *entry;
00687 
00688         // Popping when there was no previous push is an error.
00689 #ifdef SMC_NO_EXCEPTIONS
00690         assert(_state_stack != NULL);
00691 #else
00692         if (_state_stack == NULL)
00693         {
00694             throw PopOnEmptyStateStackException();
00695         }
00696 #endif  // SMC_NO_EXCEPTIONS
00697 
00698         _state = _state_stack->getState();
00699         entry = _state_stack;
00700         _state_stack = _state_stack->getNext();
00701         delete entry;
00702 
00703         if (_debug_flag == true)
00704         {
00705 #ifdef SMC_USES_IOSTREAMS
00706             *_debug_stream << "POP TO STATE    : "
00707                            << _state->getName()
00708                            << std::endl;
00709 #else
00710             TRACE("POP TO STATE    : %s\n\r",
00711                   _state->getName());
00712 #endif  // SMC_USES_IOSTREAMS
00713         }
00714     };
00715 
00716     // Remove all states from the state stack.
00717     void emptyStateStack()
00718     {
00719         StateEntry *state_ptr,
00720                    *next_ptr;
00721 
00722         for (state_ptr = _state_stack;
00723              state_ptr != NULL;
00724              state_ptr = next_ptr)
00725         {
00726             next_ptr = state_ptr->getNext();
00727             delete state_ptr;
00728         }
00729 
00730         _state_stack = NULL;
00731     };
00732 
00733 protected:
00734     // Default constructor.
00735     FSMContext(const State& state)
00736     : _state(const_cast<State *>(&state)),
00737       _previous_state(NULL),
00738       _state_stack(NULL),
00739       _transition(NULL),
00740 #ifdef SMC_USES_IOSTREAMS
00741       _debug_flag(false),
00742       _debug_stream(&std::cerr)
00743 #else
00744       _debug_flag(false)
00745 #endif  // SMC_USES_IOSTREAMS
00746     {};
00747 
00748 private:
00749     // I don't believe that it makes sense to copy a
00750     // context. It may make sense to copy the application
00751     // class but the new object is *not* in the same
00752     // state as the old - the new object must start in
00753     // the FSM's initial state. Therefore, the copy
00754     // constructor is private in order to prevent it
00755     // being used.
00756     FSMContext(const FSMContext&)
00757     {};
00758 
00759 //-----------------------------------------------------------
00760 // Member data
00761 //
00762 public:
00763 protected:
00764     // The current state of the finite state machine.
00765     State *_state;
00766 
00767     // Remember which state a transition left.
00768     State *_previous_state;
00769 
00770     // The stack of pushed states.
00771     StateEntry *_state_stack;
00772 
00773     // The current transition *name*. Use for debugging
00774     // purposes.
00775     char *_transition;
00776 
00777 private:
00778     // When this flag is set to true, this class will print
00779     // out debug messages.
00780     bool _debug_flag;
00781 
00782 // Include the following only if C++ iostreams are being used.
00783 #ifdef SMC_USES_IOSTREAMS
00784     // When FSM debugging is on, debug messages will be
00785     // written to this output stream. This stream is set to
00786     // standard error by default.
00787     std::ostream *_debug_stream;
00788 #endif  // SMC_USES_IOSTREAMS
00789 };  // end of class FSMContext
00790 }  // namespace statemap
00791 
00792 //
00793 // CHANGE LOG
00794 // $Log: statemap.h,v $
00795 // Revision 1.15  2009/11/24 20:42:39  cwrapp
00796 // v. 6.0.1 update
00797 //
00798 // Revision 1.14  2009/03/01 18:20:40  cwrapp
00799 // Preliminary v. 6.0.0 commit.
00800 //
00801 // Revision 1.13  2008/05/20 18:31:12  cwrapp
00802 // ----------------------------------------------------------------------
00803 //
00804 // Committing release 5.1.0.
00805 //
00806 // Modified Files:
00807 //  Makefile README.txt smc.mk tar_list.txt bin/Smc.jar
00808 //  examples/Ant/EX1/build.xml examples/Ant/EX2/build.xml
00809 //  examples/Ant/EX3/build.xml examples/Ant/EX4/build.xml
00810 //  examples/Ant/EX5/build.xml examples/Ant/EX6/build.xml
00811 //  examples/Ant/EX7/build.xml examples/Ant/EX7/src/Telephone.java
00812 //  examples/Java/EX1/Makefile examples/Java/EX4/Makefile
00813 //  examples/Java/EX5/Makefile examples/Java/EX6/Makefile
00814 //  examples/Java/EX7/Makefile examples/Ruby/EX1/Makefile
00815 //  lib/statemap.jar lib/C++/statemap.h lib/Java/Makefile
00816 //  lib/Php/statemap.php lib/Scala/Makefile
00817 //  lib/Scala/statemap.scala net/sf/smc/CODE_README.txt
00818 //  net/sf/smc/README.txt net/sf/smc/Smc.java
00819 // ----------------------------------------------------------------------
00820 //
00821 // Revision 1.12  2007/12/28 12:34:40  cwrapp
00822 // Version 5.0.1 check-in.
00823 //
00824 // Revision 1.11  2007/08/05 12:58:54  cwrapp
00825 // Version 5.0.1 check-in. See net/sf/smc/CODE_README.txt for more information.
00826 //
00827 // Revision 1.10  2007/01/15 00:23:50  cwrapp
00828 // Release 4.4.0 initial commit.
00829 //
00830 // Revision 1.9  2006/07/11 18:28:22  cwrapp
00831 // Move SmcException::copyString() to a package-wide routine.
00832 //
00833 // Revision 1.8  2006/04/22 12:45:24  cwrapp
00834 // Version 4.3.1
00835 //
00836 // Revision 1.7  2005/06/08 11:09:14  cwrapp
00837 // + Updated Python code generator to place "pass" in methods with empty
00838 //   bodies.
00839 // + Corrected FSM errors in Python example 7.
00840 // + Removed unnecessary includes from C++ examples.
00841 // + Corrected errors in top-level makefile's distribution build.
00842 //
00843 // Revision 1.6  2005/05/28 18:44:13  cwrapp
00844 // Updated C++, Java and Tcl libraries, added CSharp, Python and VB.
00845 //
00846 // Revision 1.2  2005/02/21 19:01:42  charlesr
00847 // Changed State::_id to State::_stateId because of Object-C++
00848 // reserved word conflict.
00849 //
00850 // Revision 1.1  2004/05/31 13:44:41  charlesr
00851 // Added support for non-iostreams output.
00852 //
00853 // Revision 1.0  2003/12/14 20:37:49  charlesr
00854 // Initial revision
00855 
00856 #endif  // SMCLIB__STATEMAP_H_


smclib
Author(s): Various
autogenerated on Thu Aug 17 2017 03:12:46