summaryrefslogtreecommitdiff
path: root/src/SDCCset.c
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /src/SDCCset.c
downloadsdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'src/SDCCset.c')
-rw-r--r--src/SDCCset.c728
1 files changed, 728 insertions, 0 deletions
diff --git a/src/SDCCset.c b/src/SDCCset.c
new file mode 100644
index 0000000..e59dfca
--- /dev/null
+++ b/src/SDCCset.c
@@ -0,0 +1,728 @@
+/*-----------------------------------------------------------------
+ SDCCset.c - contains support routines for doubly linked lists.
+
+ Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include "newalloc.h"
+#include "SDCCerr.h"
+#include "SDCCset.h"
+
+/*-----------------------------------------------------------------*/
+/* newSet - will allocate & return a new set entry */
+/*-----------------------------------------------------------------*/
+set *
+newSet (void)
+{
+ set *lp;
+
+ lp = Safe_alloc (sizeof (set));
+ lp->item = lp->curr = lp->next = NULL;
+ return lp;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* setFromSet - creates a list from another list; the order of */
+/* elements in new list is reverted */
+/*-----------------------------------------------------------------*/
+set *
+setFromSet (const set *lp)
+{
+ set *lfl = NULL;
+
+ while (lp)
+ {
+ addSetHead (&lfl, lp->item);
+ lp = lp->next;
+ }
+
+ return lfl;
+}
+
+/*-----------------------------------------------------------------*/
+/* setFromSet - creates a list from another list; the order of */
+/* elements in retained */
+/*-----------------------------------------------------------------*/
+set *
+setFromSetNonRev (const set *lp)
+{
+ set *lfl = NULL;
+
+ while (lp)
+ {
+ addSet (&lfl, lp->item);
+ lp = lp->next;
+ }
+
+ return lfl;
+}
+
+/*-----------------------------------------------------------------*/
+/* isSetsEqual - are the lists equal, they are equal if they have */
+/* the same objects & the same number of objects */
+/*-----------------------------------------------------------------*/
+int
+isSetsEqual (const set *dest, const set *src)
+{
+ const set *src1 = src;
+
+ for (; dest && src; dest = dest->next, src = src->next)
+ {
+ if (!isinSet (src1, dest->item))
+ return 0;
+ }
+ if (!dest && !src)
+ return 1;
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* isSetsEqualWith - are the lists equal, they are equal if they */
+/* have the same objects & the same number of */
+/* objects , compare function */
+/*-----------------------------------------------------------------*/
+int
+isSetsEqualWith (set * dest, set * src, int (*cFunc) (void *, void *))
+{
+ set *src1 = src;
+
+ for (; dest && src; dest = dest->next, src = src->next)
+ {
+ if (!isinSetWith (src1, dest->item, cFunc))
+ return 0;
+ }
+ if (!dest && !src)
+ return 1;
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* addSetIfnotP - adds to a linked list if not already present */
+/*-----------------------------------------------------------------*/
+void *
+addSetIfnotP (set ** list, void *item)
+{
+ if (isinSet (*list, item))
+ return item;
+
+ addSetHead (list, item);
+
+ return item;
+}
+
+/*-----------------------------------------------------------------*/
+/* addSetHead - add item to head of linked list */
+/*-----------------------------------------------------------------*/
+void *
+addSetHead (set ** list, void *item)
+{
+ set *lp = newSet ();
+
+ lp->item = item;
+ lp->next = *list;
+
+ assert (lp != lp->item);
+ *list = lp;
+ return item;
+}
+
+/*-----------------------------------------------------------------*/
+/* addSet - add an item to a linear linked list */
+/*-----------------------------------------------------------------*/
+void *
+addSet (set ** list, void *item)
+{
+ set *lp;
+
+ if (!list)
+ werror (E_INTERNAL_ERROR,__FILE__,__LINE__, "Invalid set.");
+
+ /* item added to the tail of the list */
+
+ /* if the list is empty */
+ if (*list == NULL)
+ {
+ lp = *list = newSet ();
+ }
+ else
+ {
+ /* go to the end of the list */
+ for (lp = *list; lp->next; lp = lp->next);
+ lp = lp->next = newSet ();
+ }
+ if (!list)
+ werror (E_OUT_OF_MEM,__FILE__,__LINE__, "Can't add to set.");
+
+ /* lp now all set */
+ lp->item = item;
+
+ return item;
+}
+
+/*-----------------------------------------------------------------*/
+/* deleteItemIf - will delete from set if cond function returns 1 */
+/*-----------------------------------------------------------------*/
+void
+deleteItemIf (set ** sset, int (*cond) (void *, va_list),...)
+{
+ set *sp = *sset;
+ va_list ap;
+
+ while (sp)
+ {
+ /*
+ * On the x86 va_list is just a pointer, so due to pass by value
+ * ap is not mofified by the called function. On the PPC va_list
+ * is a pointer to a structure, so ap is modified. Re-init each time.
+ */
+ va_start (ap, cond);
+
+ if ((*cond) (sp->item, ap))
+ {
+ deleteSetItem (sset, sp->item);
+ sp = *sset;
+ continue;
+ }
+
+ va_end(ap);
+ sp = sp->next;
+ }
+}
+
+/*-------------------------------------------------------------------*/
+/* destructItemIf - will delete from set if cond function returns 1, */
+/* upon deletion, item's destructor is also called */
+/*-------------------------------------------------------------------*/
+void
+destructItemIf (set ** sset, void (*destructor)(void * item), int (*cond) (void *, va_list),...)
+{
+ set *sp = *sset;
+ va_list ap;
+
+ while (sp)
+ {
+ /*
+ * On the x86 va_list is just a pointer, so due to pass by value
+ * ap is not mofified by the called function. On the PPC va_list
+ * is a pointer to a structure, so ap is modified. Re-init each time.
+ */
+ va_start (ap, cond);
+
+ if ((*cond) (sp->item, ap))
+ {
+ destructor (sp->item);
+ deleteSetItem (sset, sp->item);
+ sp = *sset;
+ continue;
+ }
+
+ va_end(ap);
+ sp = sp->next;
+ }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* deleteSetItem - will delete a given item from the list */
+/*-----------------------------------------------------------------*/
+void
+deleteSetItem (set **list, void *item)
+{
+ set *lp, *lp1;
+
+ /* if list is empty */
+ if (*list == NULL)
+ return;
+
+ /* if this item is at the head of the list */
+ if ((*list)->item == item)
+ {
+ lp = *list;
+ *list = (*list)->next;
+ Safe_free (lp);
+ return;
+ }
+
+ /* find the item in the list */
+ for (lp = *list; lp->next; lp = lp->next)
+ {
+ if (lp->next->item == item) /* the next one is it */
+ {
+ lp1 = lp->next; /* this one will need to be freed */
+ lp->next = lp->next->next; /* take out of list */
+ Safe_free (lp1);
+ return;
+ }
+ }
+
+ /* could not find it */
+}
+
+/*-----------------------------------------------------------------*/
+/* replaceSetItem - will replace a given item in the list */
+/*-----------------------------------------------------------------*/
+void
+replaceSetItem (set *list, void *olditem, void *newitem)
+{
+ /* find the item in the list */
+ for (; list; list = list->next)
+ if (list->item == olditem)
+ {
+ list->item = newitem;
+ return;
+ }
+
+
+ /* could not find it */
+}
+
+/*-----------------------------------------------------------------*/
+/* isinSet - the item is present in the linked list */
+/*-----------------------------------------------------------------*/
+int
+isinSet (const set *list, const void *item)
+{
+ const set *lp;
+
+ for (lp = list; lp; lp = lp->next)
+ if (lp->item == item)
+ return 1;
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* isinSetWith - the item is present in the linked list */
+/*-----------------------------------------------------------------*/
+int
+isinSetWith (set * list, void *item, int (*cFunc) (void *, void *))
+{
+ set *lp;
+
+ for (lp = list; lp; lp = lp->next)
+ if ((*cFunc) (lp->item, item))
+ return 1;
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* mergeSets - append list to sset */
+/*-----------------------------------------------------------------*/
+void
+mergeSets (set **sset, set *list)
+{
+ if (*sset == NULL)
+ {
+ *sset = list;
+ }
+ else
+ {
+ set *lp;
+
+ for (lp = *sset; lp->next; lp = lp->next)
+ ;
+ lp->next = list;
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* unionSets - will return the union of the two lists */
+/*-----------------------------------------------------------------*/
+set *
+unionSets (set * list1, set * list2, int throw)
+{
+ set *un = NULL;
+ set *lp;
+
+ /* If we were going to throw away the destination list */
+ /* anyway, save memory and time by using it as the */
+ /* starting point for the new list. */
+ if (throw == THROW_DEST || throw == THROW_BOTH)
+ {
+ un = list1;
+ if (throw == THROW_BOTH)
+ throw = THROW_SRC;
+ else
+ throw = THROW_NONE;
+ }
+ else
+ {
+ /* add all elements in the first list */
+ for (lp = list1; lp; lp = lp->next)
+ addSet (&un, lp->item);
+ }
+
+ /* now for all those in list2 which does not */
+ /* already exist in the list add */
+ for (lp = list2; lp; lp = lp->next)
+ if (!isinSet (un, lp->item))
+ addSet (&un, lp->item);
+
+ switch (throw)
+ {
+ case THROW_SRC:
+ setToNull ((void *) &list2);
+ break;
+ case THROW_DEST:
+ setToNull ((void *) &list1);
+ break;
+ case THROW_BOTH:
+ setToNull ((void *) &list1);
+ setToNull ((void *) &list2);
+ }
+
+ return un;
+}
+
+/*-----------------------------------------------------------------*/
+/* unionSetsWith - will return the union of the two lists */
+/*-----------------------------------------------------------------*/
+set *
+unionSetsWith (set * list1, set * list2, int (*cFunc) (), int throw)
+{
+ set *un = NULL;
+ set *lp;
+
+ /* add all elements in the first list */
+ for (lp = list1; lp; lp = lp->next)
+ addSet (&un, lp->item);
+
+ /* now for all those in list2 which does not */
+ /* already exist in the list add */
+ for (lp = list2; lp; lp = lp->next)
+ if (!isinSetWith (un, lp->item, (int (*)(void *, void *)) cFunc))
+ addSet (&un, lp->item);
+
+ switch (throw)
+ {
+ case THROW_SRC:
+ setToNull ((void *) &list2);
+ break;
+ case THROW_DEST:
+ setToNull ((void *) &list1);
+ break;
+ case THROW_BOTH:
+ setToNull ((void *) &list1);
+ setToNull ((void *) &list2);
+ }
+
+ return un;
+}
+
+/*-----------------------------------------------------------------*/
+/* intersectSets - returns list of items in common to two lists */
+/*-----------------------------------------------------------------*/
+set *
+intersectSets (set * list1, set * list2, int throw)
+{
+ set *in = NULL;
+ set *lp;
+
+ /* we can take any one of the lists and iterate over it */
+ for (lp = list1; lp; lp = lp->next)
+ if (isinSet (list2, lp->item))
+ addSetHead (&in, lp->item);
+
+ switch (throw)
+ {
+ case THROW_SRC:
+ setToNull ((void *) &list2);
+ break;
+ case THROW_DEST:
+ setToNull ((void *) &list1);
+ break;
+ case THROW_BOTH:
+ setToNull ((void *) &list1);
+ setToNull ((void *) &list2);
+ }
+
+ return in;
+}
+
+/*-----------------------------------------------------------------*/
+/* intersectSetsWith - returns list of items in common to two */
+/* lists */
+/*-----------------------------------------------------------------*/
+set *
+intersectSetsWith (set * list1, set * list2,
+ int (*cFunc) (void *, void *), int throw)
+{
+ set *in = NULL;
+ set *lp;
+
+ /* we can take any one of the lists and iterate over it */
+ for (lp = list1; lp; lp = lp->next)
+ if (isinSetWith (list2, lp->item, cFunc))
+ addSetHead (&in, lp->item);
+
+ switch (throw)
+ {
+ case THROW_SRC:
+ setToNull ((void *) &list2);
+ break;
+ case THROW_DEST:
+ setToNull ((void *) &list1);
+ break;
+ case THROW_BOTH:
+ setToNull ((void *) &list1);
+ setToNull ((void *) &list2);
+ }
+
+ return in;
+}
+
+/*-----------------------------------------------------------------*/
+/* elementsInSet - elements count of a set */
+/*-----------------------------------------------------------------*/
+int
+elementsInSet (const set * s)
+{
+ const set *loop = s;
+ int count = 0;
+
+ while (loop)
+ {
+ count++;
+ loop = loop->next;
+ }
+
+ return count;
+}
+
+/*-----------------------------------------------------------------*/
+/* indexSet - returns the i'th item in set */
+/*-----------------------------------------------------------------*/
+void *
+indexSet (set * s, int index)
+{
+ set *loop = s;
+
+ while (loop && index--)
+ {
+ loop = loop->next;
+ }
+
+ return loop ? loop->item : NULL;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* reverseSet - reverse the order of the items of a set */
+/*-----------------------------------------------------------------*/
+set *
+reverseSet (set * s)
+{
+ set *t = NULL;
+ set *u = NULL;
+
+ while(s->next)
+ {
+ t = s->next;
+ s->next = u;
+ u = s;
+ s = t;
+ }
+ s->next = u;
+ return s;
+}
+
+/*-----------------------------------------------------------------*/
+/* subtractFromSet - take away from set1 elements of set2 */
+/*-----------------------------------------------------------------*/
+set *
+subtractFromSet (set * left, set * right, int throw)
+{
+ set *result = setFromSet (left);
+ set *loop;
+
+ if (right)
+ {
+ for (loop = right; loop; loop = loop->next)
+ if (isinSet (result, loop->item))
+ deleteSetItem (&result, loop->item);
+ }
+
+ switch (throw)
+ {
+ case THROW_SRC:
+ setToNull ((void *) &right);
+ break;
+ case THROW_DEST:
+ setToNull ((void *) &left);
+ break;
+ case THROW_BOTH:
+ setToNull ((void *) &left);
+ setToNull ((void *) &right);
+ break;
+ }
+
+ return result;
+}
+
+/*-----------------------------------------------------------------*/
+/* applyToSet - will call the supplied function with each item */
+/*-----------------------------------------------------------------*/
+int
+applyToSet (set * list, int (*somefunc) (void *, va_list),...)
+{
+ set *lp;
+ va_list ap;
+ int rvalue = 0;
+
+ for (lp = list; lp; lp = lp->next)
+ {
+ va_start (ap, somefunc);
+ rvalue += (*somefunc) (lp->item, ap);
+ va_end (ap);
+ }
+ return rvalue;
+}
+
+/*-----------------------------------------------------------------*/
+/* applyToSetFTrue - will call the supplied function with each */
+/* item until list is exhausted or a true is */
+/* returned */
+/*-----------------------------------------------------------------*/
+int
+applyToSetFTrue (set * list, int (*somefunc) (void *, va_list),...)
+{
+ set *lp;
+ va_list ap;
+ int rvalue = 0;
+
+ for (lp = list; lp; lp = lp->next)
+ {
+ va_start (ap, somefunc);
+ rvalue += (*somefunc) (lp->item, ap);
+ va_end (ap);
+ if (rvalue)
+ break;
+ }
+ return rvalue;
+}
+
+/*-----------------------------------------------------------------*/
+/* peekSet - will return the first element of the set */
+/*-----------------------------------------------------------------*/
+void *
+peekSet (const set *sp)
+{
+ if (!sp)
+ return NULL;
+
+ return sp->item;
+}
+
+/*-----------------------------------------------------------------*/
+/* setFirstItem - gets the first item in the set, begins iteration */
+/*-----------------------------------------------------------------*/
+void *
+setFirstItem (set *sset)
+{
+ if (sset)
+ {
+ sset->curr = sset;
+ return sset->item;
+ }
+
+ return NULL;
+}
+/*-----------------------------------------------------------------*/
+/* setNextItem - gets the next item, changes the iteration */
+/*-----------------------------------------------------------------*/
+void *
+setNextItem (set * sset)
+{
+ if (sset && sset->curr)
+ {
+ sset->curr = sset->curr->next;
+ if (sset->curr)
+ return sset->curr->item;
+ }
+ return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* getSet - will delete & return the first item from the set */
+/*-----------------------------------------------------------------*/
+void *
+getSet (set ** list)
+{
+ set *lp;
+ void *item;
+
+ /* if list is empty then we cannot delete */
+ if (*list == NULL)
+ return (void *) NULL;
+
+ /* find the item in the list */
+ lp = *list;
+ item = lp->item; /* save the item */
+
+ *list = lp->next;
+ return item;
+}
+
+/*-----------------------------------------------------------------*/
+/* setToNull - will throw away the entire list */
+/*-----------------------------------------------------------------*/
+void
+setToNull (void **item)
+{
+ if (!item)
+ return;
+
+ if (!*item)
+ return;
+ Safe_free (*item);
+ *item = NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* deleteSet - will throw away the entire list */
+/* note - setToNull doesn't actually throw away the whole list. */
+/* Instead it only throws away the first item. */
+/*-----------------------------------------------------------------*/
+void
+deleteSet (set **s)
+{
+ set *curr;
+ set *next;
+
+ if(!s || !*s)
+ return;
+
+ curr = *s;
+ next = curr->next;
+ while (next)
+ {
+ Safe_free (curr);
+ curr = next;
+ next = next->next;
+ }
+
+ Safe_free (curr);
+
+ *s = NULL;
+}