⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inherpsr.c

📁 VC嵌入式CLips专家系统,实现战场环境的目标识别
💻 C
📖 第 1 页 / 共 3 页
字号:
                                    OBJECT
                 Predecessor Count   0
                 Successor List     <NIL>

                 Precedence List: C A B USER OBJECT

                 And since the table is now empty we are done!
  INPUTS       : 1) The old class definition (NULL if it is new)
                 2) The list of direct superclasses
  RETURNS      : The address of the precedence list if successful,
                 NULL otherwise
  SIDE EFFECTS : Precedence list allocated
  NOTES        : WARNING!! - This routine assumes that there are no
                 cyclic dependencies in the given superclass list, i.e.
                 none of the superclasses inherit from the class for
                 which the precedence list is being defined.  (This
                 is verified in ParseDefclasses() in CLASSCOM.C)

                 Every class-precedence list has the class itself on it
                 (implicitly) and a built-in system class on it explicitly
                 (except for the built-in classes).

                 The precedence determination algorithm is a variation on
                 the topological sorting algorithm given in The Art of
                 Computer Programming - Vol. I (Fundamental Algorithms) by
                 Donald Knuth.
 ***************************************************************************/
globle PACKED_CLASS_LINKS *FindPrecedenceList(
  void *theEnv,
  DEFCLASS *cls,
  PACKED_CLASS_LINKS *supers)
  {
   PARTIAL_ORDER *po_table = NULL,*start,*pop,*poprv,*potmp;
   SUCCESSOR *stmp;
   CLASS_LINK *ptop,*pbot,*ptmp;
   PACKED_CLASS_LINKS *plinks;
   register unsigned i;

   /* =====================================================================
      Recursively add all superclasses in a pre-order depth-first traversal
      to the partial order table.  There should be only one node per class.
      ===================================================================== */
   po_table = InitializePartialOrderTable(theEnv,po_table,supers);

   /* =============================================================
      If the class already exists, record the rule 1 partial orders
      with the new superclass lists.  This is so that cyclic
      dependencies can be detected.
      ============================================================= */
   if (cls != NULL)
     {
      pop = get_struct(theEnv,partialOrder);
      pop->cls = cls;
      pop->pre = 0;
      pop->suc = NULL;
      pop->nxt = po_table;
      po_table = pop;
      pop = po_table->nxt;
      RecordPartialOrders(theEnv,po_table,cls,supers,0);
     }
   else
     pop = po_table;

   /* ==================================================================
      Record the rule 1 and rule 2 partial orders given by the direct
      superclass lists of the classes in the table.  There is no need to
      recurse since all possible classes have been entered already.

      Be sure to skip the class itself if it was added to the front of
      the table.
      ================================================================== */
   for ( ; pop != NULL ; pop = pop->nxt)
     {
      RecordPartialOrders(theEnv,po_table,pop->cls,&pop->cls->directSuperclasses,0);
      for (i = 0 ; i < pop->cls->directSuperclasses.classCount ; i++)
        RecordPartialOrders(theEnv,po_table,pop->cls->directSuperclasses.classArray[i],
                            &pop->cls->directSuperclasses,i+1);
     }

   /* =============================================================
      Record the rule 2 partial orders given by the superclass list
      ============================================================= */
   for (i = 0 ; i < supers->classCount ; i++)
     RecordPartialOrders(theEnv,po_table,supers->classArray[i],supers,i+1);

   start = NULL;
   poprv = NULL;
   pop = po_table;
   ptop = pbot = NULL;
   while (pop != start)
     {
      /* ==============================================================
         Allow wraparound - happens when the search for a 0 node begins
         somewhere in the middle of the sequence table
         ============================================================== */
      if (pop == NULL)
        {
         poprv = NULL;
         pop = po_table;
         start = start->nxt;
        }

      /* =========================================================
         Search for the first class with no remaining predecessors
         ========================================================= */
      if (pop->pre == 0)
        {
         /* =================================================
            Decrement the predecessor count for all the
            successors of this class and delete the list.

            This is the variation on Knuth's algorithm which
            allows us to preserve the "family" heuristic.
            Since we will pick up scanning for 0's from
            this point, we will be able to keep "family"
            trees together, if possible. BuildPartialOrders()
            entered the classes into the sequence table
            in a pre-order depth traversal order.
            ================================================= */
         while (pop->suc != NULL)
           {
            stmp = pop->suc;
            pop->suc = stmp->nxt;
            stmp->po->pre--;
            rtn_struct(theEnv,successor,stmp);
           }

         /* =============================================
            Append the class to the precedence list and
            remove its entry from the partial order table
            ============================================= */
         potmp = pop;
         if (poprv == NULL)
           po_table = pop->nxt;
         else
           poprv->nxt = pop->nxt;
         pop = pop->nxt;
         start = poprv;
         ptmp = get_struct(theEnv,classLink);
         ptmp->cls = potmp->cls;
         ptmp->nxt = NULL;
         rtn_struct(theEnv,partialOrder,potmp);
         if (ptop == NULL)
           ptop = ptmp;
         else
           pbot->nxt = ptmp;
         pbot = ptmp;
        }
      else
        {
         poprv = pop;
         pop = pop->nxt;
        }
     }

   /* ======================================================================
      If the table of partial orders is not empty and we were unable to find
      a class with no predecessors, then there is no solution! Print out the
      precedence loop in the partial orders. Delete the remaining partial
      order table and the partial precedence list.
      ====================================================================== */
   if (po_table != NULL)
     {
      PrintErrorID(theEnv,"INHERPSR",5,FALSE);
      PrintClassLinks(theEnv,WERROR,"Partial precedence list formed:",ptop);
      PrintPartialOrderLoop(theEnv,po_table);
      while (po_table != NULL)
        {
         while (po_table->suc != NULL)
           {
            stmp = po_table->suc;
            po_table->suc = stmp->nxt;
            rtn_struct(theEnv,successor,stmp);
           }
         potmp = po_table;
         po_table = po_table->nxt;
         rtn_struct(theEnv,partialOrder,potmp);
        }
      DeleteClassLinks(theEnv,ptop);
      return(NULL);
     }

   /* =============================================================================
      If the class already existed, be sure and remove it from its own precedence
      list.  Remember that we stuck it on the table artificially to catch cycles.
      It was first in the table, and, since it started with a predecessor count
      of zero (given that there were no loops), it is first in the precedence list.

      We will leave the dummy node there so that functions which wish to iterate
      over a class and its superclasses may easily do so.
      ============================================================================= */
   if (cls == NULL)
     {
      ptmp = get_struct(theEnv,classLink);
      ptmp->nxt = ptop;
      ptop = ptmp;
     }

   /* ============================================================
      The class pointer will be filled in later by ParseDefclass()
      ============================================================ */
   ptop->cls = NULL;

   plinks = get_struct(theEnv,packedClassLinks);
   PackClassLinks(theEnv,plinks,ptop);
   return(plinks);
  }

