1 /*-----------------------------------------------------------------
2 SDCCset.c - contains support routines for linked lists.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
30 /*-----------------------------------------------------------------*/
31 /* newSet - will allocate & return a new set entry */
32 /*-----------------------------------------------------------------*/
38 lp
= Safe_alloc (sizeof (set
));
39 lp
->item
= lp
->curr
= lp
->next
= NULL
;
44 /*-----------------------------------------------------------------*/
45 /* setFromSet - creates a list from another list; the order of */
46 /* elements in new list is reverted */
47 /*-----------------------------------------------------------------*/
49 setFromSet (const set
*lp
)
55 addSetHead (&lfl
, lp
->item
);
62 /*-----------------------------------------------------------------*/
63 /* setFromSet - creates a list from another list; the order of */
64 /* elements in retained */
65 /*-----------------------------------------------------------------*/
67 setFromSetNonRev (const set
*lp
)
73 addSet (&lfl
, lp
->item
);
80 /*-----------------------------------------------------------------*/
81 /* isSetsEqual - are the lists equal, they are equal if they have */
82 /* the same objects & the same number of objects */
83 /*-----------------------------------------------------------------*/
85 isSetsEqual (const set
*dest
, const set
*src
)
87 const set
*src1
= src
;
89 for (; dest
&& src
; dest
= dest
->next
, src
= src
->next
)
91 if (!isinSet (src1
, dest
->item
))
99 /*-----------------------------------------------------------------*/
100 /* isSetsEqualWith - are the lists equal, they are equal if they */
101 /* have the same objects & the same number of */
102 /* objects , compare function */
103 /*-----------------------------------------------------------------*/
105 isSetsEqualWith (set
* dest
, set
* src
, int (*cFunc
) (void *, void *))
109 for (; dest
&& src
; dest
= dest
->next
, src
= src
->next
)
111 if (!isinSetWith (src1
, dest
->item
, cFunc
))
119 /*-----------------------------------------------------------------*/
120 /* addSetIfnotP - adds to a linked list if not already present */
121 /*-----------------------------------------------------------------*/
123 addSetIfnotP (set
** list
, void *item
)
125 if (isinSet (*list
, item
))
128 addSetHead (list
, item
);
133 /*-----------------------------------------------------------------*/
134 /* addSetHead - add item to head of linked list */
135 /*-----------------------------------------------------------------*/
137 addSetHead (set
** list
, void *item
)
144 assert (lp
!= lp
->item
);
149 /*-----------------------------------------------------------------*/
150 /* addSet - add an item to a linear linked list */
151 /*-----------------------------------------------------------------*/
153 addSet (set
** list
, void *item
)
158 werror (E_INTERNAL_ERROR
,__FILE__
,__LINE__
, "Invalid set.");
160 /* item added to the tail of the list */
162 /* if the list is empty */
165 lp
= *list
= newSet ();
169 /* go to the end of the list */
170 for (lp
= *list
; lp
->next
; lp
= lp
->next
);
171 lp
= lp
->next
= newSet ();
174 werror (E_OUT_OF_MEM
,__FILE__
,__LINE__
, "Can't add to set.");
182 /*-----------------------------------------------------------------*/
183 /* deleteItemIf - will delete from set if cond function returns 1 */
184 /*-----------------------------------------------------------------*/
186 deleteItemIf (set
** sset
, int (*cond
) (void *, va_list),...)
194 * On the x86 va_list is just a pointer, so due to pass by value
195 * ap is not modified by the called function. On the PPC va_list
196 * is a pointer to a structure, so ap is modified. Re-init each time.
200 if ((*cond
) (sp
->item
, ap
))
202 deleteSetItem (sset
, sp
->item
);
212 /*-------------------------------------------------------------------*/
213 /* destructItemIf - will delete from set if cond function returns 1, */
214 /* upon deletion, item's destructor is also called */
215 /*-------------------------------------------------------------------*/
217 destructItemIf (set
** sset
, void (*destructor
)(void * item
), int (*cond
) (void *, va_list),...)
225 * On the x86 va_list is just a pointer, so due to pass by value
226 * ap is not modified by the called function. On the PPC va_list
227 * is a pointer to a structure, so ap is modified. Re-init each time.
231 if ((*cond
) (sp
->item
, ap
))
233 destructor (sp
->item
);
234 deleteSetItem (sset
, sp
->item
);
245 /*-----------------------------------------------------------------*/
246 /* deleteSetItem - will delete a given item from the list */
247 /*-----------------------------------------------------------------*/
249 deleteSetItem (set
**list
, void *item
)
253 /* if list is empty */
257 /* if this item is at the head of the list */
258 if ((*list
)->item
== item
)
261 *list
= (*list
)->next
;
266 /* find the item in the list */
267 for (lp
= *list
; lp
->next
; lp
= lp
->next
)
269 if (lp
->next
->item
== item
) /* the next one is it */
271 lp1
= lp
->next
; /* this one will need to be freed */
272 lp
->next
= lp
->next
->next
; /* take out of list */
278 /* could not find it */
281 /*-----------------------------------------------------------------*/
282 /* replaceSetItem - will replace a given item in the list */
283 /*-----------------------------------------------------------------*/
285 replaceSetItem (set
*list
, void *olditem
, void *newitem
)
287 /* find the item in the list */
288 for (; list
; list
= list
->next
)
289 if (list
->item
== olditem
)
291 list
->item
= newitem
;
296 /* could not find it */
299 /*-----------------------------------------------------------------*/
300 /* isinSet - the item is present in the linked list */
301 /*-----------------------------------------------------------------*/
303 isinSet (const set
*list
, const void *item
)
307 for (lp
= list
; lp
; lp
= lp
->next
)
308 if (lp
->item
== item
)
314 /*-----------------------------------------------------------------*/
315 /* isinSetWith - the item is present in the linked list */
316 /*-----------------------------------------------------------------*/
318 isinSetWith (set
* list
, void *item
, int (*cFunc
) (void *, void *))
322 for (lp
= list
; lp
; lp
= lp
->next
)
323 if ((*cFunc
) (lp
->item
, item
))
329 /*-----------------------------------------------------------------*/
330 /* mergeSets - append list to sset */
331 /*-----------------------------------------------------------------*/
333 mergeSets (set
**sset
, set
*list
)
343 for (lp
= *sset
; lp
->next
; lp
= lp
->next
)
349 /*-----------------------------------------------------------------*/
350 /* unionSets - will return the union of the two lists */
351 /*-----------------------------------------------------------------*/
353 unionSets (set
* list1
, set
* list2
, int throw)
358 /* If we were going to throw away the destination list */
359 /* anyway, save memory and time by using it as the */
360 /* starting point for the new list. */
361 if (throw == THROW_DEST
|| throw == THROW_BOTH
)
364 if (throw == THROW_BOTH
)
371 /* add all elements in the first list */
372 for (lp
= list1
; lp
; lp
= lp
->next
)
373 addSet (&un
, lp
->item
);
376 /* now for all those in list2 which does not */
377 /* already exist in the list add */
378 for (lp
= list2
; lp
; lp
= lp
->next
)
379 if (!isinSet (un
, lp
->item
))
380 addSet (&un
, lp
->item
);
385 setToNull ((void *) &list2
);
388 setToNull ((void *) &list1
);
391 setToNull ((void *) &list1
);
392 setToNull ((void *) &list2
);
398 /*-----------------------------------------------------------------*/
399 /* unionSetsWith - will return the union of the two lists */
400 /*-----------------------------------------------------------------*/
402 unionSetsWith (set
* list1
, set
* list2
, int (*cFunc
) (), int throw)
407 /* add all elements in the first list */
408 for (lp
= list1
; lp
; lp
= lp
->next
)
409 addSet (&un
, lp
->item
);
411 /* now for all those in list2 which does not */
412 /* already exist in the list add */
413 for (lp
= list2
; lp
; lp
= lp
->next
)
414 if (!isinSetWith (un
, lp
->item
, (int (*)(void *, void *)) cFunc
))
415 addSet (&un
, lp
->item
);
420 setToNull ((void *) &list2
);
423 setToNull ((void *) &list1
);
426 setToNull ((void *) &list1
);
427 setToNull ((void *) &list2
);
433 /*-----------------------------------------------------------------*/
434 /* intersectSets - returns list of items in common to two lists */
435 /*-----------------------------------------------------------------*/
437 intersectSets (set
* list1
, set
* list2
, int throw)
442 /* we can take any one of the lists and iterate over it */
443 for (lp
= list1
; lp
; lp
= lp
->next
)
444 if (isinSet (list2
, lp
->item
))
445 addSetHead (&in
, lp
->item
);
450 setToNull ((void *) &list2
);
453 setToNull ((void *) &list1
);
456 setToNull ((void *) &list1
);
457 setToNull ((void *) &list2
);
463 /*-----------------------------------------------------------------*/
464 /* intersectSetsWith - returns list of items in common to two */
466 /*-----------------------------------------------------------------*/
468 intersectSetsWith (set
* list1
, set
* list2
,
469 int (*cFunc
) (void *, void *), int throw)
474 /* we can take any one of the lists and iterate over it */
475 for (lp
= list1
; lp
; lp
= lp
->next
)
476 if (isinSetWith (list2
, lp
->item
, cFunc
))
477 addSetHead (&in
, lp
->item
);
482 setToNull ((void *) &list2
);
485 setToNull ((void *) &list1
);
488 setToNull ((void *) &list1
);
489 setToNull ((void *) &list2
);
495 /*-----------------------------------------------------------------*/
496 /* elementsInSet - elements count of a set */
497 /*-----------------------------------------------------------------*/
499 elementsInSet (const set
* s
)
513 /*-----------------------------------------------------------------*/
514 /* indexSet - returns the i'th item in set */
515 /*-----------------------------------------------------------------*/
517 indexSet (set
* s
, int index
)
521 while (loop
&& index
--)
526 return loop
? loop
->item
: NULL
;
530 /*-----------------------------------------------------------------*/
531 /* reverseSet - reverse the order of the items of a set */
532 /*-----------------------------------------------------------------*/
550 /*-----------------------------------------------------------------*/
551 /* subtractFromSet - take away from set1 elements of set2 */
552 /*-----------------------------------------------------------------*/
554 subtractFromSet (set
* left
, set
* right
, int throw)
556 set
*result
= setFromSet (left
);
561 for (loop
= right
; loop
; loop
= loop
->next
)
562 if (isinSet (result
, loop
->item
))
563 deleteSetItem (&result
, loop
->item
);
569 setToNull ((void *) &right
);
572 setToNull ((void *) &left
);
575 setToNull ((void *) &left
);
576 setToNull ((void *) &right
);
583 /*-----------------------------------------------------------------*/
584 /* applyToSet - will call the supplied function with each item */
585 /*-----------------------------------------------------------------*/
587 applyToSet (set
* list
, int (*somefunc
) (void *, va_list),...)
593 for (lp
= list
; lp
; lp
= lp
->next
)
595 va_start (ap
, somefunc
);
596 rvalue
+= (*somefunc
) (lp
->item
, ap
);
602 /*-----------------------------------------------------------------*/
603 /* applyToSetFTrue - will call the supplied function with each */
604 /* item until list is exhausted or a true is */
606 /*-----------------------------------------------------------------*/
608 applyToSetFTrue (set
* list
, int (*somefunc
) (void *, va_list),...)
614 for (lp
= list
; lp
; lp
= lp
->next
)
616 va_start (ap
, somefunc
);
617 rvalue
+= (*somefunc
) (lp
->item
, ap
);
625 /*-----------------------------------------------------------------*/
626 /* peekSet - will return the first element of the set */
627 /*-----------------------------------------------------------------*/
629 peekSet (const set
*sp
)
637 /*-----------------------------------------------------------------*/
638 /* setFirstItem - gets the first item in the set, begins iteration */
639 /*-----------------------------------------------------------------*/
641 setFirstItem (set
*sset
)
651 /*-----------------------------------------------------------------*/
652 /* setNextItem - gets the next item, changes the iteration */
653 /*-----------------------------------------------------------------*/
655 setNextItem (set
* sset
)
657 if (sset
&& sset
->curr
)
659 sset
->curr
= sset
->curr
->next
;
661 return sset
->curr
->item
;
666 /*-----------------------------------------------------------------*/
667 /* getSet - will delete & return the first item from the set */
668 /*-----------------------------------------------------------------*/
675 /* if list is empty then we cannot delete */
677 return (void *) NULL
;
679 /* find the item in the list */
681 item
= lp
->item
; /* save the item */
687 /*-----------------------------------------------------------------*/
688 /* setToNull - will throw away the entire list */
689 /*-----------------------------------------------------------------*/
691 setToNull (void **item
)
702 /*-----------------------------------------------------------------*/
703 /* deleteSet - will throw away the entire list */
704 /* note - setToNull doesn't actually throw away the whole list. */
705 /* Instead it only throws away the first item. */
706 /*-----------------------------------------------------------------*/