Ejemplo n.º 1
0
globle void *GetSalienceEvaluationCommand(
    void *theEnv)
{
    EnvArgCountCheck(theEnv,(char*)"get-salience-evaluation",EXACTLY,0);

    return((SYMBOL_HN *) EnvAddSymbol(theEnv,SalienceEvaluationName(EnvGetSalienceEvaluation(theEnv))));
}
Ejemplo n.º 2
0
void SaveExecutionInformation()
  {
   HKEY hKey;
   DWORD lpdwDisposition;
   struct ExecutionInformation executionInfo;
   
   if (RegCreateKeyEx(HKEY_CURRENT_USER,TEXT("Software\\CLIPS\\CLIPSWin"),0,"",0,
                      KEY_READ | KEY_WRITE,NULL,&hKey,&lpdwDisposition) != ERROR_SUCCESS)
     { return; }
              
   executionInfo.salienceEvaluation = EnvGetSalienceEvaluation(GlobalEnv);
   executionInfo.strategy = EnvGetStrategy(GlobalEnv);
   executionInfo.staticConstraintChecking = (boolean) EnvGetStaticConstraintChecking(GlobalEnv);
   executionInfo.dynamicConstraintChecking = (boolean) EnvGetDynamicConstraintChecking(GlobalEnv);
   executionInfo.autoFloatDividend = (boolean) EnvGetAutoFloatDividend(GlobalEnv);
   executionInfo.resetGlobals = (boolean) EnvGetResetGlobals(GlobalEnv);
   executionInfo.factDuplication = (boolean) EnvGetFactDuplication(GlobalEnv);
   executionInfo.incrementalReset = (boolean) EnvGetIncrementalReset(GlobalEnv);
   executionInfo.sequenceOperatorRecognition = (boolean) EnvGetSequenceOperatorRecognition(GlobalEnv);

   if (RegSetValueEx(hKey,"Execution",0,REG_BINARY,(BYTE *) &executionInfo,
                     sizeof(struct ExecutionInformation)) != ERROR_SUCCESS)
     {
      RegCloseKey(hKey);
      return;
     }

   RegCloseKey(hKey);
  }
Ejemplo n.º 3
0
globle void *SetSalienceEvaluationCommand(
    void *theEnv)
{
    DATA_OBJECT argPtr;
    char *argument, *oldValue;

    /*==================================================*/
    /* Get the current setting for salience evaluation. */
    /*==================================================*/

    oldValue = SalienceEvaluationName(EnvGetSalienceEvaluation(theEnv));

    /*=========================================*/
    /* This function expects a single argument */
    /* which must be a symbol.                 */
    /*=========================================*/

    if (EnvArgCountCheck(theEnv,(char*)"set-salience-evaluation",EXACTLY,1) == -1)
    {
        return((SYMBOL_HN *) EnvAddSymbol(theEnv,oldValue));
    }

    if (EnvArgTypeCheck(theEnv,(char*)"set-salience-evaluation",1,SYMBOL,&argPtr) == FALSE)
    {
        return((SYMBOL_HN *) EnvAddSymbol(theEnv,oldValue));
    }

    /*=============================================================*/
    /* The allowed symbols to pass as an argument to this function */
    /* are when-defined, when-activated, and every-cycle.          */
    /*=============================================================*/

    argument = DOToString(argPtr);

    if (strcmp(argument,(char*)"when-defined") == 0)
    {
        EnvSetSalienceEvaluation(theEnv,WHEN_DEFINED);
    }
    else if (strcmp(argument,(char*)"when-activated") == 0)
    {
        EnvSetSalienceEvaluation(theEnv,WHEN_ACTIVATED);
    }
    else if (strcmp(argument,(char*)"every-cycle") == 0)
    {
        EnvSetSalienceEvaluation(theEnv,EVERY_CYCLE);
    }
    else
    {
        ExpectedTypeError1(theEnv,(char*)"set-salience-evaluation",1,
                           (char*)"symbol with value when-defined, when-activated, or every-cycle");
        return((SYMBOL_HN *) EnvAddSymbol(theEnv,oldValue));
    }

    /*=================================================*/
    /* Return the old setting for salience evaluation. */
    /*=================================================*/

    return((SYMBOL_HN *) EnvAddSymbol(theEnv,oldValue));
}
Ejemplo n.º 4
0
static int EvaluateSalience(
    void *theEnv,
    void *vPtr)
{
    struct defrule *rPtr = (struct defrule *) vPtr;
    DATA_OBJECT salienceValue;
    int salience;

    /*==================================================*/
    /* If saliences are only being evaluated when rules */
    /* are defined, then just return the last salience  */
    /* value evaluated for the rule.                    */
    /*==================================================*/

    if (EnvGetSalienceEvaluation(theEnv) == WHEN_DEFINED)
    {
        return(rPtr->salience);
    }

    /*=================================================================*/
    /* If the rule's salience value was defined as an integer constant */
    /* (i.e., not an expression or global variable which could change  */
    /* on reevaluation), then just return the salience value computed  */
    /* for the rule when it was defined.                               */
    /*=================================================================*/

    if (rPtr->dynamicSalience == NULL) return(rPtr->salience);

    /*====================================================*/
    /* Reevaluate the rule's salience. If an error occurs */
    /* during evaluation, print an error message.         */
    /*====================================================*/

    SetEvaluationError(theEnv,FALSE);
    if (EvaluateExpression(theEnv,rPtr->dynamicSalience,&salienceValue))
    {
        SalienceInformationError(theEnv,(char*)"defrule",ValueToString(rPtr->header.name));
        return(rPtr->salience);
    }

    /*========================================*/
    /* The salience value must be an integer. */
    /*========================================*/

    if (salienceValue.type != INTEGER)
    {
        SalienceNonIntegerError(theEnv);
        SalienceInformationError(theEnv,(char*)"defrule",ValueToString(rPtr->header.name));
        SetEvaluationError(theEnv,TRUE);
        return(rPtr->salience);
    }

    /*==========================================*/
    /* The salience value must fall between the */
    /* minimum and maximum allowed values.      */
    /*==========================================*/

    salience = (int) ValueToLong(salienceValue.value);

    if ((salience > MAX_DEFRULE_SALIENCE) || (salience < MIN_DEFRULE_SALIENCE))
    {
        SalienceRangeError(theEnv,MIN_DEFRULE_SALIENCE,MAX_DEFRULE_SALIENCE);
        SetEvaluationError(theEnv,TRUE);
        SalienceInformationError(theEnv,(char*)"defrule",ValueToString(((struct defrule *) rPtr)->header.name));
        return(rPtr->salience);
    }

    /*===================================*/
    /* Store the new salience value with */
    /* the rule and return this value.   */
    /*===================================*/

    rPtr->salience = salience;
    return(rPtr->salience);
}
Ejemplo n.º 5
0
globle void EnvRefreshAgenda(
    void *theEnv,
    void *vTheModule)
{
    struct activation *theActivation;
    struct defmodule *theModule = (struct defmodule *) vTheModule;
    intBool oldValue;
    int allModules = FALSE;

    /*==========================*/
    /* Save the current module. */
    /*==========================*/

    SaveCurrentModule(theEnv);

    /*=============================================*/
    /* If the module specified is a NULL pointer,  */
    /* then every module has its agenda refreshed. */
    /*=============================================*/

    if (theModule == NULL)
    {
        allModules = TRUE;
        theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
    }

    /*=======================================================*/
    /* Remember the current setting for salience evaluation. */
    /* To perform the refresh, the when activated setting is */
    /* used to recompute the salience values.                */
    /*=======================================================*/

    oldValue = EnvGetSalienceEvaluation(theEnv);
    EnvSetSalienceEvaluation(theEnv,WHEN_ACTIVATED);

    /*========================*/
    /* Refresh the agenda(s). */
    /*========================*/

    for (;
            theModule != NULL;
            theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
    {
        /*=========================================*/
        /* Change the current module to the module */
        /* of the agenda being refreshed.          */
        /*=========================================*/

        EnvSetCurrentModule(theEnv,(void *) theModule);

        /*================================================================*/
        /* Recompute the salience values for the current module's agenda. */
        /*================================================================*/

        for (theActivation = (struct activation *) EnvGetNextActivation(theEnv,NULL);
                theActivation != NULL;
                theActivation = (struct activation *) EnvGetNextActivation(theEnv,theActivation))
        {
            theActivation->salience = EvaluateSalience(theEnv,theActivation->theRule);
        }

        /*======================================================*/
        /* Reorder the agenda based on the new salience values. */
        /*======================================================*/

        EnvReorderAgenda(theEnv,theModule);

        /*===============================================*/
        /* Return if only one agenda is being refreshed. */
        /*===============================================*/

        if (! allModules)
        {
            EnvSetSalienceEvaluation(theEnv,oldValue);
            RestoreCurrentModule(theEnv);
            return;
        }
    }

    /*==========================================*/
    /* Restore the salience evaluation setting. */
    /*==========================================*/

    EnvSetSalienceEvaluation(theEnv,oldValue);

    /*=============================*/
    /* Restore the current module. */
    /*=============================*/

    RestoreCurrentModule(theEnv);
}
Ejemplo n.º 6
0
/*******************************************************************************
          Name:        UpdateOptionsMenu
          Description: Set menu item mark on options selected
          Arguments:    None
          Returns:     None
*******************************************************************************/
void UpdateOptionsMenu()
  {
   int i;
   unsigned n =  0;
   void *theEnv = GetCurrentEnvironment();

  XtSetArg(TheArgs[n], XtNleftBitmap, None);n++;
  for(i = 0; i <= RANDOM_STRATEGY;i++) 
    XtSetValues(strategy_widgets[i], TheArgs, n);
  for(i = 0; i <= EVERY_CYCLE;i++)
    XtSetValues(sal_opt_widgets[i],TheArgs,n);
  n = 0;
  XtSetArg(TheArgs[n], XtNleftBitmap, checker);n++;
  XtSetValues(strategy_widgets[EnvGetStrategy(theEnv)],TheArgs,n);
  XtSetValues(sal_opt_widgets[EnvGetSalienceEvaluation(theEnv)],TheArgs,n);
  n = 0;
  if (EnvGetFactDuplication(theEnv))
    {
    XtSetArg(TheArgs[n], XtNstate,True);n++;
    XtSetValues(option_widgets[INT_FACT_DUPLICATION], TheArgs, n);
    }
  else
    {
    XtSetArg(TheArgs[n], XtNstate,False);n++;
    XtSetValues(option_widgets[INT_FACT_DUPLICATION], TheArgs, n);
    }
  n = 0;
  if (EnvGetDynamicConstraintChecking(theEnv))
    {
    XtSetArg(TheArgs[n], XtNstate,True);n++;
    XtSetValues(option_widgets[INT_DYN_CONSTRAINT_CHK], TheArgs, n);
    }
  else
    {
    XtSetArg(TheArgs[n], XtNstate,False);n++;
    XtSetValues(option_widgets[INT_DYN_CONSTRAINT_CHK], TheArgs, n);
    }
  n = 0;
  if (EnvGetStaticConstraintChecking(theEnv))
    {
    XtSetArg(TheArgs[n], XtNstate,True);n++;
    XtSetValues(option_widgets[INT_STA_CONSTRAINT_CHK], TheArgs, n);
    }
  else
    {
    XtSetArg(TheArgs[n], XtNstate,False);n++;
    XtSetValues(option_widgets[INT_STA_CONSTRAINT_CHK], TheArgs, n);
    }
  n = 0;
  if (EnvGetSequenceOperatorRecognition(theEnv))
    {
    XtSetArg(TheArgs[n], XtNstate,True);n++;
    XtSetValues(option_widgets[INT_SEQUENCE_OPT_REG], TheArgs, n);
    }
  else
    {
    XtSetArg(TheArgs[n], XtNstate,False);n++;
    XtSetValues(option_widgets[INT_SEQUENCE_OPT_REG], TheArgs, n);
    }

  n = 0;
  if (EnvGetAutoFloatDividend(theEnv))
    {
    XtSetArg(TheArgs[n], XtNstate,True);n++;
    XtSetValues(option_widgets[INT_AUTO_FLOAT_DIV], TheArgs, n);
    }
  else
    {
    XtSetArg(TheArgs[n], XtNstate,False);n++;
    XtSetValues(option_widgets[INT_AUTO_FLOAT_DIV], TheArgs, n);
    }
  n =  0;
  if (EnvGetIncrementalReset(theEnv))
    {
    XtSetArg(TheArgs[n], XtNstate,True);n++;
    XtSetValues(option_widgets[INT_INCREMENTAL_RESET], TheArgs, n);
    }
  else
    {
    XtSetArg(TheArgs[n], XtNstate,False);n++;
    XtSetValues(option_widgets[INT_INCREMENTAL_RESET], TheArgs, n);
    }
  n =  0;
  if (EnvGetResetGlobals(theEnv))
    {
    XtSetArg(TheArgs[n], XtNstate,True);n++;
    XtSetValues(option_widgets[INT_RESET_GLOBALS], TheArgs, n);
    }
  else
    {
    XtSetArg(TheArgs[n], XtNstate,False);n++;
    XtSetValues(option_widgets[INT_RESET_GLOBALS], TheArgs, n);
    }
  }
Ejemplo n.º 7
0
globle long int EnvRun(
  void *theEnv,
  long int runLimit)
  {
   long int rulesFired = 0;
   DATA_OBJECT result;
   struct callFunctionItem *theRunFunction;
#if DEBUGGING_FUNCTIONS
   unsigned long maxActivations = 0, sumActivations = 0;
#if DEFTEMPLATE_CONSTRUCT
   unsigned long maxFacts = 0, sumFacts = 0;
#endif
#if OBJECT_SYSTEM
   unsigned long maxInstances = 0, sumInstances = 0;
#endif
   double endTime, startTime = 0.0;
   unsigned long tempValue;
#endif
   unsigned int i;
   struct patternEntity *theMatchingItem;
   struct partialMatch *theBasis;
   ACTIVATION *theActivation;
   char *ruleFiring;
#if PROFILING_FUNCTIONS
   struct profileFrameInfo profileFrame;
#endif

   /*=====================================================*/
   /* Make sure the run command is not already executing. */
   /*=====================================================*/

   if (EngineData(theEnv)->AlreadyRunning) return(0);
   EngineData(theEnv)->AlreadyRunning = TRUE;

   /*================================*/
   /* Set up statistics information. */
   /*================================*/

#if DEBUGGING_FUNCTIONS
   if (EngineData(theEnv)->WatchStatistics)
     {
#if DEFTEMPLATE_CONSTRUCT
      maxFacts = GetNumberOfFacts(theEnv);
      sumFacts = maxFacts;
#endif
#if OBJECT_SYSTEM
      maxInstances = GetGlobalNumberOfInstances(theEnv);
      sumInstances = maxInstances;
#endif
      maxActivations = GetNumberOfActivations(theEnv);
      sumActivations = maxActivations;
      startTime = gentime();
     }
#endif

   /*=============================*/
   /* Set up execution variables. */
   /*=============================*/

   if (EvaluationData(theEnv)->CurrentEvaluationDepth == 0) SetHaltExecution(theEnv,FALSE);
   EngineData(theEnv)->HaltRules = FALSE;

   /*=====================================================*/
   /* Fire rules until the agenda is empty, the run limit */
   /* has been reached, or a rule execution error occurs. */
   /*=====================================================*/

   theActivation = NextActivationToFire(theEnv);
   while ((theActivation != NULL) &&
          (runLimit != 0) &&
          (EvaluationData(theEnv)->HaltExecution == FALSE) &&
          (EngineData(theEnv)->HaltRules == FALSE))
     {
      /*===========================================*/
      /* Detach the activation from the agenda and */
      /* determine which rule is firing.           */
      /*===========================================*/

      DetachActivation(theEnv,theActivation);
      ruleFiring = EnvGetActivationName(theEnv,theActivation);
      theBasis = (struct partialMatch *) GetActivationBasis(theActivation);
      EngineData(theEnv)->ExecutingRule = (struct defrule *) GetActivationRule(theActivation);

      /*=============================================*/
      /* Update the number of rules that have fired. */
      /*=============================================*/

      rulesFired++;
      if (runLimit > 0) { runLimit--; }

      /*==================================*/
      /* If rules are being watched, then */
      /* print an information message.    */
      /*==================================*/

#if DEBUGGING_FUNCTIONS
      if (EngineData(theEnv)->ExecutingRule->watchFiring)
        {
         char printSpace[60];

         sprintf(printSpace,"FIRE %4ld ",rulesFired);
         EnvPrintRouter(theEnv,WTRACE,printSpace);
         EnvPrintRouter(theEnv,WTRACE,ruleFiring);
         EnvPrintRouter(theEnv,WTRACE,": ");
         PrintPartialMatch(theEnv,WTRACE,theBasis);
         EnvPrintRouter(theEnv,WTRACE,"\n");
        }
#endif

      /*=================================================*/
      /* Remove the link between the activation and the  */
      /* completed match for the rule. Set the busy flag */
      /* for the completed match to TRUE (so the match   */
      /* upon which our RHS variables are dependent is   */
      /* not deleted while our rule is firing). Set up   */
      /* the global pointers to the completed match for  */
      /* routines which do variable extractions.         */
      /*=================================================*/

      theBasis->binds[theBasis->bcount].gm.theValue = NULL;
      theBasis->busy = TRUE;

      EngineData(theEnv)->GlobalLHSBinds = theBasis;
      EngineData(theEnv)->GlobalRHSBinds = NULL;

      /*===================================================================*/
      /* Increment the count for each of the facts/objects associated with */
      /* the rule activation so that the facts/objects cannot be deleted   */
      /* by garbage collection while the rule is executing.                */
      /*===================================================================*/

      for (i = 0; i < theBasis->bcount; i++)
        {
         theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem;
         if (theMatchingItem != NULL)
           { (*theMatchingItem->theInfo->incrementBasisCount)(theEnv,theMatchingItem); }
        }

      /*====================================================*/
      /* Execute the rule's right hand side actions. If the */
      /* rule has logical CEs, set up the pointer to the    */
      /* rules logical join so the assert command will      */
      /* attach the appropriate dependencies to the facts.  */
      /*====================================================*/

      EngineData(theEnv)->TheLogicalJoin = EngineData(theEnv)->ExecutingRule->logicalJoin;
      EvaluationData(theEnv)->CurrentEvaluationDepth++;
      SetEvaluationError(theEnv,FALSE);
      EngineData(theEnv)->ExecutingRule->executing = TRUE;

#if PROFILING_FUNCTIONS
      StartProfile(theEnv,&profileFrame,
                   &EngineData(theEnv)->ExecutingRule->header.usrData,
                   ProfileFunctionData(theEnv)->ProfileConstructs);
#endif

      EvaluateProcActions(theEnv,EngineData(theEnv)->ExecutingRule->header.whichModule->theModule,
                          EngineData(theEnv)->ExecutingRule->actions,EngineData(theEnv)->ExecutingRule->localVarCnt,
                          &result,NULL);

#if PROFILING_FUNCTIONS
      EndProfile(theEnv,&profileFrame);
#endif

      EngineData(theEnv)->ExecutingRule->executing = FALSE;
      SetEvaluationError(theEnv,FALSE);
      EvaluationData(theEnv)->CurrentEvaluationDepth--;
      EngineData(theEnv)->TheLogicalJoin = NULL;

      /*=====================================================*/
      /* If rule execution was halted, then print a message. */
      /*=====================================================*/

#if DEBUGGING_FUNCTIONS
      if ((EvaluationData(theEnv)->HaltExecution) || (EngineData(theEnv)->HaltRules && EngineData(theEnv)->ExecutingRule->watchFiring))
#else
      if ((EvaluationData(theEnv)->HaltExecution) || (EngineData(theEnv)->HaltRules))
#endif

        {
         PrintErrorID(theEnv,"PRCCODE",4,FALSE);
         EnvPrintRouter(theEnv,WERROR,"Execution halted during the actions of defrule ");
         EnvPrintRouter(theEnv,WERROR,ruleFiring);
         EnvPrintRouter(theEnv,WERROR,".\n");
        }

      /*===================================================================*/
      /* Decrement the count for each of the facts/objects associated with */
      /* the rule activation. If the last match for the activation         */
      /* is from a not CE, then we need to make sure that the last         */
      /* match is an actual match for the CE and not a counter.            */
      /*===================================================================*/

      theBasis->busy = FALSE;

      for (i = 0; i < (theBasis->bcount - 1); i++)
        {
         theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem;
         if (theMatchingItem != NULL)
           { (*theMatchingItem->theInfo->decrementBasisCount)(theEnv,theMatchingItem); }
        }

      i = (unsigned) (theBasis->bcount - 1);
      if (theBasis->counterf == FALSE)
        {
         theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem;
         if (theMatchingItem != NULL)
           { (*theMatchingItem->theInfo->decrementBasisCount)(theEnv,theMatchingItem); }
        }

      /*========================================*/
      /* Return the agenda node to free memory. */
      /*========================================*/

      RemoveActivation(theEnv,theActivation,FALSE,FALSE);

      /*======================================*/
      /* Get rid of partial matches discarded */
      /* while executing the rule's RHS.      */
      /*======================================*/

      FlushGarbagePartialMatches(theEnv);

      /*==================================*/
      /* Get rid of other garbage created */
      /* while executing the rule's RHS.  */
      /*==================================*/

      PeriodicCleanup(theEnv,FALSE,TRUE);

      /*==========================*/
      /* Keep up with statistics. */
      /*==========================*/

#if DEBUGGING_FUNCTIONS
      if (EngineData(theEnv)->WatchStatistics)
        {
#if DEFTEMPLATE_CONSTRUCT
         tempValue = GetNumberOfFacts(theEnv);
         if (tempValue > maxFacts) maxFacts = tempValue;
         sumFacts += tempValue;
#endif
#if OBJECT_SYSTEM
         tempValue = GetGlobalNumberOfInstances(theEnv);
         if (tempValue > maxInstances) maxInstances = tempValue;
         sumInstances += tempValue;
#endif
         tempValue = GetNumberOfActivations(theEnv);
         if (tempValue > maxActivations) maxActivations = tempValue;
         sumActivations += tempValue;
        }
#endif

      /*==================================*/
      /* Update saliences if appropriate. */
      /*==================================*/

      if (EnvGetSalienceEvaluation(theEnv) == EVERY_CYCLE) EnvRefreshAgenda(theEnv,NULL);

      /*========================================*/
      /* Execute the list of functions that are */
      /* to be called after each rule firing.   */
      /*========================================*/

      for (theRunFunction = EngineData(theEnv)->ListOfRunFunctions;
           theRunFunction != NULL;
           theRunFunction = theRunFunction->next)
        { 
         if (theRunFunction->environmentAware)
           { (*theRunFunction->func)(theEnv); }
         else            
           { ((void (*)(void))(*theRunFunction->func))(); }
        }

      /*========================================*/
      /* If a return was issued on the RHS of a */
      /* rule, then remove *that* rule's module */
      /* from the focus stack                   */
      /*========================================*/

      if (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE)
        { RemoveFocus(theEnv,EngineData(theEnv)->ExecutingRule->header.whichModule->theModule); }
      ProcedureFunctionData(theEnv)->ReturnFlag = FALSE;

      /*========================================*/
      /* Determine the next activation to fire. */
      /*========================================*/

      theActivation = (struct activation *) NextActivationToFire(theEnv);

      /*==============================*/
      /* Check for a rule breakpoint. */
      /*==============================*/

      if (theActivation != NULL)
        {
         if (((struct defrule *) GetActivationRule(theActivation))->afterBreakpoint)
           {
            EngineData(theEnv)->HaltRules = TRUE;
            EnvPrintRouter(theEnv,WDIALOG,"Breaking on rule ");
            EnvPrintRouter(theEnv,WDIALOG,EnvGetActivationName(theEnv,theActivation));
            EnvPrintRouter(theEnv,WDIALOG,".\n");
           }
        }
     }

   /*=====================================================*/
   /* Make sure run functions are executed at least once. */
   /*=====================================================*/

   if (rulesFired == 0)
     {
      for (theRunFunction = EngineData(theEnv)->ListOfRunFunctions;
           theRunFunction != NULL;
           theRunFunction = theRunFunction->next)
        { 
         if (theRunFunction->environmentAware)
           { (*theRunFunction->func)(theEnv); }
         else            
           { ((void (*)(void))(*theRunFunction->func))(); }
        }
     }

   /*======================================================*/
   /* If rule execution was halted because the rule firing */
   /* limit was reached, then print a message.             */
   /*======================================================*/

   if (runLimit == rulesFired)
     { EnvPrintRouter(theEnv,WDIALOG,"rule firing limit reached\n"); }

   /*==============================*/
   /* Restore execution variables. */
   /*==============================*/

   EngineData(theEnv)->ExecutingRule = NULL;
   EngineData(theEnv)->HaltRules = FALSE;

   /*=================================================*/
   /* Print out statistics if they are being watched. */
   /*=================================================*/

#if DEBUGGING_FUNCTIONS
   if (EngineData(theEnv)->WatchStatistics)
     {
      char printSpace[60];

      endTime = gentime();

      PrintLongInteger(theEnv,WDIALOG,rulesFired);
      EnvPrintRouter(theEnv,WDIALOG," rules fired");

#if (! GENERIC)
      if (startTime != endTime)
        {
         EnvPrintRouter(theEnv,WDIALOG,"        Run time is ");
         PrintFloat(theEnv,WDIALOG,endTime - startTime);
         EnvPrintRouter(theEnv,WDIALOG," seconds.\n");
         PrintFloat(theEnv,WDIALOG,(double) rulesFired / (endTime - startTime));
         EnvPrintRouter(theEnv,WDIALOG," rules per second.\n");
        }
      else
        { EnvPrintRouter(theEnv,WDIALOG,"\n"); }
#endif

#if DEFTEMPLATE_CONSTRUCT
      sprintf(printSpace,"%ld mean number of facts (%ld maximum).\n",
                          (long) (((double) sumFacts / (rulesFired + 1)) + 0.5),
                          maxFacts);
      EnvPrintRouter(theEnv,WDIALOG,printSpace);
#endif

#if OBJECT_SYSTEM
      sprintf(printSpace,"%ld mean number of instances (%ld maximum).\n",
                          (long) (((double) sumInstances / (rulesFired + 1)) + 0.5),
                          maxInstances);
      EnvPrintRouter(theEnv,WDIALOG,printSpace);
#endif

      sprintf(printSpace,"%ld mean number of activations (%ld maximum).\n",
                          (long) (((double) sumActivations / (rulesFired + 1)) + 0.5),
                          maxActivations);
      EnvPrintRouter(theEnv,WDIALOG,printSpace);
     }
#endif

   /*==========================================*/
   /* The current module should be the current */
   /* focus when the run finishes.             */
   /*==========================================*/

   if (EngineData(theEnv)->CurrentFocus != NULL)
     {
      if (EngineData(theEnv)->CurrentFocus->theModule != ((struct defmodule *) EnvGetCurrentModule(theEnv)))
        { EnvSetCurrentModule(theEnv,(void *) EngineData(theEnv)->CurrentFocus->theModule); }
     }

   /*===================================*/
   /* Return the number of rules fired. */
   /*===================================*/

   EngineData(theEnv)->AlreadyRunning = FALSE;
   return(rulesFired);
  }