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