C:/Users/Dennis/src/lang/Life_start/Life/life-1.02/source/list.c

Go to the documentation of this file.
00001 /* 
00002  * Copyright 1991 Digital Equipment Corporation.
00003  * All Rights Reserved.
00004  */
00005 /*      $Id: list.c,v 1.2 1994/12/08 23:28:16 duchier Exp $      */
00006 
00007 #ifndef lint
00008 static char vcid[] = "$Id: list.c,v 1.2 1994/12/08 23:28:16 duchier Exp $";
00009 #endif /* lint */
00010 
00011 /*
00012 ** list.c contains the functions to manage double link list
00013 ** with 2 entries (first and last element)
00014 ** Links belongs to each atom
00015 */
00016 
00017 #include "list.h"
00018 
00019 
00020 
00021 /*=============================================================================*/
00022 /*                      Set functions                                          */
00023 /*=============================================================================*/
00024 
00025 void List_SetLinkProc (header, getLinks)
00026 RefListHeader header;
00027 RefListGetLinksProc getLinks;
00028 {
00029     header->First = NULL;
00030     header->Last = NULL;
00031 
00032 #ifdef prlDEBUG
00033     header->Lock = 0;
00034 #endif
00035 
00036     header->GetLinks = getLinks;
00037 }
00038 
00039 /*=============================================================================*/
00040 /*                      List functions                                         */
00041 /*=============================================================================*/
00042 
00043 void List_InsertAhead (header, atom) 
00044 RefListHeader header;
00045 Ref atom;
00046 {
00047     RefListGetLinksProc  getLinks = header->GetLinks;
00048 
00049         /* Update links of atom to insert */
00050 
00051     (*getLinks)(atom)->Next = header->First;
00052     (*getLinks)(atom)->Prev = NULL;
00053 
00054         /* Link to the head of list */
00055 
00056     if (header->First != NULL)
00057       (*getLinks)(header->First)->Prev = atom;
00058 
00059     else        /* The list is empty */
00060       header->Last  = atom;
00061 
00062     header->First = atom;
00063 }
00064 
00065 /*==============================================================================*/
00066 
00067 void List_Append (header, atom) 
00068 RefListHeader header;
00069 Ref atom;
00070 {
00071     RefListGetLinksProc  getLinks = header->GetLinks;
00072 
00073                 /* Link to the end of list */
00074 
00075     if (header->Last != NULL)
00076       (*getLinks)(header->Last)->Next = atom;
00077 
00078     else        /* The list is empty */
00079       header->First = atom;
00080 
00081                 /* Update links of atom to insert */
00082 
00083     (*getLinks)(atom)->Prev = header->Last;
00084     (*getLinks)(atom)->Next = NULL;
00085 
00086                 /* Update last element of header */
00087 
00088     header->Last  = atom;
00089 }
00090 
00091 /*==============================================================================*/
00092 
00093 void List_InsertBefore (header, atom, mark)
00094 RefListHeader header;
00095 Ref atom;
00096 Ref mark;
00097 {
00098     RefListGetLinksProc  getLinks = header->GetLinks;
00099 
00100     if (mark != NULL)
00101     {
00102         (*getLinks)(atom)->Next = mark;
00103 
00104         if (mark != header->First)
00105         {
00106             (*getLinks)(atom)->Prev = (*getLinks)(mark)->Prev;
00107             (*getLinks)((*getLinks)(mark)->Prev)->Next = atom;
00108         }
00109         else    /* Insert ahead the list */
00110         {
00111             (*getLinks)(atom)->Prev = NULL;
00112             header->First = atom;
00113         }
00114 
00115         (*getLinks)(mark)->Prev = atom;
00116     }
00117     else        /* Append to the list */
00118       List_Append (header, atom);
00119 } 
00120 
00121 /*==============================================================================*/
00122 
00123 void List_InsertAfter (header, atom, mark)
00124 RefListHeader header;
00125 Ref atom;
00126 Ref mark;
00127 {
00128     RefListGetLinksProc  getLinks = header->GetLinks;
00129 
00130 #ifdef prlDEBUG
00131     if (header->Lock > 1)
00132       OS_PrintMessage ("List_InsertAfter: Warning insert after on recursive List_Enum call !!\n");
00133 #endif
00134 
00135     if (mark != NULL)
00136     {
00137         (*getLinks)(atom)->Prev = mark;
00138 
00139         if (mark != header->Last)
00140         {
00141             (*getLinks)(atom)->Next = (*getLinks)(mark)->Next;
00142             (*getLinks)((*getLinks)(mark)->Next)->Prev = atom;
00143         }
00144         else    /* Insert at the end of the list */
00145         {
00146             (*getLinks)(atom)->Next = NULL;
00147             header->Last = atom;
00148         }
00149 
00150         (*getLinks)(mark)->Next = atom;
00151     }
00152     else        /* Insert ahead the list */
00153       List_InsertAhead (header, atom);
00154 } 
00155 
00156 /*==============================================================================*/
00157 
00158 void List_Swap (header, first, second)
00159 RefListHeader header;
00160 Ref first;
00161 Ref second;
00162 {
00163     RefListGetLinksProc getLinks = header->GetLinks;
00164 
00165         /* Don't swap if the input is wrong */
00166 
00167     if ((*getLinks)(first)->Next != second)
00168     {
00169 #ifdef prlDEBUG
00170         OS_PrintMessage ("List_Swap: WARNING wrong input data, swap not done..\n");
00171 #endif
00172         return;
00173     }
00174 
00175         /* Special Cases */
00176 
00177     if (header->First == first)
00178       header->First = second;
00179     else
00180       (*getLinks)((*getLinks)(first)->Prev)->Next = second;
00181     
00182     if (header->Last == second)
00183       header->Last = first;
00184     else
00185       (*getLinks)((*getLinks)(second)->Next)->Prev = first;
00186 
00187         /* Swap the atoms */
00188 
00189     (*getLinks)(second)->Prev = (*getLinks)(first)->Prev;
00190     (*getLinks)(first)->Next  = (*getLinks)(second)->Next;
00191     (*getLinks)(first)->Prev  = second;
00192     (*getLinks)(second)->Next = first;
00193 }
00194 
00195 /*==============================================================================*/
00196 
00197 static long List_SwapLinks (header, atom)
00198 RefListHeader header;
00199 Ref atom;
00200 {
00201     Ref save;
00202 
00203     save = (*header->GetLinks)(atom)->Next;
00204     (*header->GetLinks)(atom)->Next = (*header->GetLinks)(atom)->Prev;
00205     (*header->GetLinks)(atom)->Prev = save;
00206 
00207     return TRUE;
00208 }
00209 
00210 void List_Reverse (header)
00211 RefListHeader header;
00212 {
00213     Ref                 cur, next;
00214     RefListGetLinksProc getLinks = header->GetLinks;
00215 
00216     /* This traverse cannot be done with function List_Enum() */
00217 
00218     cur = header->First;
00219 
00220     /* Swap the headers */
00221     header->First = header->Last;
00222     header->Last  = cur;
00223 
00224     while (cur != NULL)
00225     {
00226         next = (*getLinks)(cur)->Next;
00227         List_SwapLinks (header, cur);
00228         cur = next;
00229     }
00230 }
00231 
00232 /*==============================================================================*/
00233 
00234 void List_Remove (header, atom)
00235 RefListHeader header;
00236 Ref atom;
00237 {
00238 /*-----------------------------------------------------------------------------
00239 
00240 WARNING
00241         - The container is 'updated' two times if the first and last atom
00242           of list is the only one to remove.
00243 
00244 -----------------------------------------------------------------------------*/
00245 
00246     RefListGetLinksProc  getLinks = header->GetLinks;
00247 
00248 #ifdef prlDEBUG
00249     if (header->Lock > 1)
00250       OS_PrintMessage ("List_Remove: Warning remove on recursive List_Enum call !!\n");
00251 #endif
00252 
00253         /* Update the DownStream links */
00254 
00255     if ((*getLinks)(atom)->Prev != NULL)
00256     {
00257         (*getLinks)((*getLinks)(atom)->Prev)->Next = 
00258             (*getLinks)(atom)->Next;
00259     }
00260     else            /* Atom is the first of list */
00261       header->First = (*getLinks)(atom)->Next;
00262 
00263         /* Update the UpStream links */
00264 
00265     if ((*getLinks)(atom)->Next != NULL)
00266     {
00267         (*getLinks)((*getLinks)(atom)->Next)->Prev = 
00268             (*getLinks)(atom)->Prev;
00269     }
00270     else            /* Atom is the last of list */
00271       header->Last = (*getLinks)(atom)->Prev;
00272 
00273         /* Reset the atom links */
00274 
00275     (*getLinks)(atom)->Prev = NULL;
00276     (*getLinks)(atom)->Next = NULL;
00277 } 
00278 
00279 /*==============================================================================*/
00280 
00281 void List_Concat (header1, header2)
00282 RefListHeader header1;
00283 RefListHeader header2;
00284 {
00285     RefListGetLinksProc  getLinks = header1->GetLinks;
00286 
00287     if (header1->GetLinks == header2->GetLinks)
00288     {
00289 #ifdef prlDEBUG
00290         OS_PrintMessage ("List_Concat: ERROR concat different lists\n");
00291 #endif
00292         return;
00293     }
00294 
00295         /* Concatenate only if the second list is not empty */
00296 
00297     if (header2->First != NULL)
00298     {
00299         /* Obvious concatenate when the first list is empty */
00300 
00301         if (header1->First == NULL)
00302             header1->First = header2->First;
00303 
00304         else    /* Concatenate the two non empty lists */
00305         {
00306             (*getLinks)(header1->Last)->Next  = header2->First;
00307             (*getLinks)(header2->First)->Prev = header1->Last;
00308         }
00309         header1->Last = header2->Last;
00310     }
00311 } 
00312 
00313 /*==============================================================================*/
00314 
00315 long List_EnumFrom (header, atom, proc, closure)
00316 RefListHeader   header;
00317 Ref atom;
00318 RefListEnumProc proc;
00319 Ref closure;
00320 {
00321     Ref cur, next;
00322     int notInterrupted = TRUE;
00323 
00324 #ifdef prlDEBUG
00325     header->Lock += 1;
00326 #endif
00327 
00328     cur = atom;
00329     while (cur != NULL && notInterrupted)
00330     {
00331         next = List_Next (header, cur);
00332         notInterrupted = (*proc)(cur, closure);
00333         cur = next;
00334     }
00335 
00336 #ifdef prlDEBUG
00337     header->Lock -=1;
00338 #endif
00339     
00340     return (notInterrupted);
00341 }
00342 
00343 /*==============================================================================*/
00344 
00345 long List_Enum (header, proc, closure)
00346 RefListHeader   header;
00347 RefListEnumProc proc;
00348 Ref closure;
00349 /*-----------------------------------------------------------------------------
00350 
00351 (NO) SIDE EFFECTS
00352         The current atom can be modified by the function RemoveAtom () during
00353         the traversing of the list. This is the reason why the current pointer
00354         is managed on the header.
00355 
00356 -----------------------------------------------------------------------------*/
00357 {
00358     return (List_EnumFrom (header, header->First, proc, closure));
00359 }
00360 
00361 /*==============================================================================*/
00362 
00363 long List_EnumBackFrom (header, atom, proc, closure)
00364 RefListHeader   header;
00365 Ref             atom;
00366 RefListEnumProc proc;
00367 Ref             closure;
00368 {
00369     Ref cur, prev;
00370     int notInterrupted = TRUE;
00371 
00372 #ifdef prlDEBUG
00373     header->Lock += 1;
00374 #endif
00375 
00376     cur = atom;
00377     while (cur != NULL && notInterrupted)
00378     {
00379         prev = List_Prev (header, cur);
00380         notInterrupted = (*proc)(cur, closure);
00381         cur = prev;
00382     }
00383 
00384 #ifdef prlDEBUG
00385     header->Lock -=1;
00386 #endif
00387     
00388     return (notInterrupted);
00389 }
00390 
00391 /*==============================================================================*/
00392 
00393 long List_EnumBack (header, proc, closure)
00394 RefListHeader   header;
00395 RefListEnumProc proc;
00396 Ref                     closure;
00397 {
00398     return (List_EnumBackFrom (header, header->Last, proc, closure));
00399 }
00400 
00401 /*==============================================================================*/
00402 
00403 /*ARGSUSED*/
00404 static long List_CountAtom (p, nbR)
00405 Ref p; 
00406 Ref nbR;
00407 {
00408     long *nb = (long *)nbR;
00409     
00410     ++*nb;
00411     return TRUE;
00412 }
00413 
00414 long List_Card (header)
00415 RefListHeader header;
00416 {
00417     long n = 0;
00418     
00419     List_Enum (header, List_CountAtom, &n);
00420     return n;
00421 }
00422 
00423 /*==============================================================================*/
00424 
00425 long List_IsUnlink (links)
00426 RefListLinks links;
00427 {
00428     return (links->Next == NULL && links->Prev == NULL);
00429 }
00430 
00431 /*==============================================================================*/
00432 
00433 void List_Cut (header, atom, newHeader)
00434 RefListHeader   header;
00435 Ref                     atom;
00436 RefListHeader   newHeader;
00437 {
00438     RefListGetLinksProc  getLinks = header->GetLinks;
00439 
00440     if (atom != List_Last (header))
00441     {
00442         newHeader->First = List_Next (header, atom);
00443         newHeader->Last  = header->Last;
00444 
00445         header->Last = atom;
00446 
00447         /* Update the links */
00448         (*getLinks)(atom)->Next = NULL;
00449         (*getLinks)(newHeader->First)->Prev = NULL;
00450     }
00451 }
00452 
00453 /*==============================================================================*/

Generated on Sat Jan 26 08:48:07 2008 for WildLife by  doxygen 1.5.4