1 /************************************************************
3 ** COPYRIGHT (C) 1993 UNIVERSITY OF PITTSBURGH
4 ** COPYRIGHT (C) 1996 GANNON UNIVERSITY
7 ** This software is distributed on an as-is basis
8 ** with no warranty implied or intended. No author
9 ** or distributor takes responsibility to anyone
10 ** regarding its use of or suitability.
12 ** The software may be distributed and modified
13 ** freely for academic and other non-commercial
14 ** use but may NOT be utilized or included in whole
15 ** or part within any commercial product.
17 ** This copyright notice must remain on all copies
18 ** and modified versions of this software.
20 ************************************************************/
23 /* ------------------------------------------------------------------------
24 * Helper / Utility routines for place and route spl 7/89, stf 2/90
25 * ------------------------------------------------------------------------
29 /*------------------------------------------------------------------------
30 * The following list processing functions are based on the following two
32 typedef struct list_struct list;
33 typedef struct indexed_list ilist;
48 *------------------------------------------------------------------------ */
50 /* ------------------------------------------------------------------------
51 * concat_list: append a generic thing to the head of a list.
52 * works for null lists.
53 * ------------------------------------------------------------------------
56 list
*concat_list(e
,l
)
62 p
= (list
*) calloc(1, sizeof(list
));
69 /* ------------------------------------------------------------------------
70 * append_list: append two generic lists together.
71 * Works for either list null.
72 * If both lists are null, it returns null.
73 * ------------------------------------------------------------------------
76 list
*append_list(l1
,l2
)
85 for(p
= l1
; p
->next
!= NULL
; p
= p
->next
)
94 /*---------------------------------------------------------------
96 * cut out a generic list element from the middle of a list
97 * note the parameter must be the address of the real thing, not
98 * a copy. so this should be called with the address of a
99 * subfield ie remove_list_element(&(thing->next))
100 * both remove_list_element(thing->next)
101 * and remove_list_element(&thing) (unless thing is global) will not work.
102 *---------------------------------------------------------------
104 void remove_list_element(lptr
)
112 my_free(trash
); /* Trash freed, contents not touched. */
115 /*--------------------------------------------------------------------------
117 * Clip all of the elements of the given list who's ->this field return TRUE
118 * to the given <testFn>. (Recursive implementation).
119 *--------------------------------------------------------------------------
121 list
*delete_if(lptr
, testFn
)
123 int (*testFn
)(); /* Should take a single *int as its arg, return TRUE/FALSE */
125 /* Remove all list elements that return TRUE to the <testFn> call. */
127 if (*lptr
== NULL
) return(NULL
);
128 else if ((*testFn
)(ll
->this) == TRUE
) /* The first list item should go */
130 remove_list_element(lptr
);
131 return(delete_if(lptr
, testFn
));
134 else /* Later list items should get nuked */
137 ll
->next
= delete_if(&ll
->next
, testFn
);
141 /* ------------------------------------------------------------------------
142 * pushnew - add a unique element to the front of a linked list
143 * ------------------------------------------------------------------------
145 void pushnew(what
, l
)
152 for (ll
= *l
; ll
!= NULL
; ll
= ll
->next
)
154 if ((int)what
== (int)ll
->this) flag
= FALSE
;
156 if (flag
== TRUE
) push(what
, l
);
159 /* ------------------------------------------------------------------------
160 * push - add to the front of a linked list
161 * ------------------------------------------------------------------------
168 if ((ll
= (list
*)calloc(1, sizeof(list
))) == NULL
)
170 fprintf(stderr
,"\nNo more room (push)"); exit(0);
180 /* ------------------------------------------------------------------------
181 * pop - (FILO) pop from the front of a linked list
182 * ------------------------------------------------------------------------
188 int * item
= ll
->this;
193 /* ------------------------------------------------------------------------
194 * queue - add to the back of a linked list
195 * ------------------------------------------------------------------------
203 if (q
== NULL
) /* create the list */
205 q
= (list
*)calloc(1, sizeof(list
));
211 { /* find the end of <l>: */
212 for(q
= *l
; q
->next
!= NULL
; q
= q
->next
);
213 queue (what
, &q
->next
);
216 /* ------------------------------------------------------------------------
217 * trans_item - pull from an unknown position within the first list, push
219 * ------------------------------------------------------------------------
221 extern int *trans_item(what
, sList
, dList
)
223 list
**sList
, **dList
;
225 list
*r
= *dList
, *q
= *sList
;
227 if (q
== NULL
) return (NULL
);
228 else if (q
->this == what
) /* Front of <sList> */
229 { /* Make the transfer */
230 *sList
= q
->next
; /* Pull from <sList> */
231 q
->next
= *dList
; /* Push onto <dList> */
236 { /* find the end of <sList>: */
237 for(q
= *sList
; ((q
->next
!= NULL
) && (q
->next
->this != what
)); q
= q
->next
);
238 return (trans_item(what
, &q
->next
, dList
));
242 /* ------------------------------------------------------------------------
243 * rem_item - pull from an unknown position within the list
244 * ------------------------------------------------------------------------
246 int *rem_item(what
, l
)
252 if (q
== NULL
) return (NULL
);
253 else if (q
->this == what
)
260 { /* find the end of <l>: */
261 for(q
= *l
; ((q
->next
!= NULL
) && (q
->next
->this != what
)); q
= q
->next
);
262 return (rem_item(what
, &q
->next
));
265 /* ------------------------------------------------------------------------
266 * repl_item - pull from an unknown position within the list, replace with
268 * ------------------------------------------------------------------------
270 int *repl_item(what
, new, l
)
276 if (q
== NULL
) return (NULL
);
277 else if (q
->this == what
)
283 { /* find the end of <l>: */
284 for(q
= l
; ((q
->next
!= NULL
) && (q
->next
->this != what
)); q
= q
->next
);
285 return (repl_item(what
, new, q
->next
));
288 /* ------------------------------------------------------------------------
289 * find_item - see if the item is in the list
290 * ------------------------------------------------------------------------
292 list
*find_item(what
, l
)
298 for (q
= l
; q
!= NULL
; q
= q
->next
)
300 if (q
->this == what
) return(q
);
305 /* ------------------------------------------------------------------------
306 * nth - Note: Numbering starts at one.
307 * ------------------------------------------------------------------------
313 /* This returns the Nth element of the list <l> given that there are at
314 least <n> elements on <l>. */
316 for (; l
!= NULL
; l
= l
->next
)
318 if (i
== n
) return(l
->this);
323 /* ------------------------------------------------------------------------
324 * nth_cdr - Note: Numbering starts at one.
325 * ------------------------------------------------------------------------
331 /* This returns the Nth element of the list <l> given that there are at
332 least <n> elements on <l>. */
334 if (n
== 0) return(l
); /* simple case... */
336 for (; l
!= NULL
; l
= l
->next
)
338 if (i
== n
) return(l
);
344 /* ------------------------------------------------------------------------
347 * ------------------------------------------------------------------------
354 for(i
= 0; l
!= NULL
; l
= l
->next
)
361 /* ------------------------------------------------------------------------
362 * member_p - returns TRUE iff the given pointer returns TRUE when compared
363 * with the ->this slot of some list element.
364 * ------------------------------------------------------------------------
366 int member_p(e
, l
, testFn
)
369 int (*testFn
)(); /* Should take two *int's as args, return TRUE/FALSE */
373 for(ll
= l
; ll
!= NULL
; ll
= ll
->next
)
375 if ((*testFn
)(e
, ll
->this) == TRUE
) return(TRUE
);
380 /* ------------------------------------------------------------------------
381 * member - returns list pointer to the first item that returns TRUE to
382 * the testFn(e, ll->this) query. Returns NULL otherwise.
383 * ------------------------------------------------------------------------
385 list
*member(e
, l
, testFn
)
388 int (*testFn
)(); /* Should take two *int's as args, return TRUE/FALSE */
392 for(ll
= l
; ll
!= NULL
; ll
= ll
->next
)
394 if ((*testFn
)(e
, ll
->this) == TRUE
) return(ll
);
399 /* ------------------------------------------------------------------------
400 * rcopy_list: make a copy of a list, reversing it for speed/convience
401 * ------------------------------------------------------------------------
409 for(ll
= l
; ll
!= NULL
; ll
= ll
->next
)
416 /* ------------------------------------------------------------------------
417 * copy_list: make a copy of a list, preserving order
418 * ------------------------------------------------------------------------
427 /* error: "copy_list passed null list" */
430 pp
= p
= (list
*) calloc(1, sizeof(list
));
434 p
->next
= (list
*) calloc(1, sizeof(list
));
441 /* ------------------------------------------------------------------------
442 * delete_duplicates Modify the given list by deleting duplicate elements:
443 * ------------------------------------------------------------------------
445 list
*delete_duplicates(l
, testFn
)
447 int (*testFn
)(); /* Should take two *int's as args, return TRUE/FALSE */
450 list
*p
, *pp
, *trash
, *last
;
454 /* error: "delete_duplicates passed null list" */
458 for (p
= *l
; ((p
!= NULL
) && (p
->next
!= NULL
)); p
= p
->next
)
462 for (pp
= p
->next
; pp
!= NULL
;)
464 if (testFn(targ
, pp
->this) == TRUE
)
466 last
->next
= pp
->next
;
480 /* ------------------------------------------------------------------------
481 * my_free wipe this pointer from memory.
482 * ------------------------------------------------------------------------
484 extern int *my_free(p
)
491 /* ------------------------------------------------------------------------
492 * free_list wipe this list from memory. Do not disturb any list elements.
493 * ------------------------------------------------------------------------
502 for(ll
= l
; ll
!= NULL
;)
507 /* Explicitly wipe memory */ /* ??? */
508 cptr
= (char *)trash
;
509 for (i
= 0; i
< sizeof(list
); i
++)
518 /* ------------------------------------------------------------------------
519 * sort_list (destructive) sort the given list via orderFn:
520 * ------------------------------------------------------------------------
522 list
*sort_list(l
, orderFn
)
524 int (*orderFn
)(); /* Should take two *int's as args, return TRUE/FALSE */
525 /* TRUE implies the first element belongs in front of the second */
529 int i
, j
, *temp
, stop
;
530 int exchange
, len
= list_length(l
);
533 for (i
= len
; i
> 1; i
-= 1)
538 for (j
= 0; ((lp
!= NULL
) && (lp
->next
!= NULL
) && (j
< stop
)); j
+= 1)
540 /* One bubbling pass - Compare lp->this with lp->next->this */
541 if (orderFn(lp
->this, lp
->next
->this) == FALSE
)
543 /* Swap lp->this with lp->next->this */
545 lp
->this = lp
->next
->this;
546 lp
->next
->this = temp
;
551 if (exchange
== FALSE
) break;
556 /* ------------------------------------------------------------------------
557 * merge_sort (destructive) sort the given list via orderFn:
558 * ------------------------------------------------------------------------
560 list
*merge_sort(l1
, l2
, n
, m
, orderFn
)
561 list
*l1
, *l2
; /* Two lists to be merge-sorted. */
562 int n
, m
; /* number of elements from <l1>, <l2> to sort... */
563 int (*orderFn
)(); /* Ordering function. Works on list elements */
565 /* The merge sorter... */
566 list
*mid1
, *mid2
, *t1
, *t2
, *r
, *result
;
569 mid1
= mid2
= t1
= t2
= r
= result
= NULL
;
571 if (l1
== l2
) result
= l1
; /* Handle the n = 0 case... */
573 else if ((n
== 1) && (m
== 0)) result
= l1
;
574 else if ((m
== 1) && (n
== 0)) result
= l2
;
576 else if ((n
== 1) && (m
== 1)) /* Handle the n = 1 case... */
578 if (orderFn(l1
->this, l2
->this) == FALSE
)
580 /* Swap l1->this with l2->this */
589 else /* if (l1 != l2) Handle the general case: */
591 t1
= nth_cdr(l1
, n
/2);
594 mid1
= t1
->next
; /* Split <l1> */
595 t1
->next
= NULL
; /* Terminate the temp list */
598 t2
= nth_cdr(l2
, m
/2);
601 mid2
= t2
->next
; /* Split <l2> */
602 t2
->next
= NULL
; /* Terminate the temp list */
605 /* Recursive calls... */
606 /* Sort the left sublist */
607 if ((n
== 0) || (n
== 1)) t1
= l1
;
608 else t1
= merge_sort(l1
, mid1
, n
/2, n
- n
/2, orderFn
);
610 /* Sort the right sublist */
611 if ((m
== 0) || (m
== 1)) t2
= l2
;
612 else t2
= merge_sort(l2
, mid2
, m
/2, m
- m
/2, orderFn
);
614 /* Check for errors: */
615 if ((t1
== NULL
) && (t2
== NULL
)) return(NULL
); /* Big Problem!! */
617 /* Merge the two sorted sublists, <t1> & <t2>... */
618 for(i
= n
+m
; i
!= 0; i
--) /* Merge all of the elements given... */
621 ((t1
== NULL
) || (orderFn(t1
->this, t2
->this) == FALSE
)))
623 /* The first element of <t2> gets added to the <result> list. */
628 r
->next
->next
= NULL
;
639 else /* ((t2 == NULL) || (orderFn(t1->this, t2->this) != FALSE)) */
641 /* The first element of <t1> gets added to the <result> list */
646 r
->next
->next
= NULL
;
661 /* ------------------------------------------------------------------------
662 * merge_sort_list (destructive) sort the given list via orderFn:
663 * ------------------------------------------------------------------------
665 list
*merge_sort_list(l
, orderFn
)
667 int (*orderFn
)(); /* Should take two *int's as args, return TRUE/FALSE */
668 /* TRUE implies the first element belongs in front of the second */
670 return(*l
= merge_sort(*l
, NULL
, list_length(*l
), 0, orderFn
));
674 /* ------------------------------------------------------------------------
675 * slow_sort_list (destructive) sort the given list via orderFn:
676 * ------------------------------------------------------------------------
678 list
*slow_sort_list(l
, orderFn
)
680 int (*orderFn
)(); /* Should take two *int's as args, return TRUE/FALSE */
681 /* TRUE implies the first element belongs in front of the second */
683 /* The slow sorter... */
687 for (lp
= l
; ((lp
!= NULL
) && (lp
->next
!= NULL
)); lp
= lp
->next
)
689 for (lpp
= lp
; lpp
!= NULL
; lpp
= lpp
->next
)
691 if (orderFn(lp
->this, lpp
->this) == FALSE
)
693 /* Swap lp->this with lpp->this */
695 lp
->this = lpp
->this;
702 /* ------------------------------------------------------------------------
703 * reverse_ilist: make a copy of an indexed list, inverting order while
704 * maintaining the original indexing
705 * ------------------------------------------------------------------------
707 ilist
*reverse_copy_ilist(l
)
710 ilist
*p
, *pp
= NULL
;
714 /* error: "reverse_copy_ilist passed null list" */
718 pp
= p
= (ilist
*) calloc(1, sizeof(ilist
));
720 pp
->index
= l
->index
;
725 p
= (ilist
*) calloc(1, sizeof(ilist
));
733 /* ------------------------------------------------------------------------
734 * rcopy_ilist: make a copy of an indexed list, inverting order
735 * ------------------------------------------------------------------------
737 ilist
*rcopy_ilist(l
)
740 ilist
*p
, *pp
= NULL
;
744 /* error: "rcopy_ilist passed null list" */
748 for (p
= l
; p
!= NULL
; p
= p
->next
)
754 /* ------------------------------------------------------------------------
755 * copy_ilist: make a copy of an indexed list, preserving order
756 * ------------------------------------------------------------------------
765 /* error: "copy_ilist passed null list" */
768 pp
= p
= (ilist
*) calloc(1, sizeof(ilist
));
773 p
->next
= (ilist
*) calloc(1, sizeof(ilist
));
782 /* ------------------------------------------------------------------------
783 * remove_indexed_element remove (by index) an element from a list structure
784 * NOTE: This renumbers the elements following the discovery.
787 * ------------------------------------------------------------------------
789 int *remove_indexed_element(indx
, lptr
)
798 if((lst
== NULL
)||(lst
->index
> indx
)||((lst
->index
!= indx
) && (lst
->next
== NULL
)))
802 for(l
= lst
; ; l
= l
->next
)
806 /* we already have a list at this index */
807 if (l
!=lst
) lst
->next
= l
-> next
; /* free trash? */
808 else *lptr
= l
->next
; /* pop off top of list */
812 /* renumber & assume it's there */
813 else if (l
->index
> indx
) --l
->index
;
815 /* quit once the list is exausted */
816 if ((l
->next
== NULL
) && (temp
)) return(temp
);
817 else if (l
->next
== NULL
)
818 { /* renumber the list and return null */
819 for (l
= *lptr
; ; l
= l
->next
)
821 if (l
->next
== NULL
) return(temp
);
822 else if (l
->index
> indx
) ++l
->index
;
829 /* ------------------------------------------------------------------------
830 * irem_item - pull from an unknown position within an indexed list
832 * ------------------------------------------------------------------------
834 int *irem_item(what
, l
, howFar
)
837 int howFar
; /* If != NULL, places a limit on the search */
841 if ((q
== NULL
) || ((howFar
!= NULL
) && (q
->index
> howFar
))) return (NULL
);
842 else if (what
== q
->this) /* Found the little Commie! */
844 *l
= q
->next
; /* Note: No renumbering occurs */
845 my_free(q
); /* Nuke it! */
849 { /* find the end of <l>: */
850 for(q
= *l
; ((q
->next
!= NULL
) && (q
->next
->this != what
)); q
= q
->next
);
851 return (irem_item(what
, &q
->next
, howFar
));
854 /* ------------------------------------------------------------------------
855 * find_indexed_element finds (by index) an element from a list structure
856 * note: this returns the list pointer to the requested element.
857 * ------------------------------------------------------------------------
859 ilist
*find_indexed_element(indx
, lst
)
865 if((lst
== NULL
)||(lst
->index
> indx
)) return (NULL
);
869 for(l
= lst
; ; l
= l
->next
)
871 if(l
->index
== indx
) return(l
);
873 /* quit once the list is exausted */
874 if (l
->next
== NULL
) return(NULL
);
879 /* ------------------------------------------------------------------------
880 * indexed_list_insert an element to an indexed list structure.
881 * ------------------------------------------------------------------------
883 int indexed_list_insert(element
, indx
, lptr
)
891 if((lst
== NULL
)||(lst
->index
> indx
))
893 tl
= (ilist
*)calloc(1, sizeof(ilist
));
902 for(l
= lst
; ; l
= l
->next
)
906 /* we already have a list at this index */
907 l
->this = element
; /* replace the contents with the new stuff */
910 if ( (l
->next
== NULL
) || (l
->next
->index
> indx
))
911 {/* note we are counting on order of above exp */
913 /* we hit the end or fall between two existing lists */
914 tl
= (ilist
*)calloc(1, sizeof(ilist
));
924 /* ------------------------------------------------------------------------
925 * ordered_ilist_insert an element to an indexed list structure.
926 * quite similar to "indexed_list_insert, saving that whenever an element having
927 * the same index value is encountered, rather than replacing the entry (as in
928 * the aforementioned function) a new list element is created, and placed in front
929 * of the first such entry encountered.
930 * ------------------------------------------------------------------------
932 int ordered_ilist_insert(element
, indx
, lptr
)
940 if((lst
== NULL
)||(lst
->index
> indx
))
942 tl
= (ilist
*)calloc(1, sizeof(ilist
));
951 for(l
= lst
; ; l
= l
->next
)
953 if ( (l
->next
== NULL
) || (l
->next
->index
>= indx
))
954 {/* note we are counting on order of above exp */
956 /* we hit the end or fall between two existing lists */
957 tl
= (ilist
*)calloc(1, sizeof(ilist
));
967 /* ------------------------------------------------------------------------
970 * ------------------------------------------------------------------------
977 for(i
= 0; l
!= NULL
; l
= l
->next
)
983 /* ------------------------------------------------------------------------
984 * ipop - (FILO) pop from the front of a indexed linked list (No renumbering)
985 * ------------------------------------------------------------------------
991 int *item
= ll
->this;
996 /* ------------------------------------------------------------------------
997 * ipush - (FILO) push to the front of a indexed linked list (renumbering)
998 * ------------------------------------------------------------------------
1005 if ((ll
= (ilist
*)calloc(1, sizeof(ilist
))) == NULL
)
1007 fprintf(stderr
,"\nNo more room (ipush)"); exit(0);
1016 for (ll
= ll
->next
; ll
!= NULL
; ll
= ll
->next
)
1018 /* Walk down the rest of the list and renumber */
1023 /* ------------------------------------------------------------------------
1024 * append_ilist: append two generic indexed lists together.
1025 * Works for either list null.
1026 * If both lists are null, it returns null.
1027 * ------------------------------------------------------------------------
1030 ilist
*append_ilist(l1
,l2
)
1040 for(p
= l1
; p
->next
!= NULL
; p
= p
->next
)
1046 for (p
= l2
; p
->next
!= NULL
; p
= p
->next
)
1053 /* ------------------------------------------------------------------------
1054 * free_ilist wipe this list from memory. Do not disturb any list elements.
1055 * ------------------------------------------------------------------------
1057 ilist
*free_ilist(l
)
1062 for(ll
= l
; ll
!= NULL
;)
1070 /* ------------------------------------------------------------------------
1072 * ------------------------------------------------------------------------