/***************************************************
  NAME         : PackClassLinks
  DESCRIPTION  : Writes a list of class links into
                 a contiguous section of memory to
                 reduce overhead (the original list
                 is deleted)
  INPUTS       : 1) The packed list structure to use
                 2) The top of the original list
  RETURNS      : Nothing useful
  SIDE EFFECTS : Packed list allocated and old list
                 deleted
  NOTES        : None
 ***************************************************/
globle void PackClassLinks(
  void *theEnv,
  PACKED_CLASS_LINKS *plinks,
  CLASS_LINK *lptop)
  {
   register unsigned count;
   register CLASS_LINK *lp;

   for (count = 0 , lp = lptop ; lp != NULL ; lp = lp->nxt)
     count++;
   if (count > 0)
     plinks->classArray = (DEFCLASS **) gm2(theEnv,(sizeof(DEFCLASS *) * count));
   else
     plinks->classArray = NULL;
   for (count = 0 , lp = lptop ; lp != NULL ; lp = lp->nxt , count++)
     plinks->classArray[count] = lp->cls;
   DeleteClassLinks(theEnv,lptop);
   plinks->classCount = (unsigned short) count;
  }

/* =========================================
   *****************************************
          INTERNALLY VISIBLE FUNCTIONS
   =========================================
   ***************************************** */

/**************************************************************************
  NAME         : InitializePartialOrderTable
  DESCRIPTION  : This function recursively enters the classes
                 that will be used in a precedence list
                 determination in depth-first pre-order traversal.
                 The predecessor counts and successor list are initialized.

  INPUTS       : 1) The partial order table
                 2) A list of direct superclasses
                 3) The class for which a precedence class is being
                    determined (NULL for new class)
                 4) The class which superclass list is being processed
  RETURNS      : The top of partial order table
  SIDE EFFECTS : The partial order table is initialized.
  NOTES        : None
 **************************************************************************/
static PARTIAL_ORDER *InitializePartialOrderTable(
  void *theEnv,
  PARTIAL_ORDER *po_table,
  PACKED_CLASS_LINKS *supers)
  {
   register PARTIAL_ORDER *pop,*poprv;
   register unsigned i;

   for (i = 0 ; i < supers->classCount ; i++)
     {
      /* =================================================
         Append this class at the end of the partial order
         table only if it is not already present
         ================================================= */
      poprv = NULL;
      for (pop = po_table ; pop != NULL ; pop = pop->nxt)
        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -