Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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 */