Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
linklist.c
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 
00037 #include "defs.h"
00038 
00039 #include "erglob.h"
00040 #include "tracing.h"
00041 #define NO_VARARGS_PROTOTYPES
00042 #include "linklist.h"
00043 #undef NO_VARARGS_PROTOTYPES
00044 
00045 char *_ary_lst_bounds_msg = "ARY LST index = %d, out of bounds: 0..%d";
00046 
00047 /*
00048  *  Define these macros in case we ever decide to put an additional
00049  *  filter on memory for linked lists data.  We never call 'malloc()'
00050  *  or 'free()' directly in this file -- we always go through these
00051  *  macros.
00052  */
00053 #define lnk_lst_malloc(x) ((MEM_PTR)malloc(x))
00054 #define lnk_lst_free(x)   free((MEM_PTR) (x))
00055 
00056 /*
00057  *  This data structure links together blocks of list items that have
00058  *  been allocated.  We have to save pointers to each allocated block
00059  *  so we can free all the list items at the end of a program unit.
00060  */
00061 typedef struct block_list_items {
00062   MEM_PTR block;                  /* ptr to block of memory alloced */
00063   struct block_list_items *next;  /* ptr to next block header */
00064 } BLK_LST_ITMS;
00065 
00066 #define BLK_block(blk)  ((blk)->block)
00067 #define BLK_next(blk)   ((blk)->next)
00068 
00069 LST_ITM * _lst_itm;  /* Definition added for ANSI C 4/19/92 (jfw) */
00070 
00071 static BLK_LST_ITMS *block_item_hdr = NULL;
00072 
00073 /*
00074  *  Allocate N_LIST_BLOCK linked list data items per block.
00075  *  We make this number just under some nice power of two, because we
00076  *  assume that blocks with a size that is a power of 2 (or just under
00077  *  a power of 2) are allocated fairly efficiently.  We don't make the
00078  *  block exactly a power of 2, because we must allocate an extra few
00079  *  bytes of overhead to keep a linked list of the blocks of memory
00080  *  allocated -- thus allowing us to free things up eventually (see the
00081  *  BLK_LST_ITMS data structure, above).
00082  */
00083 #define N_LIST_BLOCK (2048 - 5)
00084 
00085 /*
00086  *  Memory Blocks Size:  the total number of bytes of memory allocated
00087  *  by every call to 'list_malloc()', see below.
00088  *  This should be a power of 2 (or slightly less than a power of 2).
00089  */
00090 #define M_BLOCK_SIZE \
00091                   ((sizeof(LST_ITM)*N_LIST_BLOCK)+sizeof(BLK_LST_ITMS))
00092 
00093 static LST_ITM *list_items = NULL;
00094 static LST_ITM *_list_tmp;
00095 
00096 static LST_ITM *list_malloc(void);
00097 
00098 /* ====================================================================
00099  *
00100  *  LST_ITM *item_alloc()   (macro)
00101  *
00102  *  This macro removes a list item from the free list and returns a
00103  *  pointer to the removed item.  If the free list is empty, it
00104  *  allocates a block of items, links that block together onto the
00105  *  free list, and returns one of the newly allocated items.
00106  *
00107  *  NOTE: THIS IS THE ONLY WAY THAT A LIST ITEM SHOULD BE ALLOCATED.
00108  *
00109  * ====================================================================
00110  */
00111 #define item_alloc()   ( list_items ? \
00112                         ( (_list_tmp = list_items), \
00113                         (list_items = LST_next(list_items)), \
00114                         (LST_next(_list_tmp) = NULL), _list_tmp ) \
00115                                                    : list_malloc() )
00116 
00117 /* ====================================================================
00118  *
00119  *  item_free()   (macro)
00120  *
00121  *  This macro places a list item onto the free list.
00122  *
00123  *  NOTE: THIS IS THE ONLY WAY THAT A LIST ITEM SHOULD BE FREED.
00124  *
00125  * ====================================================================
00126  */
00127 #ifdef LNK_LST_CHECK
00128 # define item_free(itm) ( (LST_next(itm)=list_items), \
00129                                 (list_items=(itm)), (LST_val(itm)=0) )
00130 #else   /* LNK_LST_CHECK not defined */
00131 # define item_free(itm) ((LST_next(itm)=list_items), (list_items=(itm)))
00132 #endif  /* LNK_LST_CHECK not defined */
00133 
00134 #ifndef MONGOOSE_BE
00135 /* ====================================================================
00136  *
00137  *  static LST_ITM *list_malloc()
00138  *
00139  *  Allocate a block of memory for N_LIST_BLOCK linked list items and
00140  *  for a BLK_LST_ITMS element.  Link this block up with any previously
00141  *  allocated blocks.  Also, link all but one of of the N_LIST_BLOCK
00142  *  elements together and put them on the free list.
00143  *
00144  *  Return a pointer to the one item that was not put on the free list
00145  *  (and NULL out the 'LST_next()' field of the returned item).
00146  *
00147  *  NOTE:  THIS ROUTINE ASSUMES THE FREE LIST IS EMPTY.  THE ONLY CALLS
00148  *         TO THIS ROUTINE SHOULD BE FROM THE MACRO 'item_alloc()' WHEN
00149  *         THERE ARE NO FREE ELEMENTS REMAINING.
00150  * ====================================================================
00151  */
00152 
00153 static LST_ITM *
00154 list_malloc ( void )
00155 {
00156   MEM_PTR mem_block;
00157   BLK_LST_ITMS *blk;
00158   register LST_ITM *itm;
00159   register INT32 i;
00160 
00161   /*
00162    *  The free list had better be empty.
00163    */
00164   Is_True (list_items == NULL, ("list_malloc: free list is not empty"));
00165 
00166   if ( (mem_block = lnk_lst_malloc(M_BLOCK_SIZE)) == NULL )
00167     ErrMsg ( EC_No_Mem, "list_malloc" );
00168 
00169   /*
00170    *  Link this block up with any previously allocated blocks of
00171    *  list items.
00172    */
00173   blk = (BLK_LST_ITMS *) mem_block;
00174   BLK_block(blk) = mem_block;  /* it points to itself! */
00175   BLK_next(blk) = block_item_hdr;
00176   block_item_hdr = blk;
00177 
00178   /*
00179    *  Link (N_LIST_BLOCK-1) elements together and place them on the free
00180    *  list, making sure the last one on the free list points to NULL.
00181    *  Take the one remaining item, NULL out its pointer, and return it.
00182    */
00183   list_items = (LST_ITM *) ++blk;
00184   for (itm=list_items, i=0; i<(N_LIST_BLOCK-2); ++i, ++itm) {
00185     LST_val(itm) = -1;
00186     LST_next(itm) = itm+1;
00187   }
00188   LST_next(itm) = NULL;     /* "ground" the end of the free list */
00189 
00190   ++itm;     /* 'itm' now points to the one remaining item */
00191   LST_next(itm) = NULL;
00192 
00193   return itm;
00194 }
00195 #endif /* MONGOOSE_BE */
00196 
00197 #ifdef Is_True_On
00198 /* ====================================================================
00199  *
00200  *  check_linked_list_free
00201  *
00202  *  This routine is called only for compile-time checking.  At the point
00203  *  of call, we are about to free all the memory ever allocated for
00204  *  linked list elements.  Here, we walk through the entire free list,
00205  *  counting number of elements we have, and make sure that we have
00206  *  exactly the number that were allocated in total.  If they are the
00207  *  same, we just return TRUE.  If they differ, we print a diagnostic
00208  *  and return FALSE.
00209  *
00210  *  NOTE: this routine will not be called in a production compiler.
00211  *  If it finds we have not freed all the items it means we have a
00212  *  memory leak somewhere.  This is bad, but it is not a valid reason
00213  *  to abort a user's compilation.
00214  *
00215  * ====================================================================
00216  */
00217 
00218 static void
00219 check_linked_list_free ( void )
00220 {
00221   INT32 n_total = 0;
00222   INT32 n_in_free = 0;
00223   INT32 n_blocks = 0;
00224   BLK_LST_ITMS *blk;
00225   LST_ITM *item = list_items;
00226 
00227   for (blk=block_item_hdr; blk!=NULL; blk=BLK_next(blk), ++n_blocks)
00228     n_total += N_LIST_BLOCK;
00229 
00230   for (item=list_items; item!=NULL; item=LST_next(item), ++n_in_free)
00231     /* NULL statement list -- just counting items */ ;
00232 
00233   if ( n_total != n_in_free ) {
00234     DevWarn("WARNING: %d linked list items allocated in %d"
00235                 " blocks, but %d in free list",
00236                 n_total, n_blocks, n_in_free);
00237     ErrMsg ( EC_Mem_Leak, "Free_All_List_Items" );      /* Warning */
00238   }
00239 }
00240 #endif    /* Is_True_On */
00241 
00242 /* ====================================================================
00243  *
00244  *  void Free_All_List_Items()
00245  *
00246  *  Step through the blocks of memory that were allocated for all the
00247  *  list items and free them up.
00248  *
00249  *  This function should be called once for each program unit, after all
00250  *  linked list manipulation is complete.
00251  *
00252  * ====================================================================
00253  */
00254 
00255 void
00256 Free_All_List_Items ( void )
00257 {
00258   BLK_LST_ITMS *blk, *nblk;
00259 
00260 /* We've had more than a year to decide we cared enough about this to
00261  * track it down and we haven't.  There's a bug filed.  I'm sick of
00262  * the stupid/cute message.  Enable the check if you plan to do
00263  * something about it and not until!    -- Rutt
00264  */ 
00265  
00266 #if 0
00267 # ifdef Is_True_On
00268   check_linked_list_free();
00269 # endif
00270 # endif
00271 
00272   for (blk=block_item_hdr; blk!=NULL; blk=nblk) {
00273     nblk = BLK_next(blk);
00274     (void) lnk_lst_free(blk);
00275   }
00276 
00277   list_items = NULL;
00278   block_item_hdr = NULL;
00279 }
00280 
00281 #ifndef MONGOOSE_BE
00282 /* ====================================================================
00283  *
00284  *  void ARY_Init_List(LNK_LST_ARY *ary, INT32 n_elems)
00285  *
00286  *  Allocate an array of 'n_elems' linked list headers for the array of
00287  *  lists 'ary'.  Initialize each list.
00288  *
00289  * ====================================================================
00290  */
00291 
00292 void
00293 ARY_Init_List ( LNK_LST_ARY *ary, INT32 n_elems )
00294 {
00295   register INT32 i;
00296   register LNK_LST *lst;
00297 
00298   Is_True (n_elems >= 1,
00299      ("ARY_Init_List: attempt to allocate array of size %d", n_elems) );
00300 
00301   if ((lst=(LNK_LST *)lnk_lst_malloc(sizeof(LNK_LST)*n_elems)) == NULL)
00302     ErrMsg ( EC_No_Mem, "ARY_Init_List" );
00303 
00304   LST_lists(ary) = lst;
00305   ARY_LST_n_elems(ary) = n_elems;
00306 
00307   for (i=0; i<n_elems; ++i, ++lst)
00308     Init_List( lst );
00309 }
00310 /* ====================================================================
00311  *
00312  *  void Free_List(LNK_LST *lst)
00313  *
00314  *  Free all the items in the linked list 'lst' (i.e., put the items on
00315  *  the free list).  Set the length of the list to 0.
00316  *
00317  * ====================================================================
00318  */
00319 
00320 void
00321 Free_List ( LNK_LST *lst )
00322 {
00323   register LST_ITM *p1, *p2;
00324 
00325   for (p1=LST_first(lst); p1!=NULL; p1=p2) {
00326     p2 = LST_next(p1);
00327     item_free(p1);
00328   }
00329 
00330   Init_List(lst);
00331 }
00332 
00333 /* ====================================================================
00334  *
00335  *  void ARY_Free_List(LNK_LST_ARY *ary)
00336  *
00337  *  Free each list in the array of linked lists 'ary'.  Also, free up
00338  *  the linked list headers.
00339  *
00340  * ====================================================================
00341  */
00342 
00343 void
00344 ARY_Free_List ( LNK_LST_ARY *ary )
00345 {
00346   INT32 n_elems = ARY_LST_n_elems(ary);
00347   INT32 i;
00348 
00349   for (i=0; i<n_elems; ++i)
00350     Free_List ( ARY_LST_Elem(ary,i) );
00351 
00352   (void) lnk_lst_free(LST_lists(ary));     /* free the headers */
00353 }
00354 
00355 /* ====================================================================
00356  *
00357  * Validate_List
00358  *
00359  * Validate a list, i.e. verify that it contains no cycles and that its
00360  * stored length matches its actual length.
00361  *
00362  * ====================================================================
00363  */
00364 
00365 BOOL
00366 Validate_List ( LNK_LST *lst )
00367 {
00368   INT32 count = LST_Len(lst);
00369   LST_ITM *p;
00370 
00371   for ( p=LST_first(lst); p!=NULL; p=LST_next(p) ) {
00372     if ( --count < 0 ) break;
00373   }
00374   if ( count != 0 ) {
00375     DevWarn("##### Validate_List: Invalid count #####" );
00376     count = 10*LST_Len(lst);
00377     for ( p=LST_first(lst); p!=NULL; p=LST_next(p) ) {
00378         if ( --count < 0 ) break;
00379         DevWarn("  %p: %d", p, LST_val(p) );
00380     }
00381     FmtAssert ( FALSE,
00382                 ( "Validate_List: invalid count %d", LST_Len(lst) ) );
00383     return FALSE;
00384   }
00385   return TRUE;
00386 }
00387 #endif /* MONGOOSE_BE */
00388 
00389 #ifndef STORE_LIST_LEN
00390 /* ====================================================================
00391  *
00392  *  INT32 LST_Len(LNK_LST *lst)
00393  *
00394  *  Count the number of elements in the list and return that value.
00395  *
00396  *  Note that this is implemented as a routine only if the length is
00397  *  not stored directly in the list data structures.  If the length
00398  *  is stored there, this operation is implemented as a macro.  See
00399  *  the discussion in "linklist.h" regarding STORE_LST_LEN.
00400  *
00401  * ====================================================================
00402  */
00403 
00404 INT32
00405 LST_Len ( LNK_LST *lst )
00406 {
00407   register INT32 count = 0;
00408   register LST_ITM *p;
00409 
00410   for (p=LST_first(lst); p!=NULL; p=LST_next(p))
00411     ++count;
00412 
00413   return count;
00414 }
00415 #endif      /* STORE_LIST_LEN not defined */
00416 
00417 #ifndef MONGOOSE_BE
00418 /* ====================================================================
00419  *
00420  *  BOOL Add_Item(LNK_LST *lst, tlst_val val)
00421  *
00422  *  Add the item 'val' to the linked list 'lst'.  If the item is already
00423  *  in the list, do not add it again.
00424  *  Update the number of items in the list.
00425  *
00426  *  Return TRUE if the item was added, FALSE if not.
00427  *
00428  * ====================================================================
00429  */
00430 
00431 BOOL
00432 Add_Item ( LNK_LST *lst, tlst_val val)
00433 {
00434   register LST_ITM *p, *last;
00435 
00436   if (LST_Empty(lst)) {
00437     LST_first(lst) = p = item_alloc();
00438     LST_val(p) = val;
00439     incr_LST_len(lst);
00440     return TRUE;
00441   }
00442 
00443   last = NULL;  /* unnecessary except to eliminate warning msg */
00444   for (p=LST_first(lst); p!=NULL; p=LST_next(p)) {
00445     if (LST_val(p) == val)
00446       return FALSE;    /* already in the list => return FALSE */
00447     last = p;
00448   }
00449 
00450   /*
00451    *  If we get to here, we went through the list without finding a
00452    *  matching item.  Append a new item to the end of the list.
00453    */
00454   LST_next(last) = p = item_alloc();
00455   LST_val(p) = val;
00456   incr_LST_len(lst);
00457 
00458   /*
00459    *  If the pointer to the next item in the list is NULL, i.e. when
00460    *  stepping through the list the end was reached, then make the next
00461    *  item be this new item.
00462    */
00463   if (LST_nxt(lst) == NULL)
00464     LST_nxt(lst) = p;
00465 
00466   return TRUE;
00467 }
00468 
00469 /* ====================================================================
00470  *
00471  * Add_Item_Validate
00472  *
00473  * Identical to Add_Item, plus verification of the list afterwards.
00474  *
00475  * ====================================================================
00476  */
00477 
00478 BOOL
00479 Add_Item_Validate ( LNK_LST *lst, tlst_val val)
00480 {
00481   BOOL added = Add_Item ( lst, val );
00482 
00483   (void) Validate_List ( lst );
00484   return added;
00485 }
00486 
00487 /* ====================================================================
00488  *
00489  *  void Add_Item_Dup(LNK_LST *lst, tlst_val val)
00490  *
00491  *  Add the item 'val' to the linked list 'lst', even if the item is
00492  *  already in the list.
00493  *  Update the number of items in the list.
00494  *
00495  * ====================================================================
00496  */
00497 
00498 void
00499 Add_Item_Dup ( LNK_LST *lst, tlst_val val )
00500 {
00501   LST_ITM *p;
00502   LST_ITM *last;
00503 
00504 
00505   if (LST_Empty(lst)) {
00506     LST_first(lst) = p = item_alloc();
00507     LST_val(p) = val;
00508     incr_LST_len(lst);
00509     return;
00510   }
00511 
00512   /*
00513    *  Find the end of the list.
00514    */
00515   last = NULL;  /* unnecessary except to eliminate warning msg */
00516   for (p=LST_first(lst); p!=NULL; p=LST_next(p))
00517     last = p;
00518 
00519   /*
00520    *  Append a new item to the end of the list.
00521    */
00522   LST_next(last) = p = item_alloc();
00523   LST_val(p) = val;
00524   incr_LST_len(lst);
00525 
00526   /*
00527    *  If the pointer to the next item in the list is NULL, i.e. when
00528    *  stepping through the list the end was reached, then make the next
00529    *  item be this new item.
00530    */
00531   if (LST_nxt(lst) == NULL)
00532     LST_nxt(lst) = p;
00533 
00534 #ifdef BB_VALIDATE_LIST
00535   Validate_List ( lst );
00536 #endif
00537 
00538   return;
00539 }
00540 
00541 /* ====================================================================
00542  *
00543  *  void Add_First_Item(LNK_LST *lst, tlst_val val)
00544  *
00545  *  Add the item 'val' to the beginning of linked list 'lst'.
00546  *  Update the number of items in the list.
00547  *
00548  *  NOTE:  The item is added even if it is already in the list.
00549  *
00550  * ====================================================================
00551  */
00552 
00553 void
00554 Add_First_Item ( LNK_LST *lst, tlst_val val )
00555 {
00556   register LST_ITM *p;
00557 
00558   p = item_alloc();
00559   LST_val(p) = val;
00560   LST_next(p) = LST_first(lst);
00561   LST_first(lst) = p;
00562   incr_LST_len(lst);
00563 }
00564 
00565 /* ====================================================================
00566  *
00567  *  BOOL Add_Ordered_Item(LNK_LST *lst, tlst_val val)
00568  *
00569  *  Add the item 'val' to the ordered linked list 'lst'.  If the item is
00570  *  already in the list, do not add it again.
00571  *  Update the number of items in the list.
00572  *
00573  *  Note: The list *must* be ordered and may not contain any duplicates
00574  *  for this routine to work properly.
00575  *
00576  *  Return TRUE if the item was added, FALSE if not.
00577  *
00578  * ====================================================================
00579  */
00580 
00581 BOOL
00582 Add_Ordered_Item ( LNK_LST *lst, tlst_val val )
00583 {
00584   register LST_ITM *p, *last;
00585   register tlst_val this_val;
00586 
00587   if (LST_Empty(lst)) {
00588     LST_first(lst) = p = item_alloc();
00589     LST_val(p) = val;
00590     incr_LST_len(lst);
00591     return TRUE;
00592   }
00593 
00594   p = LST_first(lst);
00595   if ( (this_val = LST_val(p)) == val ) {
00596     return FALSE;    /* already in the list => return FALSE */
00597 
00598   } else if ( val < this_val ) {  /* insert at beginning of the list */
00599     register LST_ITM *new = item_alloc();
00600     LST_next(new) = p;
00601     LST_first(lst) = new;
00602     LST_val(new) = val;
00603     incr_LST_len(lst);
00604     return TRUE;
00605   }
00606 
00607   last = p;
00608   for ( p=LST_next(p); p!=NULL; p=LST_next(p)) {
00609 #ifdef LNK_LST_CHECK
00610     Is_True ( this_val < LST_val(p),
00611       ("ordered list not sorted: elems %d and %d",this_val,LST_val(p)));
00612 #endif  /* LNK_LST_CHECK */
00613     if ( (this_val = LST_val(p)) == val ) {
00614       return FALSE;    /* already in the list => return FALSE */
00615 
00616     } else if ( val < this_val ) {  /* insert here */
00617       register LST_ITM *new = item_alloc();
00618       LST_next(new) = p;
00619       LST_next(last) = new;
00620       LST_val(new) = val;
00621       incr_LST_len(lst);
00622       return TRUE;
00623     }
00624     last = p;
00625   }
00626 
00627   /*
00628    *  If we get to here, we went through the list without finding a
00629    *  matching item, and all items in the list have values less than
00630    *  the new value.  Append a new item to the end of the list.
00631    */
00632   LST_next(last) = p = item_alloc();
00633   LST_val(p) = val;
00634   incr_LST_len(lst);
00635 
00636   /*
00637    *  If the pointer to the next item in the list is NULL, i.e. when
00638    *  stepping through the list the end was reached, then make the next
00639    *  item be this new item.
00640    */
00641   if (LST_nxt(lst) == NULL)
00642     LST_nxt(lst) = p;
00643 
00644   return TRUE;
00645 }
00646 
00647 /* ====================================================================
00648  *
00649  *  void Add_Ordered_Item_Dupl(LNK_LST *lst, tlst_val val)
00650  *
00651  *  Add the item 'val' to the ordered linked list 'lst'.  If the item is
00652  *  already in the list, add a duplicate.
00653  *  Update the number of items in the list.
00654  *
00655  *  Note: The list *must* already be ordered for this routine to
00656  *  work properly.
00657  *
00658  * ====================================================================
00659  */
00660 
00661 void
00662 Add_Ordered_Item_Dupl ( LNK_LST *lst, tlst_val val )
00663 {
00664   register LST_ITM *p, *last;
00665   register tlst_val this_val;
00666 
00667   if (LST_Empty(lst)) {
00668     LST_first(lst) = p = item_alloc();
00669     LST_val(p) = val;
00670     incr_LST_len(lst);
00671     return;
00672   }
00673 
00674   p = LST_first(lst);
00675   this_val = LST_val(p);
00676 
00677   if ( val <= this_val ) {  /* insert at beginning of the list */
00678     register LST_ITM *new = item_alloc();
00679     LST_next(new) = p;
00680     LST_first(lst) = new;
00681     LST_val(new) = val;
00682     incr_LST_len(lst);
00683     return;
00684   }
00685 
00686   last = p;
00687   for ( p=LST_next(p); p!=NULL; p=LST_next(p)) {
00688 #ifdef LNK_LST_CHECK
00689     Is_True ( this_val <= LST_val(p),
00690       ("ordered list not sorted: elems %d and %d",this_val,LST_val(p)));
00691 #endif  /* LNK_LST_CHECK */
00692 
00693     this_val = LST_val(p);
00694     if ( val <= this_val ) {  /* insert here */
00695       register LST_ITM *new = item_alloc();
00696       LST_next(new) = p;
00697       LST_next(last) = new;
00698       LST_val(new) = val;
00699       incr_LST_len(lst);
00700       return;
00701     }
00702     last = p;
00703   }
00704 
00705   /*
00706    *  If we get to here, we went through the list without finding a
00707    *  matching item, and all items in the list have values less than
00708    *  the new value.  Append a new item to the end of the list.
00709    */
00710   LST_next(last) = p = item_alloc();
00711   LST_val(p) = val;
00712   incr_LST_len(lst);
00713 
00714   /*
00715    *  If the pointer to the next item in the list is NULL, i.e. when
00716    *  stepping through the list the end was reached, then make the next
00717    *  item be this new item.
00718    */
00719   if (LST_nxt(lst) == NULL)
00720     LST_nxt(lst) = p;
00721 }
00722 
00723 /* ====================================================================
00724  *
00725  *  BOOL Del_Item(LNK_LST *lst, tlst_val val)
00726  *
00727  *  Delete the item 'val' from the linked list 'lst' (and free the
00728  *  deleted item).
00729  *  Update the number of items in the list.
00730  *
00731  *  Return TRUE if the item was deleted, FALSE if not (ie it wasn't
00732  *  there).
00733  *
00734  *  NOTE:
00735  *      If the item being deleted is the 'next' item in the list
00736  *      then make the 'next' item in the list the one AFTER the
00737  *      item being deleted.
00738  *
00739  * ====================================================================
00740  */
00741 
00742 BOOL
00743 Del_Item ( LNK_LST *lst, tlst_val val )
00744 {
00745   register LST_ITM *p, *last;
00746 
00747   if (LST_Empty(lst))
00748     return FALSE; /* not in the list => nothing to delete */
00749 
00750   last = NULL;
00751   for (p=LST_first(lst); p!=NULL; p=LST_next(p)) {
00752 
00753     if (LST_val(p) == val) {
00754 
00755       if (LST_nxt(lst) == p) /* item being deleted is 'next' item */
00756         LST_nxt(lst) = LST_next(p);
00757 
00758       if (last == NULL)     /* it was the first item in the list */
00759         LST_first(lst) = LST_next(p);
00760       else      /* it was not the first item in the list */
00761         LST_next(last) = LST_next(p);
00762 
00763       item_free(p);       /* put deleted item into the free list */
00764       decr_LST_len(lst);
00765       return TRUE; /* it was deleted from the list => return TRUE */
00766 
00767     }
00768 
00769     last = p;
00770   }
00771 
00772   /*
00773    *  If we get to here, we went through the list searching for the item
00774    *  but could not find it.  Just return FALSE.
00775    */
00776   return FALSE;
00777 }
00778 
00779 /* ====================================================================
00780  *
00781  *  BOOL Del_Cur_Item(LNK_LST *lst)
00782  *
00783  *  Delete the "current" item from the linked list 'lst' (and free the
00784  *  deleted item).  Note that the current item is, by definition, the
00785  *  item whose LST_next(item) field the same as the LST_nxt(lst) field
00786  *  of the list-header.  Therefore, this routine can only be called
00787  *  when the LST_nxt(lst) field is valid -- i.e., only when stepping
00788  *  through the list.
00789  *
00790  *  Update the number of items in the list.
00791  *
00792  *  Return TRUE if there was an item that was deleted, FALSE if not
00793  *  (i.e., FALSE when the list was empty on input).
00794  *
00795  * ====================================================================
00796  */
00797 
00798 BOOL
00799 Del_Cur_Item ( LNK_LST *lst )
00800 {
00801   LST_ITM *p, *last;
00802   LST_ITM *next_item = LST_nxt(lst);
00803 
00804   if ( LST_Empty(lst) )
00805     return FALSE; /* not in the list => nothing to delete */
00806 
00807   last = NULL;
00808   for ( p=LST_first(lst); p!=NULL; p=LST_next(p) ) {
00809 
00810     if ( LST_next(p) == next_item ) {
00811 
00812       if ( last == NULL )       /* it was the first item in the list */
00813         LST_first(lst) = LST_next(p);
00814       else      /* it was not the first item in the list */
00815         LST_next(last) = LST_next(p);
00816 
00817       item_free ( p );  /* put deleted item into the free list */
00818       decr_LST_len(lst);
00819       return TRUE;      /* it was deleted from the list => return TRUE */
00820 
00821     }
00822 
00823     last = p;
00824   }
00825 
00826   /* If we get to here, we went through the list, but we did not find
00827    *  an item with an LST_next field matching the next item of the list.
00828    */
00829   return FALSE;
00830 }
00831 
00832 /* ====================================================================
00833  *
00834  *  BOOL Item_In_List(LNK_LST *lst, tlst_val val)
00835  *
00836  *  Check to see if the item 'val' is in the linked list 'lst'.
00837  *
00838  *  Return TRUE if the item is in the list, FALSE if not.
00839  *
00840  * ====================================================================
00841  */
00842 
00843 BOOL
00844 Item_In_List ( LNK_LST *lst, tlst_val val )
00845 {
00846   register LST_ITM *p;
00847 
00848   if (LST_Empty(lst))
00849     return FALSE;       /* empty list => not in the list */
00850 
00851   for (p=LST_first(lst); p!=NULL; p=LST_next(p))
00852     if (LST_val(p) == val)
00853       return TRUE; /* found it */
00854 
00855   /*
00856    *  If we get to here, we went through the list searching for the item
00857    *  but could not find it.  Just return FALSE.
00858    */
00859   return FALSE;
00860 }
00861 
00862 /* ====================================================================
00863  *
00864  *  BOOL ARY_Item_In_List(LNK_LST_ARY *ary, INT32 i, tlst_val val)
00865  *
00866  *  Check to see if the item 'val' is in the linked list 'ary[i]' ('ary'
00867  *  is an array of linked lists).
00868  *
00869  *  Return TRUE if the item is in the list, FALSE if not.
00870  *
00871  * ====================================================================
00872  */
00873 
00874 BOOL
00875 ARY_Item_In_List ( LNK_LST_ARY *ary, INT32 i, tlst_val val )
00876 {
00877   register LNK_LST *lst = ARY_LST_Elem(ary,i);
00878   register LST_ITM *p;
00879 
00880   if (LST_Empty(lst))
00881     return FALSE;       /* empty list => not in the list */
00882 
00883   for (p=LST_first(lst); p!=NULL; p=LST_next(p))
00884     if (LST_val(p) == val)
00885       return TRUE; /* found it */
00886 
00887   /*
00888    *  If we get to here, we went through the list searching for the item
00889    *  but could not find it.  Just return FALSE.
00890    */
00891   return FALSE;
00892 }
00893 /* ====================================================================
00894  *
00895  * List_Print
00896  *
00897  * Print the message 'msg' along with any arguments.  Then print each
00898  * item in the linked list 'lst' (print the items in decimal form).
00899  *
00900  * NOTE: All output is written to the "trace file" whose file
00901  *       pointer is in the externally defined variable, 'TFile'.
00902  *
00903  * ====================================================================
00904  */
00905 
00906 void
00907 List_Print ( lst, msg, arg1, arg2, arg3 )
00908   LNK_LST *lst;
00909   char *msg;
00910   INT32 arg1, arg2, arg3;
00911 {
00912   tlst_val data;
00913 
00914   fprintf ( TFile, msg, arg1, arg2, arg3 );
00915   fprintf ( TFile,"\n" );
00916 
00917   /*
00918    *  Loop over all the items, printing the data value.
00919    */
00920   data = First_Item(lst);
00921   for (data=First_Item(lst); Valid_Item(data); data=Next_Item(lst))
00922     fprintf ( TFile," %d", data );
00923 
00924   fprintf(TFile,"\n");
00925 }
00926 
00927 /* ====================================================================
00928  *
00929  * ARY_List_Print
00930  *
00931  * Print the message 'msg' along with any arguments.  Then print each
00932  * linked list in the array of linked lists 'ary' (print the items in
00933  * decimal form).
00934  *
00935  * NOTE: All output is written to the "trace file" whose file
00936  *       pointer is in the externally defined variable, 'TFile'.
00937  *
00938  * ====================================================================
00939  */
00940 
00941 void
00942 ARY_List_Print ( ary, msg, arg1, arg2, arg3 )
00943   LNK_LST_ARY *ary;
00944   char *msg;
00945   INT32 arg1, arg2, arg3;
00946 {
00947   INT32 n_elems = ARY_LST_n_elems(ary);
00948   INT32 i;
00949   tlst_val data;
00950   LNK_LST *lst;
00951 
00952   fprintf(TFile,msg,arg1,arg2,arg3);
00953   fprintf(TFile,"\n");
00954 
00955   /*
00956    *  Loop over all the lists in the array of linked lists.
00957    */
00958   for (i=0; i<n_elems; ++i) {
00959     /*
00960      *  Loop over all the items, printing the data value.
00961      */
00962     lst = ARY_LST_Elem(ary,i);
00963     data=First_Item(lst);
00964     if (Invalid_Item(data))
00965       continue;
00966     fprintf(TFile,"%3d: ", i);
00967     for (; Valid_Item(data); data=Next_Item(lst))
00968       fprintf ( TFile," %d", data );
00969 
00970     fprintf(TFile,"\n");
00971   }
00972 }
00973 #endif /* MONGOOSE_BE */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines