==JZcmd==

##!checkJZcmd = "result/check_States.genC.txt";
!checkXml = <:><&currdir>/check_States.genC.xml<.>;

Filepath outfile = &sOutfile; ##sOutfile is defined in the java calling environment: path to the out file which is
  written by <+>...<.+>

String stateMethodSuffix = stm.zsrcFile.variables.StateMethodSuffix;

Class classStateComposite = org.vishia.states.StateComposite;   ##used for instanceof check
Class classStateCompositeFlat = org.vishia.states.StateCompositeFlat;   ##used for instanceof check
Class classStateParallel = org.vishia.states.StateParallel;  ##used for instanceof check


subtext conditionaction(Obj trans)
<:>
  <:for:exitState:trans.exitStates>
      exit_<&exitState.src.stateName><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>);
  <.for>
      <&trans.code>
   
    
  <:for:entryState:trans.dstStateTree.entrySubStates>
      entry_<&entryState.name><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>);
      <:for:entryState2:entryState.entrySubStates>
        entry_<&entryState2.name><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>); 
        <:for:entryState3:entryState2.entrySubStates>
        entry_<&entryState3.name><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>);
          <:for:entryState4:entryState3.entrySubStates>
          entry_<&entryState4.name><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>); 
          <.for>
        <.for>
      <.for>
  <.for>

<.>




sub setSubStateNull(Obj state) 
{ ##if(state.src.stateName == "RemainOn"){ debug test; }
  if(state.subStates && (state.hasHistory || state.parallelParentState)){
    <:>
        thiz->state.state<&state.src.stateName> = kNull_<&state.src.stateName>_<&stm.zsrcFile.variables.StateSubStruct>;
          <.>
    for(substate:state.subStates) {
      call setSubStateNull (state = substate);
    }
  }
}





sub stateMethodArguments()
{ 
  for(arg:stm.zsrcFile.statefnargs) { <:><&arg><:hasNext>, <.hasNext><.>; }
}



main(){


<+><: >
   //first line
/*This file is generated from StateMGen.java */
<.+>
  for(includeline:stm.zsrcFile.includeLines) 
  { <+>
::::::#include <&includeline><.+>
  }
  <+>  
::::#include "<&outfile.name()>.h"
::::
:::://all entry-prototypes:<.+>
  for(state: stm.listStates)
  {
    <+>
::::::void entry_<&state.stateId><&stateMethodSuffix>(<:subtext:stateMethodArguments>);<.+>
  }
  <+>
::::<.+>  
  for(state: stm.listStates)
  {
    <+>
::::::void exit_<&state.stateId><&stateMethodSuffix>(<:subtext:stateMethodArguments>);<.+>
  }
  <+>
::::
::::<.+>
  for(state: stm.listStates)
  { Obj zsrcState = state.auxInfo().zsrcState; 
    if(state ?instanceof classStateParallel) {

                            <+>
                            ::::::    
                            ::::::    
                            :::::://genStateM: stateParallel    
                            ::::::static void
                              entry_<&state.stateId><&stateMethodSuffix>(<:subtext:stateMethodArguments>)
                            ::::::{ //genStateM: entry StateParallel. 
                            ::::::  <&stm.zsrcFile.variables.StateInstance>.state<&state.stateCtrl.stateId> =
                              k<&state.stateId>_<&stm.zsrcFile.variables.StateSubStruct>;
                            ::::::  #ifdef __DEBUG_entryprintf_States_Fwc__
                            ::::::    printf(" entry <&state.stateId>; parallel\n");
                            ::::::  #endif
                            ::::::}
                            ::::::
                            ::::::
                            ::::::INLINE_Fwc void
                              exit_<&state.stateId><&stateMethodSuffix>(<:subtext:stateMethodArguments>)
                            ::::::{ //genStateM: it is a parallelState , it is its own rootstate:
                              <&state.stateCtrl.stateId> 
                            ::::::  //<&stm.zsrcFile.variables.StateInstance>.state<&state.stateId> = 0;  //if a
                              parallel state has a history, set bit and preserve state nr
                            ::::::  #ifdef __DEBUG_entryprintf_States_Fwc__
                            ::::::    printf("   exit <&state.stateId>;\n");
                            ::::::  #endif
                            ::::::}
                            ::::::
                            ::::::
                            ::::::INLINE_Fwc int
                              trans_<&state.stateId><&stateMethodSuffix>(<:subtext:stateMethodArguments>)
                            ::::::{ //genStateM: parallelState
                            ::::::  //TODO transitions
                            ::::::  return 0;
                            ::::::}
                            ::::::
                            ::::::
                            ::::::<.+>
                            ##::::::INLINE_Fwc int switch_<&state.stateId><&stm.zsrcFile.variables.StateSubStruct>(
                              <:subtext:stateMethodArguments> )
                            ##::::::  //parallel<.+>
##      //call switchStates(stateComposite = state, recurs =1);

    } else {  //normal, non parallel, composite or simple:

                            <+>
                            ::::::    
                            ::::::    
                            ::::::    
                            ::::::static void
                              entry_<&state.stateId><&stateMethodSuffix>(<:subtext:stateMethodArguments>)
                            ::::::{ //genStateM: entry StateComposite or StateSimple. <.+>
    if(state.stateCtrl) { //note: if first composite of parallel, then it has not a root state.                         
                               
                            <+>
                            ::::::  <&stm.zsrcFile.variables.StateInstance>.state<&state.stateCtrl.stateId> =
                              k<&state.stateId>_<&stm.zsrcFile.variables.StateSubStruct>;<.+>
    }
    if(state.auxInfo().timeCondition) {                    <+>
                            ::::::  <&stm.zsrcFile.variables.StateInstance>.timer<&state.stateCtrl.stateId> =
                              <&state.auxInfo().timeCondition>;<.+>  
    }                                                      <+>
                            ::::::  <&state.auxInfo().zsrcState.entry.code>
                            ::::::  #ifdef __DEBUG_entryprintf_States_Fwc__
                            ::::::    printf(" entry <&state.stateId>;\n");
                            ::::::  #endif
                            ::::::}
                            ::::::
                            ::::::INLINE_Fwc void
                              exit_<&state.stateId><&stateMethodSuffix>(<:subtext:stateMethodArguments>)
                            ::::::{ 
                            ::::::  #ifdef __DEBUG_entryprintf_States_Fwc__
                            ::::::    printf("   exit <&state.stateId>;\n");
                            ::::::  #endif<.+>
    if(zsrcState.hasHistory) {                             <+>
                            ::::::  //It is a composite state with a history state. Mark the state number with the
                              inactive bit:
                            ::::::  <&stm.zsrcFile.variables.StateInstance>.state<&state.stateId> |= 0x80000000; <.+>
    } elsif(state.aParallelStates) {                       <+>
                            ::::::  //It is a composite state without a history state. Set the state number to zero.
                            ::::::  <&stm.zsrcFile.variables.StateInstance>.state<&stateComposite.stateId> = 0; <.+>
    }
                            <+>
                            ::::::  <&state.auxInfo().zsrcState.exit.code>
                            ::::::}
                            ::::::<.+>
##    debug;
##    if(state ?instanceof classStateComposite && (zsrcState.hasHistory || state.aParallelstates) ) {
##    <+>
##::::::
##::::::
##::::::int switchStates_<&state.stateId><&stm.zsrcFile.variables.StateSubStruct>( <:subtext:stateMethodArguments> )<.+>
             
##      call switchStates(stateComposite = state, recurs =1);
##    }


                            <+>
                            ::::::
                            ::::::
                            ::::::INLINE_Fwc int
                              trans_<&state.stateId><&stateMethodSuffix>(<:subtext:stateMethodArguments>)
                            ::::::{ int trans = 0;
                            ::::::  //genStateM: check all conditions of transitions, return on transition with != 0<.+>
                                 
      if(zsrcState.hasHistory || state.aParallelstates) { <+>
                            ::::::  //xxx trans =
                              switchStates_<&state.stateId><&stm.zsrcFile.variables.StateSubStruct>(<&stm.zsrcFile.calli
                              ngArgs>);<.+>     
      }
      Obj stateOwn = state;
      do {  //for own state and all enclosing states
        if(state.aTransitions) {
          for(trans: state.aTransitions) {
            if(trans.zsrcTrans.cond) {                  <+>  
                            ::::::::  if(<&trans.zsrcTrans.cond>) {<.+>
            } elsif(trans.zsrcTrans.time) {             <+>
                            ::::::::  if(<&stm.zsrcFile.variables.StateInstance>.timer<&state.stateCtrl.stateId> <0)
                              {<.+>
            } elsif(trans.zsrcTrans.joinStatesSrc) {             <+>
                            ::::::::  if(false /*join:<.+>
              for(stateJoin: trans.zsrcTrans.joinStatesSrc) {
                            <+><&stateJoin> <.+> 
              }
                            <+>*/) {<.+>
            } else {                                    <+>
                            ::::::::  if(false) { //genStateM: undefined condition, TODO.<.+>
            }
            call genTransitionFire(trans = trans);
                            <+>
                            ::::::  }
                            ::::::  else <.+>
          } ##for(state.transitions)           
        } else {                                      <+>
                            ::::::  //genStateM: no transitions.<.+>
        }//if state.aTransitions
        if(state.transJoins) {
          for(trans: state.transJoins) {                <+>
                            ::::::::  //StateMGen: join transition
                            ::::::::  if(<.+>
            if(trans.zsrcTrans.cond) {                  <+><&trans.zsrcTrans.cond> <.+>
            } else {                                    <+>true <.+>
            }
            for(joinState: trans.joinStates) {          <+>&&
              <&stm.zsrcFile.variables.StateInstance>.state<&joinState.stateCtrl.stateId> ==
              k<&joinState.auxInfo().zsrcState.stateName>_<&stm.zsrcFile.variables.StateSubStruct> <.+>
            }                                           <+>) {<.+>
            call genTransitionFire(trans = trans);
                            <+>
                            ::::::  }
                            ::::::  else <.+>
          } ##for(state.transitions)           
        }//if state.transJoins
        
        state = state.enclState;  //all transitions of StateCompositeFlat
        if(state ?instanceof classStateComposite || state ?instanceof classStateParallel) {
          state = null;
        } else {                                    <+>
                            ::::::  //genStateM: transitions of enclosing state: <&state.stateId><.+>
        }
      } while(state);  
                            <+>
                            ::::::  { //StateMGen: action in state. No transition switched.
                            ::::::    <&stateOwn.auxInfo().zsrcState.instate.code>
                            ::::::  }
                            ::::::  return trans;                           
                            ::::::}
                            ::::::
                            ::::::
                            ::::::<.+>
    }##NOT stateParallel
  }##for all states
  
  
##  for(rootState: stm.rootStates) {
##                                                    <+>
##                                                ::::::
##                                                ::::::
##                                                ::::::INLINE_Fwc int
  switch_<&rootState.stateId><&stm.zsrcFile.variables.StateSubStruct>( <:subtext:stateMethodArguments> )<.+>
##     call switchStates(stateComposite = rootState, recurs =1);
##  }
  
  
  
  
  <+>
:::://This method should be called in any step time. It decrements all timer which are set.
:::://
::::void stepStateTimer_<&stm.zsrcFile.variables.StateSubStruct>( <:subtext:stateMethodArguments> )
::::{<.+>
      for(rootState: stm.rootStates) {
        Obj srcState = rootState.auxInfo();
        if(srcState.hasTimer) { 
          String timer = <:><&stm.zsrcFile.variables.StateInstance>.timer<&rootState.stateId><.>;
          <+>
        ::::  if(<&timer> >=0) { 
        ::::    <&timer> -=1; 
        ::::  }<.+>        
      } }
  <+>
::::
::::}
::::
::::
::::
::::
::::
::::
::::int stepStates_<&stm.zsrcFile.variables.StateSubStruct>( <:subtext:stateMethodArguments> )<.+>
    call switchStatesMethodBody(stateComposite = stm.topState, recurs =1);
  <+>
::::<.+>
  
  
} ##main





sub genTransitionFire(Obj trans) 
{
   for(exitState:trans.exitStates) {         <+>
                            ::::::    exit_<&exitState.stateId><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>);<.+>  
   }                                         <+>  
                            ::::::    <:if:trans.zsrcTrans><&trans.zsrcTrans.code><.if><.+>
   for(entryState:trans.entryStates) {       <+>
                            ::::::    entry_<&entryState.stateId><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>);<.+> 
                              
   }                                         <+>    
                            ::::::    trans = mTransit_States_Fwc; <.+>
}


##recursively call of case for switch-state:
sub YYYswitchStates(Obj stateComposite, Num recurs = 0)
{                                         <+>
                            ::::::{ int trans = 0;                //set to true if transition has fired.<.+>
  if(stateComposite.aSubstates && stateComposite.aSubstates.length()>0) {
    //only if it has aSubstates:          <+>
                            ::::::  int ctSwitchState = 10;     //prevent too many transitions - a endless loop
                            ::::::  do { 
                            ::::::    trans &= ~mTransit_States_Fwc;
                            ::::    switch(<&stm.zsrcFile.variables.StateInstance>.state<&stateComposite.stateId>) {
                            ::::               //if the state was entried newly without define an inner state, then the
                              statedefault will be entered now.
                            ::::               //Note that the default state cannot be entered on entry action because
                              it is unknown in that time
                            ::::               //whether there will be an entry to a designated state.
                            ::::       case 0:
                              entry_<&stateComposite.stateDefault><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>);
                              //without break, do trans:
                            ::::       //switch to the current state:<.+>
    for(state : stateComposite.aSubstates) {
      Obj zsrcState = state.auxInfo().zsrcState;              <+>
                            ::::::::::       case k<&state.stateId>_State<&stateMethodSuffix>: trans |=
                              trans_<&state.stateId><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>); break;<.+>      
    }
                            <+>
                            ::::::    } //switch    
                            ::::::  } while((trans & mTransit_States_Fwc)    //continue checking transitions if one of
                              the has fired, it is run to completion.
                            ::::::      && <&stm.zsrcFile.variables.StateInstance>.state<&stateComposite.stateId> !=0 
                              //don't continue if the composite is inactive now.
                            ::::::      && --ctSwitchState >0);     //don't execute too may loops, only a safety check.
                              <.+>
  }                                       <+>
                            ::::::  //
                            ::::::  //for all parallel states: switch only if this state is the active one still. Regard
                              a leave of the state from any substate.<.+> 
##  for(state : stateComposite.aParallelstates) {
##                                          <+>
##                                      :::::: 
  if(<&stm.zsrcFile.variables.StateInstance>.state<&state.stateCtrl.stateId> ==
  k<&stateComposite.stateId>_State<&stateMethodSuffix>)  
##                                  ::::::::::  { switch_<&state.stateId><&stm.zsrcFile.variables.StateSubStruct>(
  <&stm.zsrcFile.callingArgs> ); }<.+>
##  }                                       
                            <+>
                            ::::::  return trans;
                            ::::::}<.+>
}

 

sub switchStatesMethodBody(Obj stateComposite, Num recurs = 0)
{                                         <+>
                            ::::::{ int trans = 0;                //set to true if transition has fired.<.+>
  call switchStates(stateComposite = stateComposite, recurs =0);
                            <+>
                            ::::::  return trans;
                            ::::::}<.+>
}
  

sub switchStates(Obj stateComposite, Num recurs = 0)
{ if(stateComposite.aSubstates && stateComposite.aSubstates.length()>0) {
    //only if it has aSubstates:          <+>
                            ::::::<:@2*recurs>  int ctSwitchState = 10;     //prevent too many transitions - a endless
                              loop
                            ::::::<:@2*recurs>  do { 
                            ::::::<:@2*recurs>    trans &= ~mTransit_States_Fwc;
                            ::::<:@2*recurs>   
                              switch(<&stm.zsrcFile.variables.StateInstance>.state<&stateComposite.stateId>) {
                            ::::<:@2*recurs>               //if the state was entried newly without define an inner
                              state, then the statedefault will be entered now.
                            ::::<:@2*recurs>               //Note that the default state cannot be entered on entry
                              action because it is unknown in that time
                            ::::<:@2*recurs>               //whether there will be an entry to a designated state.
                            ::::<:@2*recurs>      case 0:
                              entry_<&stateComposite.stateDefault><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>);
                              //without break, do trans:
                            ::::<:@2*recurs>      //switch to the current state:<.+>
    call switchCaseState(stateComposite = stateComposite, recurs = recurs+2);
                            <+>
                            ::::::<:@2*recurs>    } //switch    
                            ::::::<:@2*recurs>  } while((trans & mTransit_States_Fwc)    //continue checking transitions
                              if one of the has fired, it is run to completion.
                            ::::::<:@2*recurs>      &&
                              <&stm.zsrcFile.variables.StateInstance>.state<&stateComposite.stateId> !=0  //don't
                              continue if the composite is inactive now.
                            ::::::<:@2*recurs>      && --ctSwitchState >0);     //don't execute too may loops, only a
                              safety check. <.+>
  }                                       <+>
                            ::::::<:@2*recurs>  //
                            ::::::<:@2*recurs>  //for all parallel states: switch only if this state is the active one
                              still. Regard a leave of the state from any substate.<.+> 
##  for(state : stateComposite.aParallelstates) {
##                                          <+>
##                                      :::::: 
  if(<&stm.zsrcFile.variables.StateInstance>.state<&state.stateCtrl.stateId> ==
  k<&stateComposite.stateId>_State<&stateMethodSuffix>)  
##                                  ::::::::::  { switch_<&state.stateId><&stm.zsrcFile.variables.StateSubStruct>(
  <&stm.zsrcFile.callingArgs> ); }<.+>
##  }                                       
}






sub switchCaseState(Obj stateComposite, Num recurs = 0)
{
  for(state : stateComposite.aSubstates) {
    Obj zsrcState = state.auxInfo().zsrcState; 
    if(state ?instanceof classStateComposite) { ##zsrcState.hasHistory || zsrcState.parallelParentState) {  
      //an innner switch-case:                                         <+>
                            ::::::::::<:@2*recurs>  case k<&state.stateId>_State<&stateMethodSuffix>: { <.+>
      call switchStates(stateComposite = state, recurs = recurs+1);    <+>
                            ::::::::::<:@2*recurs>  } break; //composite state<.+>
    } elsif(state ?instanceof classStateCompositeFlat) {
      //it has not an own case!
      call switchCaseState(stateComposite = state, recurs = recurs);   //all case of composite:     
    } elsif(state ?instanceof classStateParallel) {                   <+>
                            ::::::::::<:@2*recurs>  case k<&state.stateId>_State<&stateMethodSuffix>: {<.+>
      for(stateParallel: state.aParallelstates) {           <+>
                            ::::::::::<:@2*recurs>     { //genStateM: Parallel state switch<.+>
        call switchStates(stateComposite = stateParallel, recurs = recurs+3);
                            <+>
                            ::::::::::<:@2*recurs>     }<.+>
      }
                            <+>
                            ::::::::::<:@2*recurs>    trans |=
                              trans_<&state.stateId><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>); 
                            ::::::::::<:@2*recurs>  } break; <.+>      
    } else { //StateSimple                                        <+>
                            ::::::::::<:@2*recurs>  case k<&state.stateId>_State<&stateMethodSuffix>: trans |=
                              trans_<&state.stateId><&stateMethodSuffix>(<&stm.zsrcFile.callingArgs>); break;<.+>      
    }
  }
  ##for(state : stateComposite.aParallelstates) {
  ##                                                                     <+>
  ##                                                  ::::::::::<:@2*recurs>    //parallelState state<&state.stateId>
  ##                                                  ::::::::::<:@2*recurs>   
    switch_<&state.stateId><&stm.zsrcFile.variables.StateSubStruct>( <&stm.zsrdFile.callingArgs> )<.+>
  ##  //call switchStates(stateComposite = state, recurs = recurs+1);
  ##}
}