home *** CD-ROM | disk | FTP | other *** search
/ Prima Shareware 3 / DuCom_Prima-Shareware-3_cd1.bin / PROGRAMO / C / OOPSV / OOPSLIB.ZIP / STATE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-01  |  26.5 KB  |  1,037 lines

  1. //==========================================
  2. //===== REALISATION DE LA CLASSE STATE =====
  3. //==========================================
  4.  
  5. //----- composition de la classe
  6. #include "statelis.hpp"  // pour la pile des etats
  7. #include "stateerr.hpp"  // pour les messages d'erreur
  8. #include "state.hpp"     // interface de la classe
  9. #include "allcodes.cod"  // pour NOT_A_STATE et MAX_STATE_SIZE
  10. // Test des inclusions
  11. #ifndef STATE_SYSTEME
  12. #error The variable STATE_SYSTEME must be defined [file STATE.CFG]
  13. #endif
  14. #ifndef STATE_COMPILER
  15. #error The variable STATE_COMPILER must be defined [file STATE.CFG]
  16. #endif
  17. //----- fonctions de service
  18. #if STATE_USE_EXCEPT == 1
  19. #include <except.h>      // pour "terminate"   
  20. #endif
  21. #include <stdlib.h>      // pour "exit"
  22. //----- conditionnel car affichage
  23. #if STATE_SYSTEME == STATE_DOS
  24. #include <iostream.h>    // pour les COUT
  25. #if STATE_COMPILER == STATE_BORLAND
  26. #include <alloc.h>      // pour les tests de memoire
  27. #endif
  28. #if STATE_COMPILER == STATE_MICROSOFT
  29. #include <malloc.h>      // pour les tests de memoire
  30. #endif
  31. #endif
  32. #if STATE_SYSTEME == STATE_WINDOWS
  33. #if STATE_COMPILER == STATE_BORLAND
  34. #include <owl\dialog.h>
  35. #include <owl\controlb.h>
  36. #else
  37. #error Windows code is dependant on BORLAND CPP V4.x compilers
  38. #endif
  39. #endif
  40.  
  41.  
  42. // nom de la version liee aux outils de taduction
  43. const char* State::version = "Version 1.0a";
  44. //pour eviter les recursions sur les pre/post conditions
  45. int         State::ppConditionInUse = 0;
  46. #ifdef STATE_DEBUG
  47. // ===== Comptage des etats crees - detruits =====
  48. int State::nbAlive = 0;
  49. // ===== Comptage des etats crees ================
  50. long State::nbCreated = 0L;
  51. #endif
  52.  
  53. // ===== Definition de l'indicateur GLOBAL d'erreur =====
  54. // = cet indicateur fait office de ERRNO pour les etats =
  55. // = Il n'est positionne qu'une seule fois afin de      =
  56. // = la cause initiale de l'exception, meme en cas de   =
  57. // = levee d'exeption multiple.                         =
  58. int State::globalError = 0;
  59. //=======================================================
  60.  
  61. // ======= Definition de l'indicateur de Controle =======
  62. // = Cet indicateur signale si les etats courants des   =
  63. // = objets doivent etre calcules et si les test d'     =
  64. // = executabilite des methodes executes.               =
  65. // = Les controles sont invalides pendant l'execution   =
  66. // = de methodes constructeurs.                         =
  67. int   State::nbInvalidated                 = 0;
  68. void* State::invalidateCtrl[MAXINVALIDATE] = {0};  
  69. // ======================================================
  70.  
  71.  
  72. // ====== Definition de la pile des etats courants ======
  73. StateList* State::pile = new StateList();
  74. //=======================================================
  75.  
  76. State::State(State& source)
  77. {
  78. #ifdef STATE_DEBUG
  79.   State::nbAlive++;
  80.   State::nbCreated++;
  81. #endif
  82.  
  83.   if(!source.currentSize)
  84.   {
  85.     if (!State::globalError)
  86.     { 
  87.       State::globalError = 11;
  88.     }
  89. #if STATE_USE_EXCEPT == 1
  90.     throw StateInternalError(11);
  91. #else
  92.     State::terminate();
  93. #endif
  94.   }
  95.   else
  96.   {
  97.     currentSize = source.currentSize;
  98. /*
  99.     value   = new int[MAX_STATE_SIZE];
  100.     for(int i=0;i<currentSize;i++)
  101.     {
  102.      value[i] = source.value[i];
  103.     }
  104. */
  105.     value = source.value;
  106.     source.value = 0;  /* to avoid the destruction */
  107.   }
  108. }
  109.  
  110. State::State(int tailleUtile)
  111. {
  112. #ifdef STATE_DEBUG
  113.   State::nbAlive++;
  114.   State::nbCreated++;
  115. #endif
  116.  
  117.   if ( (tailleUtile==0)||(tailleUtile>MAX_STATE_SIZE))
  118.   {
  119.     if (!State::globalError)
  120.     { /* pour ne pas perdre la cause initiale de l'erreur */
  121.       State::globalError = 1;
  122.     }
  123. #if STATE_USE_EXCEPT == 1
  124.     throw StateInternalError(1);
  125. #else
  126.     State::terminate();
  127. #endif
  128.   }
  129.   else
  130.   {
  131.     currentSize = tailleUtile;
  132.     value   = new int[MAX_STATE_SIZE];
  133.   }
  134. }
  135.  
  136. State::~State()
  137. {
  138. #ifdef STATE_TRACE
  139.   cout << "State::~State" << endl;
  140. #endif
  141. #ifdef STATE_DEBUG
  142.   State::nbAlive--;
  143. #endif
  144.   if (value)
  145.   {
  146. #if STATE_OLD_COMPILER == 0
  147.     delete [] value;
  148. #else
  149.     delete value;
  150. #endif
  151.   }
  152. }
  153.  
  154. #ifdef STATE_DEBUG
  155. int  State::getStackSize()
  156. {
  157.   return pile->size();
  158. }
  159. int  State::getNbAlive()
  160. {
  161.   return State::nbAlive;
  162. }
  163. long  State::getNbCreated()
  164. {
  165.   return State::nbCreated;
  166. }
  167. #endif
  168.  
  169. void State::display(char* phrase)
  170. {
  171. #if STATE_SYSTEME == STATE_WINDOWS
  172.   char msgTexte[100];
  173.   char tmpBuff [20];
  174. #endif
  175.  
  176.  
  177.   int i;
  178. #if STATE_SYSTEME == STATE_DOS
  179.   if (phrase)
  180.   {
  181.      cout << phrase << "   ";
  182.   }
  183.   cout << "State value : ";
  184. #endif
  185. #if STATE_SYSTEME == STATE_WINDOWS
  186.   if(phrase)
  187.   {
  188.      strcpy(msgTexte,phrase);
  189.      strcat(msgTexte,"\tState value [ ");
  190.   }
  191.   else
  192.   {
  193.      strcpy(msgTexte,"State value [ ");
  194.   }
  195. #endif
  196.   for(i=0;i<currentSize;i++)
  197.   {
  198. #if STATE_SYSTEME == STATE_DOS
  199.      cout << value[i];
  200. #endif
  201. #if STATE_SYSTEME == STATE_WINDOWS
  202.      itoa(value[i],tmpBuff,10);
  203.      strcat(msgTexte,tmpBuff);
  204. #endif
  205.      if (i<currentSize-1)
  206.      {
  207. #if STATE_SYSTEME == STATE_DOS
  208.         cout << " , ";
  209. #endif
  210. #if STATE_SYSTEME == STATE_WINDOWS
  211.         strcat(msgTexte,",");
  212. #endif
  213.      }
  214.   }
  215. #if STATE_SYSTEME == STATE_DOS
  216.   cout << endl;
  217. #endif
  218. #if STATE_SYSTEME == STATE_WINDOWS
  219.   strcat(msgTexte,"]");
  220.   MessageBox(0,msgTexte,"STATE VALUE",MB_OK);
  221. #endif
  222. }
  223.  
  224. void State::warning(char* message)
  225. {
  226. #if STATE_SYSTEME == STATE_DOS
  227.      cout << message << endl;
  228. #endif
  229. #if STATE_SYSTEME == STATE_WINDOWS
  230.   MessageBox(0,message,"STATE WARNING",MB_OK);
  231. #endif
  232. }
  233.  
  234. void State::set(int rang, int stateCode)
  235. {
  236.   if ((rang<currentSize)&&(rang>=0))
  237.   {
  238.      value[rang]=stateCode;
  239.   }
  240.   else
  241.   {
  242.      if (!State::globalError)
  243.      { /* pour ne pas perdre la cause initiale de l'erreur */
  244.        State::globalError = 2;
  245.      }
  246. #if STATE_USE_EXCEPT == 1
  247.      throw StateInternalError(2);
  248. #else
  249.      State::terminate();
  250. #endif
  251.   }
  252. }
  253.  
  254. State* State::estPermise(int classCode,int methodCode,int light)
  255. {
  256. #ifdef STATE_TRACE
  257. #if STATE_SYSTEME == STATE_DOS
  258.   cout << "State::estPermise(classCode["<< classCode <<"],methodCode["<< methodCode <<"])" << endl;   
  259. #endif
  260. #endif
  261.   /* ================================================== */
  262.   /* ===== controle effectif de la permission.    ===== */
  263.   /* ===== Le "classCode" est utilise pour savoir ===== */
  264.   /* ===== ou commencer la recherche.             ===== */
  265.   /* ================================================== */
  266.  
  267.  
  268.     int rang;
  269.     int etat;
  270. #ifdef STATE_TRACE
  271. #if STATE_SYSTEME == STATE_DOS
  272.     int etatSvg;
  273. #endif
  274. #endif
  275.     int permi;
  276.     int interdit;
  277.     int rangPermi;    /* rang correspond au package */
  278.     int rangInterdit; /* rang correspond au package */
  279.     int statePermi;   /* code de l'etat dans la classe */
  280.     int stateInterdit;/* code de l'etat dans la classe*/
  281.     int code;
  282.     int currentClass;
  283.  
  284.     permi    = 0;
  285.     interdit = 0;
  286. #ifdef STATE_TRACE    
  287.     this->display();
  288. #endif
  289.     /* ==================================== */
  290.     /* ===== RECHERCHE SI EST-PERMISE ===== */
  291.     /* ==================================== */
  292.     rang = 0;
  293.     while( (rang<currentSize)&&(!permi) )
  294.     {
  295.       etat = value[rang];
  296. #ifdef STATE_TRACE
  297. #if STATE_SYSTEME == STATE_DOS
  298.       etatSvg = etat;
  299. #endif
  300. #endif
  301.       /*=== Balayage des champs de l'etat courant ===== */
  302.       while( (etat!=NOT_A_STATE)&&(!permi) )
  303.       {
  304.     int i;
  305.  
  306.     /* === recherche de la classe definissant l'etat === */
  307.     /* === actuellement analyse                      === */
  308. /* ===== ANCIENNE VERSION: Heritage simple ===== */
  309. //      currentClass = classCode;   /* la recherche commence en bas */
  310. //      while((currentClass>=0)&&
  311. //             State::tabPermise[
  312. //                               currentClass*MAX_STATES*MAX_METHOD_BY_STATE*2
  313. //                              +                   etat*MAX_METHOD_BY_STATE*2
  314. //                               ] == NOT_DEFINED)
  315. //      {
  316. //        currentClass = State::tabClassAnc[currentClass*MAX_ANC_CLASSES];
  317. //      }
  318. //
  319. /* ===== NOUVELLE VERSION ===== */
  320.     currentClass = State::classeDefiniEtatP(classCode,etat);
  321. /* ============================ */
  322.  
  323.     if (currentClass<0)
  324.     {
  325. #if STATE_SYSTEME == STATE_DOS
  326.       cout << "EstPermise/allowance: No class defines the state " << etat << endl;
  327. #endif
  328. #if STATE_SYSTEME == STATE_WINDOWS
  329.       MessageBox(0,"EstPermise/allowance: No class defines the recherched state","STATE EST PERMISE",MB_OK);
  330. #endif
  331.       exit(1);
  332.     }
  333.  
  334.     /* === balayage des methodes permises === */
  335.     i=0;
  336.     while( (!permi)&&
  337.            (State::tabPermise[
  338.                    currentClass*MAX_STATES*MAX_METHOD_BY_STATE*2
  339.                   +                  (etat*MAX_METHOD_BY_STATE+i)*2
  340.                  ] != NOT_A_METHOD)
  341.            )
  342.     {
  343.       if (State::tabPermise[
  344.                  currentClass*MAX_STATES*MAX_METHOD_BY_STATE*2
  345.                 +                  (etat*MAX_METHOD_BY_STATE+i)*2
  346.                    ] == methodCode)
  347.       { 
  348.         permi     = currentClass+1; /* pour memoriser le niveau d'acceptation dans le package   */
  349.         rangPermi = rang;           /* et tester si il y a eu redefinition dans le meme pachage */
  350.         statePermi=etat;            /* en cas d'etats contradictoires dans la meme classe suite a une fusion */
  351. #ifdef STATE_TRACE
  352. #if STATE_SYSTEME == STATE_DOS
  353.         cout << "Method accepted in the class   : " << currentClass ;
  354.         cout << "                in the package : " << rang ;
  355.         cout << "                by the state   : " << etat << endl;
  356. #endif
  357. #endif
  358.         code  = State::tabPermise[
  359.                        currentClass*MAX_STATES*MAX_METHOD_BY_STATE*2
  360.                       +                 ((etat*MAX_METHOD_BY_STATE+i)*2)+1
  361.                      ];
  362.       }
  363.       else
  364.       {
  365.         i++;
  366.       }
  367.     }
  368.     /* passage a la suite ssi ... */
  369.     if(!permi)
  370.     {
  371.       etat = State::tabAncestor[etat];
  372.     }
  373.       }
  374.       rang++;
  375.     } /* fin du while*/
  376.     
  377.     /* ====================================== */
  378.     /* ===== RECHERCHE SI EST-INTERDITE ===== */
  379.     /* ====================================== */
  380.     rang = 0;
  381.     while( (rang<currentSize)&&(!interdit) )
  382.     {
  383.       etat = value[rang];
  384. #ifdef STATE_TRACE
  385. #if STATE_SYSTEME == STATE_DOS
  386.       etatSvg = etat;
  387. #endif
  388. #endif
  389.       /*=== recherche de l'interdiction de la methode ===== */
  390.       while( (etat!=NOT_A_STATE) && (!interdit) )
  391.       {
  392.     int i;
  393.  
  394.     /* === recherche de la classe definissant l'etat === */
  395.     /* === actuellement analyse                      === */
  396. /* ===== ANCIENNE VERSION: HEritage simple ===== */
  397. //      currentClass = classCode;   /* la recherche commence en bas */
  398. //      while((currentClass>=0)&&
  399. //             State::tabInterdite[
  400. //                                 currentClass*MAX_STATES*MAX_METHOD_BY_STATE
  401. //                                +                   etat*MAX_METHOD_BY_STATE
  402. //                                 ] == NOT_DEFINED)
  403. //      {
  404. //        currentClass = State::tabClassAnc[currentClass*MAX_ANC_CLASSES];
  405. //      }
  406. /* ===== NOUVELLE VERSION ===== */
  407.     currentClass = State::classeDefiniEtatI(classCode,etat);
  408. /* ============================ */
  409.  
  410.     if (currentClass<0)
  411.     {
  412. #if STATE_SYSTEME == STATE_DOS
  413.       cout << "EstPermise/refused: No class defines the state " << etat << endl;
  414. #endif
  415. #if STATE_SYSTEME == STATE_WINDOWS
  416.       MessageBox(0,"EstPermise/refused: No class defines the recherched state","STATE EST PERMISE",MB_OK);
  417. #endif
  418.       exit(1);
  419.     }
  420.  
  421.     /* === balayage des methodes interdites === */
  422.     i=0;
  423.     while( (!interdit)&&
  424.            (State::tabInterdite[
  425.                      currentClass*MAX_STATES*MAX_METHOD_BY_STATE
  426.                     +                  (etat*MAX_METHOD_BY_STATE+i)
  427.                    ] != NOT_A_METHOD)
  428.            )
  429.     {
  430.       if (State::tabInterdite[
  431.                    currentClass*MAX_STATES*MAX_METHOD_BY_STATE
  432.                   +                  (etat*MAX_METHOD_BY_STATE+i)
  433.                  ] == methodCode)
  434.       { 
  435.         interdit     = (currentClass+1); /* memoriser le niveau de refus dans le package */
  436.         rangInterdit = rang;             /* et tester si il y a eu redefinition dans le meme pachage */   
  437.         stateInterdit=etat;              /* en cas d'etats contradictoires dans la meme classe suite a une fusion */
  438. #ifdef STATE_TRACE
  439. #if STATE_SYSTEME == STATE_DOS
  440.         cout << "Methode refused in the class   : " << currentClass ;
  441.         cout << "                in the package : " << rang;
  442.         cout << "                by the state   : " << etat << endl; 
  443. #endif
  444. #endif
  445.       }
  446.       else
  447.       {
  448.         i++;
  449.       }
  450.     }
  451.     /* passage a la suite ssi ... */
  452.     if (!interdit)
  453.     {
  454.       etat = State::tabAncestor[etat];
  455.     }
  456.       }
  457.       rang++;
  458.     } /* fin du while*/
  459.  
  460.     /* ==================== */
  461.     /* ===== RESULTAT ===== */
  462.     /* ==================== */
  463. #ifdef STATE_TRACE
  464. #if STATE_SYSTEME == STATE_DOS
  465.     cout << "Allowed   : " << permi << endl;
  466.     cout << "  package : " << rangPermi << endl;
  467.     cout << "  state   : " << statePermi << endl;
  468.     cout << "Refused   : " << interdit << endl;
  469.     cout << "  package : " << rangInterdit << endl;
  470.     cout << "  state   : " << stateInterdit << endl;
  471. #endif
  472. #endif
  473.     if (  (!permi)
  474.     ||(  interdit                                    /* erreur si interdit et       */
  475.        &&(interdit>permi)&&(rangPermi==rangInterdit) /* redef dans le meme package  */
  476.       )
  477.     ||(  interdit                                    /* erreur si interdit et       */
  478.        &&(rangInterdit!=rangPermi)                   /* permi dans un autre package */
  479.       )
  480.     ||(  interdit
  481.        &&(rangInterdit==rangPermi)                   /* erreur permi et interdi dans*/
  482.        &&(etatDescendDe(stateInterdit,statePermi))   /* le meme package mais interdi*/
  483.       )                                              /* est fil de permi            */
  484.        )  
  485.     {
  486. #ifdef STATE_TRACE
  487. #if STATE_SYSTEME == STATE_DOS
  488.       cout << "ERREUR : Method " << methodCode << " refused in the state " << etatSvg << endl;
  489. #endif
  490. #endif
  491.       if (!State::globalError)
  492.       { /* pour ne pas perdre la cause initiale de l'erreur */
  493.     State::globalError = 6;
  494.       }
  495. #if STATE_USE_EXCEPT == 1
  496.       throw StateBehaviorError(6);
  497. #else
  498.       State::terminate();
  499. #endif
  500.     }
  501. #if STATE_LIGHT == 0
  502.     if(!light)
  503.     {
  504.       /* ============== memoriser pour "estCorrecte" ============= */
  505.       /* Normalement, quand l'objet temporaire "this" est detruit  */
  506.       /* dans la methode qui appelle "estPermise", le destructeur  */
  507.       /* "State::~State" n'est pas appelle. De ce fait, le contenu */
  508.       /* du "StateListElem" cree dans "StateList::addLast" n'est   */
  509.       /* pas detruit!!                                             */
  510.       State::pile->addLast(new State(*this),code);
  511.     }
  512. #endif
  513.     return this;
  514. }
  515.  
  516. #if STATE_LIGHT == 0
  517. State* State::estCorrecte()
  518. {
  519. #ifdef STATE_TRACE
  520. #if STATE_SYSTEME == STATE_DOS
  521.   cout << "State::estCorrecte()" << endl;
  522. #endif
  523. #endif
  524.  
  525.   /* Tant que le controle n'est pas reactive pour la classe    */
  526.   /* des objets consideres, getCurrentState retourne des etats */
  527.   /* invalides qui ne sont pas empiles dans "estPermise". De ce*/
  528.   /* fait, il est inutile de depiler!!                         */
  529.  
  530.   State*  avant = State::pile->getLastState();
  531.   int     code  = State::pile->getLastCode();
  532.     
  533.     /* == controle effectif de la correction == */  
  534.     if (code>=0)
  535.     {
  536.       int rang;
  537.       int etat;
  538.       int i;
  539.       int correct=0;
  540.  
  541.       if (State::tabExitStates[code*MAX_EXIT_STATE]==SAME_STATE)
  542.       {
  543. #ifdef STATE_TRACE
  544. #if STATE_SYSTEME == STATE_DOS
  545.   cout << "   ==> REAL TEST [SAME]" << endl;
  546. #endif
  547. #if STATE_SYSTEME == STATE_WINDOWS
  548.     MessageBox(0,"REAL TEST because SAME_STATE","STATE EST CORRECTE",MB_OK);
  549. #endif
  550. #endif
  551.     /* l'arite de l'etat ne doit pas avoir changee */
  552.     correct=(currentSize==avant->currentSize);
  553.     /* normalement la facon dont est calcule l'etat reste la meme */
  554.     /* ATTENTION : A verifier si heritage multiple !!             */
  555.     /* de ce fait, chaque composant du nouvel etat doit descendre */
  556.     /* de son pendant dans l'etat de depart.                      */
  557.     for(rang=0;(rang<currentSize)&&(correct);rang++)
  558.     {
  559.       correct = etatDescendDe(value[rang],avant->value[rang]);
  560.     }
  561.       }
  562.       else
  563.       {
  564. #ifdef STATE_TRACE
  565. #if STATE_SYSTEME == STATE_DOS
  566.   cout << "   ==> REAL TEST [TRANSITION] (" << code << ")" << endl;
  567. #endif
  568. #endif
  569.     rang     = 0;
  570.     while( (rang<currentSize)&&(!correct) )
  571.     {
  572.       etat = value[rang];
  573.       i = 0;
  574.       while( (State::tabExitStates[code*MAX_EXIT_STATE+i]!=NOT_A_STATE)&&(!correct) )
  575.       {
  576.         if (etatDescendDe(etat,State::tabExitStates[code*MAX_EXIT_STATE+i])) {  correct=1;  }
  577.         else                                                                 {  i++;        }
  578.       }
  579.       rang++;
  580.     }
  581.       }
  582.       if (!correct)
  583.       {
  584. #ifdef STATE_TRACE
  585. #if STATE_SYSTEME == STATE_DOS
  586.     cout << "ERROR : incorrect transition (code = " << code << " )" << endl;
  587. #endif
  588. #endif
  589.     if (!State::globalError)
  590.     { /* pour ne pas perdre la cause initiale de l'erreur */
  591.       State::globalError = 7;
  592.     }
  593. #if STATE_USE_EXCEPT == 1
  594.     throw StateBehaviorError(7);
  595. #else
  596.     State::terminate();
  597. #endif
  598.       }
  599.     }
  600.     else
  601.     {
  602.       if (!State::globalError)
  603.       { /* pour ne pas perdre la cause initiale de l'erreur */
  604.     State::globalError = 10;
  605.       }
  606. #if STATE_USE_EXCEPT == 1
  607.       throw StateInternalError(10);
  608. #else
  609.       State::terminate();
  610. #endif
  611.     }
  612.     /* ========== */
  613.     State::pile->removeLast(); 
  614.     return this;
  615. }
  616. #endif
  617.  
  618. State* State::estInitial(int classCode)
  619. {
  620. #ifdef STATE_TRACE
  621. #if STATE_SYSTEME == STATE_DOS
  622.   cout << "State::estInitial" << endl;
  623. #endif
  624. #endif
  625.  
  626.   int i,rang,ok;
  627.  
  628.   if (tabInitial[classCode*MAX_INIT_STATE]==NOT_A_STATE)
  629.   {
  630.      return this; /* ok car alors par defaut ils sont TOUS initiaux !! */
  631.   }
  632.  
  633.   for (rang=0;rang<currentSize;rang++)
  634.   {
  635.     i  = 0;
  636.     ok = 0;
  637.     while (   (tabInitial[classCode*MAX_INIT_STATE+i]!=NOT_A_STATE)
  638.         &&(i<MAX_INIT_STATE)
  639.         &&(!ok)
  640.       )
  641.     {
  642.       if (value[rang]==tabInitial[classCode*MAX_INIT_STATE+i])
  643.       {
  644.     /* ok l'etat est initial.                        */
  645.     /* sortie du "while" et passage au "for" suivant */
  646.     ok = 1;
  647.       }
  648.       else
  649.       {
  650.     i++;
  651.     if (i==MAX_INIT_STATE)
  652.     {
  653.       if (!State::globalError)
  654.       { /* pour ne pas perdre la cause initiale de l'erreur */
  655.         State::globalError = 4;
  656.       }
  657. #if STATE_USE_EXCEPT == 1
  658.       throw StateInternalError(4);
  659. #else
  660.       State::terminate();
  661. #endif
  662.     }
  663.       }
  664.     }
  665.     if (!ok)
  666.     {
  667.       if (!State::globalError)
  668.       { /* pour ne pas perdre la cause initiale de l'erreur */
  669.     State::globalError = 3;
  670.       }
  671. #if STATE_USE_EXCEPT == 1
  672.       throw StateBehaviorError(3);
  673. #else
  674.       State::terminate();
  675. #endif
  676.     }
  677.   }
  678.   return this;
  679. }
  680.  
  681. State* State::estFinal(int classCode)
  682. {
  683. #ifdef STATE_TRACE
  684. #if STATE_SYSTEME == STATE_DOS
  685.   cout << "State::estFinal" << endl;
  686. #endif
  687. #endif
  688.  
  689.   int i,rang,ok;
  690.  
  691.   if (tabFinal[classCode*MAX_FINA_STATE]==NOT_A_STATE)
  692.   {
  693.      return this; /* ok car alors par defaut ils sont TOUS finaux !! */
  694.   }
  695.   
  696.   for (rang=0;rang<currentSize;rang++)
  697.   {
  698.     i  = 0;
  699.     ok = 0;
  700.  
  701.     while (  (tabFinal[classCode*MAX_FINA_STATE+i]!=NOT_A_STATE)
  702.        &&(i<MAX_FINA_STATE)
  703.        &&(!ok)
  704.       )
  705.     {
  706.       if (value[rang]==tabFinal[classCode*MAX_FINA_STATE+i])
  707.       {
  708.     /* ok l'etat est initial.                        */
  709.     /* sortie du "while" et passage au "for" suivant */
  710.     ok = 1;
  711.       }
  712.       else
  713.       {
  714.     i++;
  715.     if (i==MAX_FINA_STATE)
  716.     {
  717.       if (!State::globalError)
  718.       { /* pour ne pas perdre la cause initiale de l'erreur */
  719.         State::globalError = 4;
  720.       }
  721. #if STATE_USE_EXCEPT == 1
  722.       throw StateInternalError(4);
  723. #else
  724.       State::terminate();
  725. #endif
  726.     }
  727.       }
  728.     }
  729.     if (!ok)
  730.     {
  731.       if (!State::globalError)
  732.       { /* pour ne pas perdre la cause initiale de l'erreur */
  733.     State::globalError = 4;
  734.       }
  735. #if STATE_USE_EXCEPT == 1
  736.       throw StateBehaviorError(4);
  737. #else
  738.       State::terminate();
  739. #endif
  740.     }
  741.   }
  742.   return this;
  743. }
  744.  
  745. int State::rang(int etat)
  746. {
  747. #ifdef STATE_TRACE
  748. #if STATE_SYSTEME == STATE_DOS
  749.   cout << "State::rang(int etat)" << endl;
  750. #endif
  751. #endif
  752.  
  753.   int result=-1;
  754.   int i;
  755.   for(i=0;i<currentSize;i++)
  756.   {
  757.      if (value[i]==etat)
  758.      {
  759.         result=i;
  760.      }
  761.   }
  762.   return result;
  763. }
  764.  
  765. int State::etendre()
  766. {
  767. #ifdef STATE_TRACE
  768. #if STATE_SYSTEME == STATE_DOS
  769.   cout << "State::etendre()" << endl;
  770. #endif
  771. #endif
  772.  
  773.   if (currentSize == MAX_STATE_SIZE)
  774.   {
  775.      if (!State::globalError)
  776.      { /* pour ne pas perdre la cause initiale de l'erreur */
  777.        State::globalError = 3;
  778.      }
  779. #if STATE_USE_EXCEPT == 1
  780.      throw StateInternalError(3);
  781. #else
  782.      State::terminate();
  783. #endif
  784.   }
  785.   else
  786.   {
  787.      currentSize++;
  788.   }
  789.   return currentSize-1; // car directement utilise
  790. }
  791.  
  792. void State::terminate(void)
  793. {
  794.   extern char* BehaviorErrorMsg[];
  795. #if STATE_SYSTEME == STATE_DOS
  796.   cout << "STATE TERMINATE" << endl;
  797. #if STATE_USE_EXCEPT == 1
  798.   cout << "Error while treating the exception ('stack rollout')" << endl;
  799.   cout << "Initial error:" << endl;
  800. #endif
  801.   cout << "     code  = " << State::globalError << endl;
  802.   cout << "     texte = " << BehaviorErrorMsg[State::globalError] << endl;
  803. #endif
  804. #if STATE_SYSTEME == STATE_WINDOWS
  805.   char texte [512];
  806.   strcpy(texte,"Error while treating the exception ('stack rollout')\n");
  807.   strcat(texte,BehaviorErrorMsg[State::globalError]);
  808.   MessageBox(0,texte,"STATE TERMINATE",MB_OK);
  809. #endif
  810.   abort();
  811. }
  812. #ifdef STATE_DEBUG
  813. void State::memoryError(void)
  814. {
  815. #if STATE_SYSTEME == STATE_DOS
  816.   cout << endl << "STATE MEMORY ERROR" << endl;
  817.   State::audit();
  818. #endif
  819. #if STATE_SYSTEME  == STATE_DOS
  820. #if STATE_COMPILER  == STATE_BORLAND
  821.   cout << "Available memory : " << coreleft() << endl;
  822.   cout << "                   " << farcoreleft() << endl;
  823.   if(heapcheck()== _HEAPCORRUPT)
  824.   {
  825.     cout << "Heap is corrupted !!!" << endl;
  826.   }
  827.   else
  828.   {
  829.     cout << "Heap is OK" << endl;
  830.   }
  831. #endif
  832. #endif
  833. #if STATE_SYSTEME == STATE_DOS
  834.   cout << "Out of memory program aborted !!" << endl;
  835. #endif
  836. #if STATE_SYSTEME == STATE_WINDOWS
  837.   MessageBox(0,"Out of memory program aborted !!","STATE MEMORY",MB_OK);
  838. #endif
  839.   abort();
  840. }
  841. void State::audit(void)
  842. {
  843. #if STATE_SYSTEME == STATE_DOS
  844.   cout << endl << "STATE AUDIT" << endl;   
  845.   cout << "State stack size    : " << State::getStackSize() << endl;
  846.   cout << "Living states       : " << nbAlive << endl;
  847.   cout << "Total created states: " << nbCreated << endl;
  848. #endif
  849. }
  850.  
  851. #endif
  852. void State::invalidateCtrlFor(void* ptrObj)
  853. {
  854. #ifdef STATE_TRACE 
  855. #if STATE_SYSTEME == STATE_DOS
  856.   cout << "State::invalidateCtrlFor(void* ptrObj)" << endl;
  857. #endif
  858. #endif
  859.  
  860.   /* ===== test si possible ===== */
  861.   if (nbInvalidated==MAXINVALIDATE-1)
  862.   {
  863.     if (!State::globalError)
  864.     { /* pour ne pas perdre la cause initiale de l'erreur */
  865.       State::globalError = 7;
  866.     }
  867. #if STATE_USE_EXCEPT == 1
  868.     throw StateInternalError(7);
  869. #else
  870.     State::terminate();
  871. #endif
  872.   }
  873.   /* ========================== ajouter ========================== */
  874.   /* Il est inutile de rechercher si deja car il faut memoriser a  */
  875.   /* chaque fois pour le cas ou dans un constructeur d'une classe  */ 
  876.   /* FOO, des instances de la classe FOO sont construites (par     */
  877.   /* exemple) comme attributs.                                     */
  878.   /* ============================================================= */
  879.   invalidateCtrl[nbInvalidated] = ptrObj;
  880.   nbInvalidated++;
  881. }
  882.  
  883. void State::activateCtrlFor(void* ptrObj)
  884. {
  885. #ifdef STATE_TRACE 
  886. #if STATE_SYSTEME == STATE_DOS
  887.   cout << "State::activateCtrlFor(void* ptrObj)" << endl;
  888. #endif
  889. #endif
  890.   int i = 0;
  891.   int trouve = -1;
  892.   /* ========= recherche si effectivement ========== */
  893.   while(i<nbInvalidated)
  894.   { 
  895.     if (invalidateCtrl[i]==ptrObj)
  896.     {
  897.       trouve = i;
  898.       break;
  899.     }
  900.     i++;
  901.   }
  902.   if(trouve>-1)
  903.   {
  904.     if (trouve==nbInvalidated-1)
  905.     {
  906.       invalidateCtrl[trouve]=0;
  907.     }
  908.     else
  909.     {
  910.       invalidateCtrl[trouve]=invalidateCtrl[nbInvalidated-1];
  911.       invalidateCtrl[nbInvalidated-1]=0;
  912.     }
  913.     nbInvalidated--;
  914.   }
  915.   else
  916.   {
  917.     if (!State::globalError)
  918.     { /* pour ne pas perdre la cause initiale de l'erreur */
  919.       State::globalError = 9;
  920.     }
  921. #if STATE_USE_EXCEPT == 1
  922.     throw StateInternalError(9);
  923. #else
  924.     State::terminate();
  925. #endif
  926.   }
  927. }
  928.  
  929. int State::testActivatedFor(void* ptrObj)
  930. {
  931. #ifdef STATE_TRACE 
  932. #if STATE_SYSTEME == STATE_DOS
  933.   cout << "State::testActivatedFor(void* ptrObj)" << endl;
  934. #endif
  935. #endif
  936.   int i = 0;
  937.   /* ===== recherche si present ===== */
  938.   while(i<nbInvalidated)
  939.   { 
  940.     if (invalidateCtrl[i]==ptrObj)
  941.     {
  942.       return 0;
  943.     }
  944.     i++;
  945.   }
  946.   return 1;
  947. }
  948. /* Les methodes ci-dessous sont plus des fonctions libres de service que */
  949. /* de veritables metodes. Cependant, pour qu'elles portent le meme nom   */
  950. /* que les veritables methodes de la classe "State" (pour limiter les    */
  951. /* collisions de noms), elles ont ete declarees en tant que methodes.    */
  952.  
  953. int State::etatDescendDe(int fils, int pere)
  954. {
  955. #ifdef STATE_TRACE
  956. #if STATE_SYSTEME == STATE_DOS
  957.   cout << "State::etatDescendDe(fils(" << fils << "),pere(" << pere << ") )" << endl;     
  958. #endif
  959. #endif
  960.   while( (fils!=NOT_A_STATE)&&(fils!=pere) )
  961.   {
  962.     fils = State::tabAncestor[fils];
  963.   }
  964.   return (fils!=NOT_A_STATE);
  965. }
  966.  
  967. int State::classeDefiniEtatP(int codeClasse, int codeState)
  968. {
  969.   int classAncetre;
  970.   int result       = NOT_A_CLASS;
  971.   /* ==== recherche locale ==== */
  972.   if(   (codeClasse>=0)
  973.      && (State::tabPermise[codeClasse*MAX_STATES*MAX_METHOD_BY_STATE*2
  974.                +           codeState*MAX_METHOD_BY_STATE*2
  975.                ] != NOT_DEFINED)
  976.     )
  977.   {
  978.     return codeClasse;
  979.   }
  980.   else
  981.   /* ==== recherche parmi les ancetres */
  982.   { 
  983.     int  i       = 0;
  984.     classAncetre = State::tabClassAnc[codeClasse*MAX_ANC_CLASSES+i];
  985.     while(classAncetre!=NOT_A_CLASS)
  986.     {
  987.       result = classeDefiniEtatP(classAncetre,codeState);
  988.       if(result!=NOT_A_CLASS)
  989.       {
  990.     return result;
  991.       }
  992.       else
  993.       {
  994.     i++;
  995.     classAncetre = State::tabClassAnc[codeClasse*MAX_ANC_CLASSES+i];
  996.       }
  997.     }
  998.   }
  999.   return NOT_A_CLASS;
  1000. }
  1001.  
  1002. int State::classeDefiniEtatI(int codeClasse, int codeState)
  1003. {
  1004.   int classAncetre;
  1005.   int result       = NOT_A_CLASS;
  1006.   /* ==== recherche locale ==== */
  1007.   if(   (codeClasse>=0)
  1008.      && (State::tabInterdite[codeClasse*MAX_STATES*MAX_METHOD_BY_STATE
  1009.                  +           codeState*MAX_METHOD_BY_STATE
  1010.                 ] != NOT_DEFINED)
  1011.     )
  1012.   {
  1013.     return codeClasse;
  1014.   }
  1015.   else
  1016.   /* ==== recherche parmi les ancetres */
  1017.   { 
  1018.     int  i       = 0;
  1019.     classAncetre = State::tabClassAnc[codeClasse*MAX_ANC_CLASSES+i];
  1020.     while(classAncetre!=NOT_A_CLASS)
  1021.     {
  1022.       result = classeDefiniEtatI(classAncetre,codeState);
  1023.       if(result!=NOT_A_CLASS)
  1024.       {
  1025.     return result;
  1026.       }
  1027.       else
  1028.       {
  1029.     i++;
  1030.     classAncetre = State::tabClassAnc[codeClasse*MAX_ANC_CLASSES+i];
  1031.       }
  1032.     }
  1033.   }
  1034.   return NOT_A_CLASS;
  1035. }
  1036.  
  1037.